Skip to content

Commit 0996e60

Browse files
committed
C++: Pretty print MaD ids in test output
1 parent ec09d36 commit 0996e60

File tree

8 files changed

+141
-60
lines changed

8 files changed

+141
-60
lines changed

cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,49 @@ private predicate summaryModel0(
229229
)
230230
}
231231

232+
/**
233+
* Holds if the given extension tuple `madId` should pretty-print as `model`.
234+
*
235+
* This predicate should only be used in tests.
236+
*/
237+
predicate interpretModelForTest(QlBuiltins::ExtensionId madId, string model) {
238+
exists(
239+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
240+
string output, string kind, string provenance
241+
|
242+
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind,
243+
provenance, madId)
244+
|
245+
model =
246+
"Source: " + namespace + "; " + type + "; " + subtypes + "; " + name + "; " + signature + "; "
247+
+ ext + "; " + output + "; " + kind + "; " + provenance
248+
)
249+
or
250+
exists(
251+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
252+
string input, string kind, string provenance
253+
|
254+
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance,
255+
madId)
256+
|
257+
model =
258+
"Sink: " + namespace + "; " + type + "; " + subtypes + "; " + name + "; " + signature + "; " +
259+
ext + "; " + input + "; " + kind + "; " + provenance
260+
)
261+
or
262+
exists(
263+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
264+
string input, string output, string kind, string provenance
265+
|
266+
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
267+
provenance, madId)
268+
|
269+
model =
270+
"Summary: " + namespace + "; " + type + "; " + subtypes + "; " + name + "; " + signature +
271+
"; " + ext + "; " + input + "; " + output + "; " + kind + "; " + provenance
272+
)
273+
}
274+
232275
/**
233276
* Holds if `input` is `input0`, but with all occurrences of `@` replaced
234277
* by `n` repetitions of `*` (and similarly for `output` and `output0`).
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* @kind test-postprocess
3+
*/
4+
5+
import semmle.code.cpp.dataflow.ExternalFlow
6+
import codeql.dataflow.test.ProvenancePathGraph::TestPostProcessing::TranslateProvenanceResults<interpretModelForTest/2>

cpp/ql/test/library-tests/dataflow/external-models/flow.expected

Lines changed: 61 additions & 37 deletions
Large diffs are not rendered by default.

cpp/ql/test/library-tests/dataflow/external-models/flow.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import utils.test.dataflow.FlowTestCommon
22
import cpp
33
import semmle.code.cpp.security.FlowSources
4-
import IRTest::IRFlow::PathGraph
4+
import codeql.dataflow.test.ProvenancePathGraph
55

