Skip to content

Commit

Permalink
Merge pull request github#3602 from MathiasVP/path-problem-for-datafl…
Browse files Browse the repository at this point in the history
…ow-tests

C++: Make path-problem versions of ir-flow.ql and flow.ql
  • Loading branch information
jbj authored Jun 2, 2020
2 parents 8b3dd6d + 2a1ba6d commit 9c50acc
Show file tree
Hide file tree
Showing 8 changed files with 1,060 additions and 66 deletions.
32 changes: 32 additions & 0 deletions cpp/ql/test/library-tests/dataflow/fields/ASTConfiguration.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
private import semmle.code.cpp.dataflow.DataFlow
private import DataFlow

class Conf extends Configuration {
Conf() { this = "FieldFlowConf" }

override predicate isSource(Node src) {
src.asExpr() instanceof NewExpr
or
src.asExpr().(Call).getTarget().hasName("user_input")
or
exists(FunctionCall fc |
fc.getAnArgument() = src.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}

override predicate isSink(Node sink) {
exists(Call c |
c.getTarget().hasName("sink") and
c.getAnArgument() = sink.asExpr()
)
}

override predicate isAdditionalFlowStep(Node a, Node b) {
b.asPartialDefinition() =
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
.getQualifier()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}
}
32 changes: 32 additions & 0 deletions cpp/ql/test/library-tests/dataflow/fields/IRConfiguration.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
private import semmle.code.cpp.ir.dataflow.DataFlow
private import DataFlow

class Conf extends Configuration {
Conf() { this = "FieldFlowConf" }

override predicate isSource(Node src) {
src.asExpr() instanceof NewExpr
or
src.asExpr().(Call).getTarget().hasName("user_input")
or
exists(FunctionCall fc |
fc.getAnArgument() = src.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}

override predicate isSink(Node sink) {
exists(Call c |
c.getTarget().hasName("sink") and
c.getAnArgument() = sink.asExpr()
)
}

override predicate isAdditionalFlowStep(Node a, Node b) {
b.asPartialDefinition() =
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
.getQualifier()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}
}
36 changes: 3 additions & 33 deletions cpp/ql/test/library-tests/dataflow/fields/flow.ql
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,19 @@

import TestUtilities.InlineExpectationsTest
import semmle.code.cpp.dataflow.DataFlow
import DataFlow
import ASTConfiguration
import cpp

class Conf extends Configuration {
Conf() { this = "FieldFlowConf" }

override predicate isSource(Node src) {
src.asExpr() instanceof NewExpr
or
src.asExpr().(Call).getTarget().hasName("user_input")
or
exists(FunctionCall fc |
fc.getAnArgument() = src.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}

override predicate isSink(Node sink) {
exists(Call c |
c.getTarget().hasName("sink") and
c.getAnArgument() = sink.asExpr()
)
}

override predicate isAdditionalFlowStep(Node a, Node b) {
b.asPartialDefinition() =
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
.getQualifier()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}
}

class ASTFieldFlowTest extends InlineExpectationsTest {
ASTFieldFlowTest() { this = "ASTFieldFlowTest" }

override string getARelevantTag() { result = "ast" }

override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Node source, Node sink, Conf conf, int n |
exists(DataFlow::Node source, DataFlow::Node sink, Conf conf, int n |
tag = "ast" and
conf.hasFlow(source, sink) and
n = strictcount(Node otherSource | conf.hasFlow(otherSource, sink)) and
n = strictcount(DataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and
(
n = 1 and value = ""
or
Expand Down
36 changes: 3 additions & 33 deletions cpp/ql/test/library-tests/dataflow/fields/ir-flow.ql
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,19 @@

import TestUtilities.InlineExpectationsTest
import semmle.code.cpp.ir.dataflow.DataFlow
import DataFlow
import IRConfiguration
import cpp

class Conf extends Configuration {
Conf() { this = "FieldFlowConf" }

override predicate isSource(Node src) {
src.asExpr() instanceof NewExpr
or
src.asExpr().(Call).getTarget().hasName("user_input")
or
exists(FunctionCall fc |
fc.getAnArgument() = src.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}

override predicate isSink(Node sink) {
exists(Call c |
c.getTarget().hasName("sink") and
c.getAnArgument() = sink.asExpr()
)
}

override predicate isAdditionalFlowStep(Node a, Node b) {
b.asPartialDefinition() =
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
.getQualifier()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}
}

class IRFieldFlowTest extends InlineExpectationsTest {
IRFieldFlowTest() { this = "IRFieldFlowTest" }

override string getARelevantTag() { result = "ir" }

override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Node source, Node sink, Conf conf, int n |
exists(DataFlow::Node source, DataFlow::Node sink, Conf conf, int n |
tag = "ir" and
conf.hasFlow(source, sink) and
n = strictcount(Node otherSource | conf.hasFlow(otherSource, sink)) and
n = strictcount(DataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and
(
n = 1 and value = ""
or
Expand Down
128 changes: 128 additions & 0 deletions cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
edges
| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] |
| A.cpp:142:7:142:20 | Store | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Store |
| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c |
| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c |
| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] |
| A.cpp:154:13:154:13 | c | A.cpp:154:10:154:13 | (void *)... |
| aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] |
| aliasing.cpp:9:3:9:22 | Store | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Store |
| aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] |
| aliasing.cpp:13:3:13:21 | Store | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Store |
| aliasing.cpp:25:17:25:19 | Chi [m1] | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:25:17:25:19 | Chi [m1] |
| aliasing.cpp:26:19:26:20 | Chi [m1] | aliasing.cpp:30:11:30:12 | m1 |
| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:26:19:26:20 | Chi [m1] |
| aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 |
| aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] |
| aliasing.cpp:60:3:60:22 | Store | aliasing.cpp:60:3:60:22 | Chi [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Store |
| aliasing.cpp:61:13:61:14 | Store [m1] | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 |
| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 |
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:3:84:25 | Store | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | Store |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:3:88:24 | Store | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | Store |
| by_reference.cpp:102:21:102:39 | Chi [a] | by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:21:102:39 | Chi [a] |
| by_reference.cpp:106:21:106:41 | Chi [a] | by_reference.cpp:114:29:114:29 | a |
| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | by_reference.cpp:106:21:106:41 | Chi [a] |
| by_reference.cpp:122:21:122:38 | Chi [a] | by_reference.cpp:130:27:130:27 | a |
| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:122:21:122:38 | Chi [a] |
| by_reference.cpp:126:21:126:40 | Chi [a] | by_reference.cpp:134:29:134:29 | a |
| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | by_reference.cpp:126:21:126:40 | Chi [a] |
| simple.cpp:65:5:65:22 | Store [i] | simple.cpp:66:12:66:12 | Store [i] |
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] |
| simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a |
nodes
| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:142:7:142:20 | Store | semmle.label | Store |
| A.cpp:142:14:142:20 | new | semmle.label | new |
| A.cpp:151:18:151:18 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] |
| A.cpp:154:10:154:13 | (void *)... | semmle.label | (void *)... |
| A.cpp:154:13:154:13 | c | semmle.label | c |
| A.cpp:154:13:154:13 | c | semmle.label | c |
| aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:9:3:9:22 | Store | semmle.label | Store |
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:13:3:13:21 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:13:3:13:21 | Store | semmle.label | Store |
| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:25:17:25:19 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] |
| aliasing.cpp:26:19:26:20 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | semmle.label | referenceSetter output argument [m1] |
| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 |
| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 |
| aliasing.cpp:37:13:37:22 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 |
| aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:60:3:60:22 | Store | semmle.label | Store |
| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:61:13:61:14 | Store [m1] | semmle.label | Store [m1] |
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
| aliasing.cpp:79:11:79:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 |
| aliasing.cpp:86:10:86:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 |
| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
| by_reference.cpp:84:3:84:25 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:84:3:84:25 | Store | semmle.label | Store |
| by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:88:3:88:24 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:88:3:88:24 | Store | semmle.label | Store |
| by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:102:21:102:39 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:106:21:106:41 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:110:27:110:27 | a | semmle.label | a |
| by_reference.cpp:114:29:114:29 | a | semmle.label | a |
| by_reference.cpp:122:21:122:38 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] |
| by_reference.cpp:126:21:126:40 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] |
| by_reference.cpp:130:27:130:27 | a | semmle.label | a |
| by_reference.cpp:134:29:134:29 | a | semmle.label | a |
| simple.cpp:65:5:65:22 | Store [i] | semmle.label | Store [i] |
| simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] |
| simple.cpp:67:13:67:13 | i | semmle.label | i |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:22:11:22:11 | a | semmle.label | a |
| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input |
| struct_init.c:31:23:31:23 | a | semmle.label | a |
#select
| A.cpp:154:10:154:13 | (void *)... | A.cpp:142:14:142:20 | new | A.cpp:154:10:154:13 | (void *)... | (void *)... flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input |
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input |
| aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input | call to user_input |
| aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input | call to user_input |
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input |
| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input | call to user_input |
| aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input | call to user_input |
| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input |
| by_reference.cpp:110:27:110:27 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:110:27:110:27 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
| by_reference.cpp:114:29:114:29 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:114:29:114:29 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
| by_reference.cpp:130:27:130:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:130:27:130:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
12 changes: 12 additions & 0 deletions cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* @kind path-problem
*/

import semmle.code.cpp.ir.dataflow.DataFlow
import IRConfiguration
import cpp
import DataFlow::PathGraph

from DataFlow::PathNode src, DataFlow::PathNode sink, Conf conf
where conf.hasFlowPath(src, sink)
select sink, src, sink, sink + " flows from $@", src, src.toString()
Loading

0 comments on commit 9c50acc

Please sign in to comment.