Skip to content

Commit 75d367a

Browse files
committed
C++: Add ad-hoc SAMATE Juliet test cases (that were previously internal). Directory structures cleaned up in a few places.
1 parent dccdc3b commit 75d367a

File tree

69 files changed

+2403
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2403
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/**
2+
* This test case is closely based on CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp
3+
* from the SAMATE test suite.
4+
*/
5+
6+
#define NULL (0)
7+
8+
typedef size_t time_t;
9+
time_t time(time_t *timer);
10+
void srand(unsigned int seed);
11+
12+
typedef struct {} FILE;
13+
extern FILE *stdin;
14+
FILE *fopen(const char *filename, const char *mode);
15+
int fclose(FILE *stream);
16+
#define FILENAME_MAX (4096)
17+
18+
typedef unsigned long size_t;
19+
size_t strlen(const char *s);
20+
char *strcat(char *s1, const char *s2);
21+
char *fgets(char *s, int n, FILE *stream);
22+
23+
int globalReturnsTrue()
24+
{
25+
return 1;
26+
}
27+
28+
int globalReturnsFalse()
29+
{
30+
return 0;
31+
}
32+
33+
void printLine(const char *str);
34+
35+
#define BASEPATH "c:\\temp\\"
36+
#define FOPEN fopen
37+
38+
namespace CWE23_Relative_Path_Traversal__char_console_fopen_11
39+
{
40+
41+
void bad()
42+
{
43+
char * data;
44+
char dataBuffer[FILENAME_MAX] = BASEPATH;
45+
data = dataBuffer;
46+
if(globalReturnsTrue())
47+
{
48+
{
49+
/* Read input from the console */
50+
size_t dataLen = strlen(data);
51+
/* if there is room in data, read into it from the console */
52+
if (FILENAME_MAX-dataLen > 1)
53+
{
54+
/* POTENTIAL FLAW: Read data from the console */
55+
if (fgets(data+dataLen, (int)(FILENAME_MAX-dataLen), stdin) != NULL)
56+
{
57+
/* The next few lines remove the carriage return from the string that is
58+
* inserted by fgets() */
59+
dataLen = strlen(data);
60+
if (dataLen > 0 && data[dataLen-1] == '\n')
61+
{
62+
data[dataLen-1] = '\0';
63+
}
64+
}
65+
else
66+
{
67+
printLine("fgets() failed");
68+
/* Restore NUL terminator if fgets fails */
69+
data[dataLen] = '\0';
70+
}
71+
}
72+
}
73+
}
74+
{
75+
FILE *pFile = NULL;
76+
/* POTENTIAL FLAW: Possibly opening a file without validating the file name or path */
77+
pFile = FOPEN(data, "wb+");
78+
if (pFile != NULL)
79+
{
80+
fclose(pFile);
81+
}
82+
}
83+
}
84+
85+
/* goodG2B1() - use goodsource and badsink by changing the globalReturnsTrue() to globalReturnsFalse() */
86+
static void goodG2B1()
87+
{
88+
char * data;
89+
char dataBuffer[FILENAME_MAX] = BASEPATH;
90+
data = dataBuffer;
91+
if(globalReturnsFalse())
92+
{
93+
/* INCIDENTAL: CWE 561 Dead Code, the code below will never run */
94+
printLine("Benign, fixed string");
95+
}
96+
else
97+
{
98+
/* FIX: Use a fixed file name */
99+
strcat(data, "file.txt");
100+
}
101+
{
102+
FILE *pFile = NULL;
103+
/* POTENTIAL FLAW: Possibly opening a file without validating the file name or path */
104+
pFile = FOPEN(data, "wb+");
105+
if (pFile != NULL)
106+
{
107+
fclose(pFile);
108+
}
109+
}
110+
}
111+
112+
/* goodG2B2() - use goodsource and badsink by reversing the blocks in the if statement */
113+
static void goodG2B2()
114+
{
115+
char * data;
116+
char dataBuffer[FILENAME_MAX] = BASEPATH;
117+
data = dataBuffer;
118+
if(globalReturnsTrue())
119+
{
120+
/* FIX: Use a fixed file name */
121+
strcat(data, "file.txt");
122+
}
123+
{
124+
FILE *pFile = NULL;
125+
/* POTENTIAL FLAW: Possibly opening a file without validating the file name or path */
126+
pFile = FOPEN(data, "wb+");
127+
if (pFile != NULL)
128+
{
129+
fclose(pFile);
130+
}
131+
}
132+
}
133+
134+
void good()
135+
{
136+
goodG2B1();
137+
goodG2B2();
138+
}
139+
140+
} /* close namespace */
141+
142+
/* Below is the main(). It is only used when building this testcase on
143+
its own for testing or for building a binary to use in testing binary
144+
analysis tools. It is not used when compiling all the testcases as one
145+
application, which is how source code analysis tools are tested. */
146+
147+
using namespace CWE23_Relative_Path_Traversal__char_console_fopen_11; /* so that we can use good and bad easily */
148+
149+
int main(int argc, char * argv[])
150+
{
151+
/* seed randomness */
152+
srand( (unsigned)time(NULL) );
153+
#ifndef OMITGOOD
154+
printLine("Calling good()...");
155+
good();
156+
printLine("Finished good()");
157+
#endif /* OMITGOOD */
158+
#ifndef OMITBAD
159+
printLine("Calling bad()...");
160+
bad();
161+
printLine("Finished bad()");
162+
#endif /* OMITBAD */
163+
return 0;
164+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
edges
2+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... |
3+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data |
4+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection |
5+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... |
6+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data |
7+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection |
8+
nodes
9+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | semmle.label | ... + ... |
10+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | semmle.label | fgets output argument |
11+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... | semmle.label | (const char *)... |
12+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... | semmle.label | (const char *)... |
13+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | semmle.label | data |
14+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | semmle.label | data indirection |
15+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | semmle.label | data indirection |
16+
#select
17+
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | This argument to a file access function is derived from $@ and then passed to fopen(filename) | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | user input (fgets) |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE/CWE-022/TaintedPath.ql
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| tests.cpp:55:16:55:19 | data | This argument to an OS command is derived from $@ and then passed to system(string) | tests.cpp:35:34:35:39 | call to getenv | user input (getenv) |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE/CWE-078/ExecTainted.ql
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//semmle-extractor-options: --edg --target --edg win64
2+
3+
// A selection of tests from the samate framework for rule CWE-78.
4+
5+
// library types, functions etc
6+
#define NULL (0)
7+
typedef unsigned long size_t;
8+
size_t strlen(const char *s);
9+
char *strncat(char *s1, const char *s2, size_t n);n);
10+
char *getenv(const char *name);
11+
int system(const char *string);
12+
void exit(int status);
13+
14+
#define FULL_COMMAND "dir "
15+
#define ENV_VARIABLE "ADD"
16+
#define GETENV getenv
17+
#define SYSTEM system
18+
19+
void printLine(const char *str);
20+
21+
// ----------
22+
23+
/* The static variable below is used to drive control flow in the source function */
24+
static int badStatic = 0;
25+
26+
static char * badSource(char * data)
27+
{
28+
if(badStatic)
29+
{
30+
{
31+
/* Append input from an environment variable to data */
32+
size_t dataLen = strlen(data);
33+
char * environment = GETENV(ENV_VARIABLE);
34+
/* If there is data in the environment variable */
35+
if (environment != NULL)
36+
{
37+
/* POTENTIAL FLAW: Read data from an environment variable */
38+
strncat(data+dataLen, environment, 100-dataLen-1);
39+
}
40+
}
41+
}
42+
return data;
43+
}
44+
45+
void CWE78_OS_Command_Injection__char_environment_system_21_bad()
46+
{
47+
char * data;
48+
char data_buf[100] = FULL_COMMAND;
49+
data = data_buf;
50+
badStatic = 1; /* true */
51+
data = badSource(data);
52+
/* POTENTIAL FLAW: Execute command in data possibly leading to command injection [NOT DETECTED] */
53+
if (SYSTEM(data) != 0)
54+
{
55+
printLine("command execution failed!");
56+
exit(1);
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
edges
2+
| test.cpp:35:73:35:76 | *data | test.cpp:41:32:41:35 | (LPCSTR)... |
3+
| test.cpp:35:73:35:76 | *data | test.cpp:41:32:41:35 | data |
4+
| test.cpp:35:73:35:76 | *data | test.cpp:41:32:41:35 | data indirection |
5+
| test.cpp:35:73:35:76 | data | test.cpp:41:32:41:35 | (LPCSTR)... |
6+
| test.cpp:35:73:35:76 | data | test.cpp:41:32:41:35 | data |
7+
| test.cpp:35:73:35:76 | data | test.cpp:41:32:41:35 | data |
8+
| test.cpp:35:73:35:76 | data | test.cpp:41:32:41:35 | data indirection |
9+
| test.cpp:62:30:62:35 | call to getenv | test.cpp:71:17:71:22 | data |
10+
| test.cpp:62:30:62:35 | call to getenv | test.cpp:71:17:71:22 | data |
11+
| test.cpp:62:30:62:35 | call to getenv | test.cpp:71:24:71:27 | data indirection |
12+
| test.cpp:62:30:62:35 | call to getenv | test.cpp:71:24:71:27 | data indirection |
13+
| test.cpp:71:17:71:22 | data | test.cpp:35:73:35:76 | data |
14+
| test.cpp:71:24:71:27 | data indirection | test.cpp:35:73:35:76 | *data |
15+
nodes
16+
| test.cpp:35:73:35:76 | *data | semmle.label | *data |
17+
| test.cpp:35:73:35:76 | data | semmle.label | data |
18+
| test.cpp:41:32:41:35 | (LPCSTR)... | semmle.label | (LPCSTR)... |
19+
| test.cpp:41:32:41:35 | (LPCSTR)... | semmle.label | (LPCSTR)... |
20+
| test.cpp:41:32:41:35 | data | semmle.label | data |
21+
| test.cpp:41:32:41:35 | data | semmle.label | data |
22+
| test.cpp:41:32:41:35 | data | semmle.label | data |
23+
| test.cpp:41:32:41:35 | data indirection | semmle.label | data indirection |
24+
| test.cpp:41:32:41:35 | data indirection | semmle.label | data indirection |
25+
| test.cpp:62:30:62:35 | call to getenv | semmle.label | call to getenv |
26+
| test.cpp:62:30:62:35 | call to getenv | semmle.label | call to getenv |
27+
| test.cpp:71:17:71:22 | data | semmle.label | data |
28+
| test.cpp:71:24:71:27 | data indirection | semmle.label | data indirection |
29+
#select
30+
| test.cpp:41:32:41:35 | data | test.cpp:62:30:62:35 | call to getenv | test.cpp:41:32:41:35 | data | The value of this argument may come from $@ and is being passed to LoadLibraryA | test.cpp:62:30:62:35 | call to getenv | call to getenv |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE/CWE-114/UncontrolledProcessOperation.ql

0 commit comments

Comments
 (0)