mirror of
https://github.com/github/codeql.git
synced 2026-05-04 21:25:44 +02:00
Merge pull request #6150 from geoffw0/toctou
C++: Tests for cpp/toctou-race-condition
This commit is contained in:
@@ -1,3 +1,14 @@
|
||||
| test2.cpp:39:7:39:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:39:13:39:16 | path | filename | test2.cpp:34:6:34:10 | call to fopen | checked |
|
||||
| test2.cpp:52:7:52:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:52:13:52:16 | path | filename | test2.cpp:52:7:52:11 | call to fopen | checked |
|
||||
| test2.cpp:69:7:69:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:69:13:69:16 | path | filename | test2.cpp:67:6:67:9 | call to stat | checked |
|
||||
| test2.cpp:98:7:98:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:98:13:98:16 | path | filename | test2.cpp:96:15:96:17 | foo | checked |
|
||||
| test2.cpp:157:7:157:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:157:12:157:15 | path | filename | test2.cpp:155:6:155:9 | call to stat | checked |
|
||||
| test2.cpp:170:7:170:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:170:12:170:15 | path | filename | test2.cpp:168:6:168:10 | call to lstat | checked |
|
||||
| test2.cpp:245:3:245:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:245:9:245:12 | path | filename | test2.cpp:238:6:238:10 | call to fopen | checked |
|
||||
| test2.cpp:255:3:255:8 | call to remove | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:255:10:255:14 | path1 | filename | test2.cpp:253:6:253:11 | call to rename | checked |
|
||||
| test2.cpp:277:7:277:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:277:13:277:16 | path | filename | test2.cpp:275:6:275:11 | call to access | checked |
|
||||
| test2.cpp:303:7:303:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:303:13:303:16 | path | filename | test2.cpp:301:7:301:12 | call to access | checked |
|
||||
| test2.cpp:317:7:317:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:317:13:317:16 | path | filename | test2.cpp:313:6:313:11 | call to access | checked |
|
||||
| test.cpp:21:3:21:8 | call to remove | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test.cpp:21:10:21:14 | file1 | filename | test.cpp:19:7:19:12 | call to rename | checked |
|
||||
| test.cpp:35:3:35:8 | call to remove | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test.cpp:35:10:35:14 | file1 | filename | test.cpp:32:7:32:12 | call to rename | checked |
|
||||
| test.cpp:49:3:49:8 | call to remove | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test.cpp:49:10:49:14 | file1 | filename | test.cpp:47:7:47:12 | call to rename | checked |
|
||||
|
||||
@@ -18,7 +18,7 @@ void test1()
|
||||
create(file1);
|
||||
if (!rename(file1, file2))
|
||||
{
|
||||
remove(file1); // BAD
|
||||
remove(file1); // DUBIOUS (bad but perhaps not exploitable) [REPORTED]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,6 @@ void test3()
|
||||
create(file1);
|
||||
if (!rename(file1, file2))
|
||||
{
|
||||
remove(file1); // BAD
|
||||
remove(file1); // DUBIOUS (bad but perhaps not exploitable) [REPORTED]
|
||||
}
|
||||
}
|
||||
|
||||
333
cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp
Normal file
333
cpp/ql/test/query-tests/Security/CWE/CWE-367/semmle/test2.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
// More test cases. Some of these are inspired by real-world cases, others are synthetic or variations.
|
||||
|
||||
#define NULL 0
|
||||
|
||||
typedef struct {} FILE;
|
||||
typedef struct {
|
||||
int foo;
|
||||
} stat_data;
|
||||
|
||||
FILE *fopen(const char *filename, const char *mode);
|
||||
int fclose(FILE *stream);
|
||||
|
||||
int open(const char *filename, int arg);
|
||||
int creat(const char *filename, int arg);
|
||||
int openat(int dir, const char *filename, int arg);
|
||||
int close(int file);
|
||||
|
||||
bool stat(const char *path, stat_data *buf);
|
||||
bool fstat(int file, stat_data *buf);
|
||||
bool lstat(const char *path, stat_data *buf);
|
||||
bool fstatat(int dir, const char *path, stat_data *buf);
|
||||
void chmod(const char *path, int setting);
|
||||
int rename(const char *from, const char *to);
|
||||
bool remove(const char *path);
|
||||
|
||||
bool access(const char *path);
|
||||
|
||||
// --- open -> open ---
|
||||
|
||||
void test1_1(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
f = fopen(path, "r");
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
// retry
|
||||
f = fopen(path, "r"); // GOOD (this is just trying again) [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test1_2(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
// try until we succeed
|
||||
while (f == NULL)
|
||||
{
|
||||
f = fopen(path, "r"); // GOOD (this is just trying again) [FALSE POSITIVE]
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
// --- stat -> open ---
|
||||
|
||||
void test2_1(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
stat_data buf;
|
||||
|
||||
if (stat(path, &buf))
|
||||
{
|
||||
f = fopen(path, "r"); // BAD
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test2_2(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
stat_data buf;
|
||||
|
||||
stat(path, &buf);
|
||||
if (buf.foo > 0)
|
||||
{
|
||||
f = fopen(path, "r"); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test2_3(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
stat_data buf;
|
||||
stat_data *buf_ptr = &buf;
|
||||
|
||||
stat(path, buf_ptr);
|
||||
if (buf_ptr->foo > 0)
|
||||
{
|
||||
f = fopen(path, "r"); // BAD
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
bool stat_condition(const stat_data *buf);
|
||||
bool other_condition();
|
||||
|
||||
void test2_4(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
stat_data buf;
|
||||
|
||||
stat(path, &buf);
|
||||
if (stat_condition(&buf))
|
||||
{
|
||||
f = fopen(path, "r"); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test2_5(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
stat_data buf;
|
||||
stat_data *buf_ptr = &buf;
|
||||
|
||||
stat(path, buf_ptr);
|
||||
if (stat_condition(buf_ptr))
|
||||
{
|
||||
f = fopen(path, "r"); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test2_6(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
stat_data buf;
|
||||
|
||||
stat(path, &buf);
|
||||
if (other_condition())
|
||||
{
|
||||
f = fopen(path, "r"); // GOOD (does not depend on the result of stat)
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test2_7(const char *path, int arg)
|
||||
{
|
||||
stat_data buf;
|
||||
int f;
|
||||
|
||||
if (stat(path, &buf))
|
||||
{
|
||||
f = open(path, arg); // BAD
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test2_8(const char *path, int arg)
|
||||
{
|
||||
stat_data buf;
|
||||
int f;
|
||||
|
||||
if (lstat(path, &buf))
|
||||
{
|
||||
f = open(path, arg); // BAD
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test2_9(const char *path, int arg)
|
||||
{
|
||||
stat_data buf;
|
||||
int f;
|
||||
|
||||
if (stat(path, &buf))
|
||||
{
|
||||
f = creat(path, arg); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test2_10(int dir, const char *path, int arg)
|
||||
{
|
||||
stat_data buf;
|
||||
int f;
|
||||
|
||||
if (fstatat(dir, path, &buf))
|
||||
{
|
||||
f = openat(dir, path, arg); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
// --- open -> stat ---
|
||||
|
||||
void test3_1(const char *path, int arg)
|
||||
{
|
||||
stat_data buf;
|
||||
int f;
|
||||
|
||||
f = open(path, arg);
|
||||
if (stat(path, &buf)) // BAD [NOT DETECTED]
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test3_2(const char *path, int arg)
|
||||
{
|
||||
stat_data buf;
|
||||
int f;
|
||||
|
||||
f = open(path, arg);
|
||||
if (fstat(f, &buf)) // GOOD (uses file descriptor, not path)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
// --- open -> chmod ---
|
||||
|
||||
void test4_1(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
f = fopen(path, "w");
|
||||
if (f)
|
||||
{
|
||||
// ...
|
||||
|
||||
fclose(f);
|
||||
|
||||
chmod(path, 0); // DUBIOUS (bad but perhaps not exploitable) [REPORTED]
|
||||
}
|
||||
}
|
||||
|
||||
// --- rename -> remove / open ---
|
||||
|
||||
void test5_1(const char *path1, const char *path2)
|
||||
{
|
||||
if (rename(path1, path2))
|
||||
{
|
||||
remove(path1); // DUBIOUS (bad but perhaps not exploitable) [REPORTED]
|
||||
}
|
||||
}
|
||||
|
||||
void test5_2(const char *path1, const char *path2)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
if (!rename(path1, path2))
|
||||
{
|
||||
f = fopen(path2, "r"); // BAD [NOT DETECTED]
|
||||
}
|
||||
}
|
||||
|
||||
// --- access -> open ---
|
||||
|
||||
void test6_1(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
if (access(path))
|
||||
{
|
||||
f = fopen(path, "r"); // BAD
|
||||
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
void test6_2(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
if (access(path))
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
f = fopen(path, "r"); // GOOD (appears not to be intended to depend on the access check)
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void test6_3(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
if (!access(path))
|
||||
{
|
||||
f = fopen(path, "r"); // BAD
|
||||
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
void test6_4(const char *path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
if (access(path))
|
||||
{
|
||||
// ...
|
||||
} else {
|
||||
f = fopen(path, "r"); // BAD
|
||||
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
void test6_5(const char *path1, const char *path2)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
if (access(path1))
|
||||
{
|
||||
f = fopen(path2, "r"); // GOOD (different file)
|
||||
|
||||
// ...
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user