66
module IRTest {
77
private import semmle.code.cpp.ir.IR
@@ -33,3 +33,4 @@ module IRTest {
3333
}
3434

3535
import MakeTest<IRFlowTest<IRTest::IRFlow>>
36+
import ShowProvenance<interpretModelForTest/2, IRTest::IRFlow::PathNode, IRTest::IRFlow::PathGraph>

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
#select
2+
| test.c:21:18:21:23 | query1 | test.c:14:27:14:30 | **argv | test.c:21:18:21:23 | *query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | **argv | user input (a command-line argument) |
3+
| test.c:51:18:51:23 | query1 | test.c:14:27:14:30 | **argv | test.c:51:18:51:23 | *query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | **argv | user input (a command-line argument) |
4+
| test.c:76:17:76:25 | userInput | test.c:75:8:75:16 | gets output argument | test.c:76:17:76:25 | *userInput | This argument to a SQL query function is derived from $@ and then passed to SQLPrepare(StatementText). | test.c:75:8:75:16 | gets output argument | user input (string read by gets) |
5+
| test.c:77:20:77:28 | userInput | test.c:75:8:75:16 | gets output argument | test.c:77:20:77:28 | *userInput | This argument to a SQL query function is derived from $@ and then passed to SQLExecDirect(StatementText). | test.c:75:8:75:16 | gets output argument | user input (string read by gets) |
6+
| test.c:106:24:106:29 | query1 | test.c:101:8:101:16 | gets output argument | test.c:106:24:106:29 | *query1 | This argument to a SQL query function is derived from $@. | test.c:101:8:101:16 | gets output argument | user input (string read by gets) |
7+
| test.c:107:28:107:33 | query1 | test.c:101:8:101:16 | gets output argument | test.c:107:28:107:33 | *query1 | This argument to a SQL query function is derived from $@. | test.c:101:8:101:16 | gets output argument | user input (string read by gets) |
8+
| test.cpp:43:27:43:33 | access to array | test.cpp:39:27:39:30 | **argv | test.cpp:43:27:43:33 | *access to array | 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 | user input (a command-line argument) |
19
edges
210
| test.c:14:27:14:30 | **argv | test.c:15:20:15:26 | *access to array | provenance | |
311
| test.c:15:20:15:26 | *access to array | test.c:21:18:21:23 | *query1 | provenance | TaintFunction |
@@ -9,9 +17,12 @@ edges
917
| test.c:48:20:48:33 | *globalUsername | test.c:51:18:51:23 | *query1 | provenance | TaintFunction |
1018
| test.c:75:8:75:16 | gets output argument | test.c:76:17:76:25 | *userInput | provenance | |
1119
| test.c:75:8:75:16 | gets output argument | test.c:77:20:77:28 | *userInput | provenance | |
12-
| test.c:101:8:101:16 | gets output argument | test.c:106:24:106:29 | *query1 | provenance | TaintFunction Sink:MaD:325 |
13-
| test.c:101:8:101:16 | gets output argument | test.c:107:28:107:33 | *query1 | provenance | TaintFunction Sink:MaD:326 |
20+
| test.c:101:8:101:16 | gets output argument | test.c:106:24:106:29 | *query1 | provenance | TaintFunction Sink:MaD:2 |
21+
| test.c:101:8:101:16 | gets output argument | test.c:107:28:107:33 | *query1 | provenance | TaintFunction Sink:MaD:1 |
1422
| test.cpp:39:27:39:30 | **argv | test.cpp:43:27:43:33 | *access to array | provenance | |
23+
models
24+
| 1 | Sink: ; ; false; OCIStmtPrepare2; ; ; Argument[*3]; sql-injection; manual |
25+
| 2 | Sink: ; ; false; OCIStmtPrepare; ; ; Argument[*2]; sql-injection; manual |
1526
nodes
1627
| test.c:14:27:14:30 | **argv | semmle.label | **argv |
1728
| test.c:15:20:15:26 | *access to array | semmle.label | *access to array |
@@ -31,11 +42,3 @@ nodes
3142
| test.cpp:39:27:39:30 | **argv | semmle.label | **argv |
3243
| test.cpp:43:27:43:33 | *access to array | semmle.label | *access to array |
3344
subpaths
34-
#select
35-
| test.c:21:18:21:23 | query1 | test.c:14:27:14:30 | **argv | test.c:21:18:21:23 | *query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | **argv | user input (a command-line argument) |
36-
| test.c:51:18:51:23 | query1 | test.c:14:27:14:30 | **argv | test.c:51:18:51:23 | *query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | **argv | user input (a command-line argument) |
37-
| test.c:76:17:76:25 | userInput | test.c:75:8:75:16 | gets output argument | test.c:76:17:76:25 | *userInput | This argument to a SQL query function is derived from $@ and then passed to SQLPrepare(StatementText). | test.c:75:8:75:16 | gets output argument | user input (string read by gets) |
38-
| test.c:77:20:77:28 | userInput | test.c:75:8:75:16 | gets output argument | test.c:77:20:77:28 | *userInput | This argument to a SQL query function is derived from $@ and then passed to SQLExecDirect(StatementText). | test.c:75:8:75:16 | gets output argument | user input (string read by gets) |
39-
| test.c:106:24:106:29 | query1 | test.c:101:8:101:16 | gets output argument | test.c:106:24:106:29 | *query1 | This argument to a SQL query function is derived from $@. | test.c:101:8:101:16 | gets output argument | user input (string read by gets) |
40-
| test.c:107:28:107:33 | query1 | test.c:101:8:101:16 | gets output argument | test.c:107:28:107:33 | *query1 | This argument to a SQL query function is derived from $@. | test.c:101:8:101:16 | gets output argument | user input (string read by gets) |
41-
| test.cpp:43:27:43:33 | access to array | test.cpp:39:27:39:30 | **argv | test.cpp:43:27:43:33 | *access to array | 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 | user input (a command-line argument) |
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
Security/CWE/CWE-089/SqlTainted.ql
1+
query: Security/CWE/CWE-089/SqlTainted.ql
2+
postprocess:
3+
- utils/test/PrettyPrintModels.ql
4+
- utils/test/InlineExpectationsTestQuery.ql
5+

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ int atoi(const char *nptr);
1111
void exit(int i);
1212
///// Test code /////
1313

14-
int main(int argc, char** argv) {
14+
int main(int argc, char** argv) { // $ Source
1515
char *userName = argv[2];
1616
int userNumber = atoi(argv[3]);
1717

1818
// a string from the user is injected directly into an SQL query.
1919
char query1[1000] = {0};
2020
snprintf(query1, 1000, "SELECT UID FROM USERS where name = \"%s\"", userName);
21-
mysql_query(0, query1); // BAD
21+
mysql_query(0, query1); // $ Alert
2222

2323
// the user string is encoded by a library routine.
2424
char userNameSanitized[1000] = {0};
@@ -48,7 +48,7 @@ void badFunc() {
4848
char *userName = globalUsername;
4949
char query1[1000] = {0};
5050
snprintf(query1, 1000, "SELECT UID FROM USERS where name = \"%s\"", userName);
51-
mysql_query(0, query1); // BAD
51+
mysql_query(0, query1); // $ Alert
5252
}
5353

5454
//ODBC Library Rountines
@@ -72,9 +72,9 @@ SQLRETURN SQLPrepare(
7272

7373
void ODBCTests(){
7474
char userInput[100];
75-
gets(userInput);
76-
SQLPrepare(0, userInput, 100); // BAD
77-
SQLExecDirect(0, userInput, 100); // BAD
75+
gets(userInput); // $ Source
76+
SQLPrepare(0, userInput, 100); // $ Alert
77+
SQLExecDirect(0, userInput, 100); // $ Alert
7878
}
7979

8080
// Oracle Call Interface (OCI) Routines
@@ -98,13 +98,13 @@ int OCIStmtPrepare2(
9898

9999
void OCITests(){
100100
char userInput[100];
101-
gets(userInput);
101+
gets(userInput); // $ Source
102102

103103
// a string from the user is injected directly into an SQL query.
104104
char query1[1000] = {0};
105105
snprintf(query1, 1000, "SELECT UID FROM USERS where name = \"%s\"", userInput);
106-
OCIStmtPrepare(0, 0, query1, 0, 0, 0); // BAD
107-
OCIStmtPrepare2(0, 0, 0, query1, 0, 0, 0, 0, 0); // BAD
106+
OCIStmtPrepare(0, 0, query1, 0, 0, 0); // $ Alert
107+
OCIStmtPrepare2(0, 0, 0, query1, 0, 0, 0, 0, 0); // $ Alert
108108

109109
// an integer from the user is injected into an SQL query.
110110
int userNumber = atoi(userInput);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ namespace pqxx {
3636
};
3737
}
3838

39-
int main(int argc, char** argv) {
39+
int main(int argc, char** argv) { // $ Source
4040
pqxx::connection c;
4141
pqxx::work w(c);
4242

43-
pqxx::row r = w.exec1(argv[1]); // BAD
43+
pqxx::row r = w.exec1(argv[1]); // $ Alert
4444

4545
pqxx::result r2 = w.exec(w.quote(argv[1])); // GOOD
4646

0 commit comments

Comments
 (0)