From d38dbf0f634121051905ec6bbecf0a61f47ff79e Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 20 Aug 2019 10:43:03 +0200 Subject: [PATCH] C++: Workaround for lambda expression locations See CPP-427. --- .../cpp/dataflow/internal/DataFlowUtil.qll | 23 ++++++++++- .../dataflow/dataflow-tests/test.expected | 6 +-- .../dataflow-tests/test_diff.expected | 4 +- .../dataflow/fields/flow.expected | 8 ++-- .../dataflow/taint-tests/localTaint.expected | 40 +++++++++---------- .../dataflow/taint-tests/taint.expected | 6 +-- .../dataflow/taint-tests/test_diff.expected | 4 +- 7 files changed, 58 insertions(+), 33 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index 955208cacc6..13f5db09b6c 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -106,12 +106,33 @@ class ExprNode extends Node, TExprNode { override string toString() { result = expr.toString() } - override Location getLocation() { result = expr.getLocation() } + override Location getLocation() { + result = getExprLocationOverride(expr) + or + not exists(getExprLocationOverride(expr)) and + result = expr.getLocation() + } /** Gets the expression corresponding to this node. */ Expr getExpr() { result = expr } } +/** + * Gets a location for `e` that's more accurate than `e.getLocation()`, if any. + */ +private Location getExprLocationOverride(Expr e) { + // Base case: the parent has a better location than `e`. + e.getLocation() instanceof UnknownExprLocation and + result = e.getParent().getLocation() and + not result instanceof UnknownLocation + or + // Recursive case: the parent has a location override that's better than what + // `e` has. + e.getLocation() instanceof UnknownExprLocation and + result = getExprLocationOverride(e.getParent()) and + not result instanceof UnknownLocation +} + abstract class ParameterNode extends Node, TNode { /** * Holds if this node is the parameter of `c` at the specified (zero-based) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected index d04fec5514b..044028f0930 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected @@ -1,8 +1,8 @@ | acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source | -| file://:0:0:0:0 | t | lambdas.cpp:8:10:8:15 | call to source | -| file://:0:0:0:0 | t | lambdas.cpp:8:10:8:15 | call to source | -| file://:0:0:0:0 | t | lambdas.cpp:8:10:8:15 | call to source | +| lambdas.cpp:14:3:14:6 | t | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:18:8:18:8 | call to operator() | lambdas.cpp:8:10:8:15 | call to source | +| lambdas.cpp:21:3:21:6 | t | lambdas.cpp:8:10:8:15 | call to source | +| lambdas.cpp:29:3:29:6 | t | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:41:8:41:8 | a | lambdas.cpp:8:10:8:15 | call to source | | test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index f87f7e20703..a32ea1e9eaf 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -1,5 +1,7 @@ -| lambdas.cpp:8:10:8:15 | file://:0:0:0:0 | AST only | +| lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only | +| lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only | +| lambdas.cpp:8:10:8:15 | lambdas.cpp:29:3:29:6 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:35:8:35:8 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:41:8:41:8 | AST only | | test.cpp:89:28:89:34 | test.cpp:92:8:92:14 | IR only | diff --git a/cpp/ql/test/library-tests/dataflow/fields/flow.expected b/cpp/ql/test/library-tests/dataflow/fields/flow.expected index de790fa56ad..3ab306bded5 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/flow.expected @@ -84,8 +84,10 @@ edges | C.cpp:24:5:24:8 | this [post update] [s3, ... (1)] | C.cpp:18:12:18:18 | call to C [s3, ... (1)] | | C.cpp:24:5:24:25 | ... = ... [void] | C.cpp:24:5:24:8 | this [post update] [s3, ... (1)] | | C.cpp:24:16:24:25 | new [void] | C.cpp:24:5:24:25 | ... = ... [void] | -| C.cpp:27:8:27:11 | `this` parameter in func [s1, ... (1)] | file://:0:0:0:0 | this [s1, ... (1)] | -| C.cpp:27:8:27:11 | `this` parameter in func [s3, ... (1)] | file://:0:0:0:0 | this [s3, ... (1)] | +| C.cpp:27:8:27:11 | `this` parameter in func [s1, ... (1)] | C.cpp:29:10:29:11 | this [s1, ... (1)] | +| C.cpp:27:8:27:11 | `this` parameter in func [s3, ... (1)] | C.cpp:31:10:31:11 | this [s3, ... (1)] | +| C.cpp:29:10:29:11 | this [s1, ... (1)] | C.cpp:29:10:29:11 | s1 | +| C.cpp:31:10:31:11 | this [s3, ... (1)] | C.cpp:31:10:31:11 | s3 | | constructors.cpp:26:15:26:15 | f [a_, ... (1)] | constructors.cpp:28:10:28:10 | f [a_, ... (1)] | | constructors.cpp:26:15:26:15 | f [b_, ... (1)] | constructors.cpp:29:10:29:10 | f [b_, ... (1)] | | constructors.cpp:28:10:28:10 | f [a_, ... (1)] | constructors.cpp:28:12:28:12 | call to a | @@ -102,8 +104,6 @@ edges | constructors.cpp:43:9:43:9 | g [b_, ... (1)] | constructors.cpp:26:15:26:15 | f [b_, ... (1)] | | constructors.cpp:46:9:46:9 | h [a_, ... (1)] | constructors.cpp:26:15:26:15 | f [a_, ... (1)] | | constructors.cpp:46:9:46:9 | h [b_, ... (1)] | constructors.cpp:26:15:26:15 | f [b_, ... (1)] | -| file://:0:0:0:0 | this [s1, ... (1)] | C.cpp:29:10:29:11 | s1 | -| file://:0:0:0:0 | this [s3, ... (1)] | C.cpp:31:10:31:11 | s3 | | simple.cpp:26:15:26:15 | f [a_, ... (1)] | simple.cpp:28:10:28:10 | f [a_, ... (1)] | | simple.cpp:26:15:26:15 | f [b_, ... (1)] | simple.cpp:29:10:29:10 | f [b_, ... (1)] | | simple.cpp:28:10:28:10 | f [a_, ... (1)] | simple.cpp:28:12:28:12 | call to a | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 33199c91006..ab23866fe0e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1,9 +1,3 @@ -| file://:0:0:0:0 | this | file://:0:0:0:0 | this | | -| file://:0:0:0:0 | this | file://:0:0:0:0 | this | | -| file://:0:0:0:0 | this | file://:0:0:0:0 | this | | -| file://:0:0:0:0 | this | file://:0:0:0:0 | this | | -| file://:0:0:0:0 | this | file://:0:0:0:0 | this | | -| file://:0:0:0:0 | this | file://:0:0:0:0 | this | | | taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | | @@ -50,13 +44,14 @@ | taint.cpp:71:14:71:17 | 0 | taint.cpp:71:14:71:17 | constructor init of field a | TAINT | | taint.cpp:71:14:71:17 | constructor init of field a [post-this] | taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | | | taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | | -| taint.cpp:71:20:71:30 | constructor init of field b [post-this] | file://:0:0:0:0 | this | | -| taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | file://:0:0:0:0 | this | | +| taint.cpp:71:20:71:30 | constructor init of field b [post-this] | taint.cpp:72:3:72:3 | this | | +| taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | taint.cpp:72:3:72:3 | this | | | taint.cpp:71:22:71:27 | call to source | taint.cpp:71:20:71:30 | constructor init of field b | TAINT | -| taint.cpp:72:3:72:3 | this [post update] | file://:0:0:0:0 | this | | +| taint.cpp:72:3:72:3 | this | taint.cpp:73:3:73:3 | this | | +| taint.cpp:72:3:72:3 | this [post update] | taint.cpp:73:3:73:3 | this | | | taint.cpp:72:7:72:12 | call to source | taint.cpp:72:3:72:14 | ... = ... | | | taint.cpp:73:7:73:7 | 0 | taint.cpp:73:3:73:7 | ... = ... | | -| taint.cpp:76:7:76:14 | `this` parameter in myMethod | file://:0:0:0:0 | this | | +| taint.cpp:76:7:76:14 | `this` parameter in myMethod | taint.cpp:77:3:77:3 | this | | | taint.cpp:77:7:77:12 | call to source | taint.cpp:77:3:77:14 | ... = ... | | | taint.cpp:84:10:84:12 | call to MyClass | taint.cpp:86:2:86:4 | mc1 | | | taint.cpp:84:10:84:12 | call to MyClass | taint.cpp:88:7:88:9 | mc1 | | @@ -176,17 +171,17 @@ | taint.cpp:213:12:213:12 | x | taint.cpp:213:15:213:15 | ref arg y | | | taint.cpp:213:15:213:15 | ref arg y | taint.cpp:216:7:216:7 | y | | | taint.cpp:213:15:213:15 | y | taint.cpp:213:12:213:12 | ref arg x | | -| taint.cpp:223:10:223:15 | call to source | file://:0:0:0:0 | t | | -| taint.cpp:223:10:223:15 | call to source | file://:0:0:0:0 | t | | | taint.cpp:223:10:223:15 | call to source | taint.cpp:228:12:228:12 | t | | +| taint.cpp:223:10:223:15 | call to source | taint.cpp:235:11:239:2 | t | | +| taint.cpp:223:10:223:15 | call to source | taint.cpp:243:11:246:2 | t | | | taint.cpp:223:10:223:15 | call to source | taint.cpp:253:4:253:4 | t | | | taint.cpp:223:10:223:15 | call to source | taint.cpp:260:4:260:4 | t | | -| taint.cpp:224:9:224:10 | 0 | file://:0:0:0:0 | u | | -| taint.cpp:224:9:224:10 | 0 | file://:0:0:0:0 | u | | | taint.cpp:224:9:224:10 | 0 | taint.cpp:228:15:228:15 | u | | +| taint.cpp:224:9:224:10 | 0 | taint.cpp:235:11:239:2 | u | | +| taint.cpp:224:9:224:10 | 0 | taint.cpp:243:11:246:2 | u | | | taint.cpp:224:9:224:10 | 0 | taint.cpp:253:7:253:7 | u | | | taint.cpp:224:9:224:10 | 0 | taint.cpp:260:7:260:7 | u | | -| taint.cpp:225:9:225:10 | 0 | file://:0:0:0:0 | v | | +| taint.cpp:225:9:225:10 | 0 | taint.cpp:235:11:239:2 | v | | | taint.cpp:225:9:225:10 | 0 | taint.cpp:241:7:241:7 | v | | | taint.cpp:226:9:226:10 | 0 | taint.cpp:260:10:260:10 | w | | | taint.cpp:226:9:226:10 | 0 | taint.cpp:261:7:261:7 | w | | @@ -196,8 +191,10 @@ | taint.cpp:228:11:228:11 | `this` parameter in (constructor) | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | | | taint.cpp:228:11:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | | | taint.cpp:228:11:232:2 | {...} | taint.cpp:228:11:232:2 | [...](...){...} | | -| taint.cpp:228:17:228:17 | `this` parameter in operator() | file://:0:0:0:0 | this | | -| taint.cpp:228:17:228:17 | `this` parameter in operator() | file://:0:0:0:0 | this | | +| taint.cpp:228:17:228:17 | `this` parameter in operator() | taint.cpp:229:3:229:6 | this | | +| taint.cpp:228:17:228:17 | `this` parameter in operator() | taint.cpp:244:3:244:6 | this | | +| taint.cpp:229:3:229:6 | this | taint.cpp:230:3:230:6 | this | | +| taint.cpp:230:3:230:6 | this | taint.cpp:231:3:231:11 | this | | | taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field t | TAINT | | taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field u | TAINT | | taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field v | TAINT | @@ -208,7 +205,9 @@ | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | | | taint.cpp:235:11:239:2 | [...](...){...} | taint.cpp:240:2:240:2 | b | | | taint.cpp:235:11:239:2 | {...} | taint.cpp:235:11:239:2 | [...](...){...} | | -| taint.cpp:235:15:235:15 | `this` parameter in operator() | file://:0:0:0:0 | this | | +| taint.cpp:235:15:235:15 | `this` parameter in operator() | taint.cpp:236:3:236:6 | this | | +| taint.cpp:236:3:236:6 | this | taint.cpp:237:3:237:6 | this | | +| taint.cpp:237:3:237:6 | this | taint.cpp:238:3:238:14 | this | | | taint.cpp:238:7:238:12 | call to source | taint.cpp:238:3:238:14 | ... = ... | | | taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field t | TAINT | | taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field u | TAINT | @@ -216,8 +215,9 @@ | taint.cpp:243:11:243:11 | `this` parameter in (constructor) | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | | | taint.cpp:243:11:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | | | taint.cpp:243:11:246:2 | {...} | taint.cpp:243:11:246:2 | [...](...){...} | | -| taint.cpp:243:15:243:15 | `this` parameter in operator() | file://:0:0:0:0 | this | | -| taint.cpp:243:15:243:15 | `this` parameter in operator() | file://:0:0:0:0 | this | | +| taint.cpp:243:15:243:15 | `this` parameter in operator() | taint.cpp:229:3:229:6 | this | | +| taint.cpp:243:15:243:15 | `this` parameter in operator() | taint.cpp:244:3:244:6 | this | | +| taint.cpp:244:3:244:6 | this | taint.cpp:245:3:245:6 | this | | | taint.cpp:249:11:252:2 | [...](...){...} | taint.cpp:253:2:253:2 | d | | | taint.cpp:249:18:249:18 | a | taint.cpp:250:8:250:8 | a | | | taint.cpp:249:25:249:25 | b | taint.cpp:251:8:251:8 | b | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 202cb423a4b..0793bf29e19 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -1,6 +1,3 @@ -| file://:0:0:0:0 | t | taint.cpp:223:10:223:15 | call to source | -| file://:0:0:0:0 | t | taint.cpp:223:10:223:15 | call to source | -| file://:0:0:0:0 | t | taint.cpp:223:10:223:15 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | @@ -25,6 +22,9 @@ | taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source | | taint.cpp:215:7:215:7 | x | taint.cpp:207:6:207:11 | call to source | | taint.cpp:216:7:216:7 | y | taint.cpp:207:6:207:11 | call to source | +| taint.cpp:229:3:229:6 | t | taint.cpp:223:10:223:15 | call to source | | taint.cpp:233:8:233:8 | call to operator() | taint.cpp:223:10:223:15 | call to source | +| taint.cpp:236:3:236:6 | t | taint.cpp:223:10:223:15 | call to source | +| taint.cpp:244:3:244:6 | t | taint.cpp:223:10:223:15 | call to source | | taint.cpp:250:8:250:8 | a | taint.cpp:223:10:223:15 | call to source | | taint.cpp:256:8:256:8 | a | taint.cpp:223:10:223:15 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index fab6f5b624b..e8c4aca85f4 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -1,4 +1,3 @@ -| file://:0:0:0:0 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | @@ -15,6 +14,9 @@ | taint.cpp:195:7:195:7 | taint.cpp:193:6:193:6 | AST only | | taint.cpp:215:7:215:7 | taint.cpp:207:6:207:11 | AST only | | taint.cpp:216:7:216:7 | taint.cpp:207:6:207:11 | AST only | +| taint.cpp:229:3:229:6 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:233:8:233:8 | taint.cpp:223:10:223:15 | AST only | +| taint.cpp:236:3:236:6 | taint.cpp:223:10:223:15 | AST only | +| taint.cpp:244:3:244:6 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:250:8:250:8 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:256:8:256:8 | taint.cpp:223:10:223:15 | AST only |