Skip to content

Commit 3db384d

Browse files
committed
CPP: Handle globals flowing into "UnreacheachedInstruction"
1 parent 67a0112 commit 3db384d

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,16 @@ class GlobalUse extends UseImpl, TGlobalUse {
447447
IRFunction getIRFunction() { result = f }
448448

449449
final override predicate hasIndexInBlock(IRBlock block, int index) {
450-
exists(ExitFunctionInstruction exit |
451-
exit = f.getExitFunctionInstruction() and
452-
block.getInstruction(index) = exit
450+
// Similar to the `FinalParameterUse` case, we want to generate flow out of
451+
// globals at any exit so that we can flow out of non-returning functions.
452+
// Obviously this isn't correct as we can't actually flow but the global flow
453+
// requires this if we want to flow into children.
454+
exists(Instruction return |
455+
return instanceof ReturnInstruction or
456+
return instanceof UnreachedInstruction
457+
|
458+
block.getInstruction(index) = return and
459+
return.getEnclosingIRFunction() = f
453460
)
454461
}
455462

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
edges
22
| test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection |
3+
| test.c:14:27:14:30 | argv indirection | test.c:35:16:35:23 | userName indirection |
4+
| test.c:35:16:35:23 | userName indirection | test.c:40:25:40:32 | username indirection |
5+
| test.c:38:7:38:20 | globalUsername indirection | test.c:51:18:51:23 | query1 indirection |
6+
| test.c:40:25:40:32 | username indirection | test.c:38:7:38:20 | globalUsername indirection |
37
| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection |
48
nodes
59
| test.c:14:27:14:30 | argv indirection | semmle.label | argv indirection |
610
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
11+
| test.c:35:16:35:23 | userName indirection | semmle.label | userName indirection |
12+
| test.c:38:7:38:20 | globalUsername indirection | semmle.label | globalUsername indirection |
13+
| test.c:40:25:40:32 | username indirection | semmle.label | username indirection |
14+
| test.c:51:18:51:23 | query1 indirection | semmle.label | query1 indirection |
715
| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection |
816
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
917
subpaths
1018
#select
1119
| test.c:21:18:21:23 | query1 | test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | argv indirection | user input (a command-line argument) |
20+
| test.c:51:18:51:23 | query1 | test.c:14:27:14:30 | argv indirection | test.c:51:18:51:23 | query1 indirection | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | argv indirection | user input (a command-line argument) |
1221
| test.cpp:43:27:43:33 | access to array | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection | This argument to a SQL query function is derived from $@ and then passed to pqxx::work::exec1((unnamed parameter 0)). | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |

cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ int snprintf(char *s, size_t n, const char *format, ...);
88
void sanitizeString(char *stringOut, size_t len, const char *strIn);
99
int mysql_query(int arg1, const char *sqlArg);
1010
int atoi(const char *nptr);
11-
11+
void exit(int i);
1212
///// Test code /////
1313

1414
int main(int argc, char** argv) {
@@ -31,4 +31,22 @@ int main(int argc, char** argv) {
3131
char query3[1000] = {0};
3232
snprintf(query3, 1000, "SELECT UID FROM USERS where number = \"%i\"", userNumber);
3333
mysql_query(0, query3); // GOOD
34+
35+
nonReturning(userName);
36+
}
37+
38+
char* globalUsername;
39+
40+
void nonReturning(char* username) {
41+
globalUsername = username;
42+
badFunc();
43+
// This function does not return, so we used to lose the global flow here.
44+
exit(0);
45+
}
46+
47+
void badFunc() {
48+
char *userName = globalUsername;
49+
char query1[1000] = {0};
50+
snprintf(query1, 1000, "SELECT UID FROM USERS where name = \"%s\"", userName);
51+
mysql_query(0, query1); // BAD
3452
}

0 commit comments

Comments
 (0)