Skip to content

Commit 10bca35

Browse files
committed
C++: Change 'annotate_path_to_sink' so that you now annotate a ir-path with the previous node (instead of its source). This gives a better overview of the path.
1 parent d9e02e8 commit 10bca35

File tree

4 files changed

+37
-33
lines changed

4 files changed

+37
-33
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,9 @@ module TaintedWithPath {
484484
/** Gets the element that `pathNode` wraps, if any. */
485485
Element getElementFromPathNode(PathNode pathNode) {
486486
exists(DataFlow::Node node | node = pathNode.(WrapPathNode).inner().getNode() |
487-
result = node.asExpr() or
488-
result = node.asParameter()
487+
result = node.asInstruction().getAST()
488+
or
489+
result = node.asOperand().getDef().getAST()
489490
)
490491
or
491492
result = pathNode.(EndpointPathNode).inner()

cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/dispatch.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ using SinkFunction = void (*)(int);
44

55
void notSink(int notSinkParam);
66

7-
void callsSink(int sinkParam) { // $ ir-path=31:28 ir-path=32:31 ir-path=34:22
8-
sink(sinkParam); // $ ir-sink=31:28 ir-sink=32:31 ir-sink=34:22 ast=31:28 ast=32:31 ast=34:22 MISSING: ast,ir=28
7+
void callsSink(int sinkParam) { // $ ir-path=31:23 ir-path=32:26 ir-path=34:17
8+
sink(sinkParam); // $ ast=31:28 ast=32:31 ast=34:22 ir-sink
99
}
1010

1111
struct {
@@ -25,7 +25,7 @@ void assignGlobals() {
2525
};
2626

2727
void testStruct() {
28-
globalStruct.sinkPtr(atoi(getenv("TAINTED"))); // $ ir MISSING: ast
28+
globalStruct.sinkPtr(atoi(getenv("TAINTED"))); // $ MISSING: ir-path,ast
2929
globalStruct.notSinkPtr(atoi(getenv("TAINTED"))); // clean
3030

3131
globalUnion.sinkPtr(atoi(getenv("TAINTED"))); // $ ast ir-path
@@ -48,8 +48,8 @@ class D2 : public D1 {
4848

4949
class D3 : public D2 {
5050
public:
51-
void f(const char* p) override { // $ ir-path=58:10 ir-path=60:17 ir-path=61:28 ir-path=62:29 ir-path=63:33 ir-path=73:30
52-
sink(p); // $ ir-sink=58:10 ir-sink=60:17 ir-sink=61:28 ir-sink=62:29 ir-sink=63:33 ast=58:10 ast=60:17 ast=61:28 ast=62:29 ast=63:33 SPURIOUS: ast=73:30 ir-sink=73:30
51+
void f(const char* p) override { // $ ir-path=58:10 ir-path=60:17 ir-path=61:28 ir-path=62:29 ir-path=63:33 SPURIOUS: ir-path=73:30
52+
sink(p); // $ ast=58:10 ast=60:17 ast=61:28 ast=62:29 ast=63:33 ir-sink SPURIOUS: ast=73:30
5353
}
5454
};
5555

cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/tainted.ql

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,18 @@ class SourceConfiguration extends TaintedWithPath::TaintTrackingConfiguration {
2323
override predicate isSink(Element e) { isSinkArgument(e) }
2424
}
2525

26-
predicate irTaint(Element source, Element sink, string tag) {
27-
exists(TaintedWithPath::PathNode sinkNode, TaintedWithPath::PathNode predNode |
26+
predicate irTaint(Element source, TaintedWithPath::PathNode predNode, string tag) {
27+
exists(TaintedWithPath::PathNode sinkNode |
2828
TaintedWithPath::taintedWithPath(source, _, _, sinkNode) and
2929
predNode = getAPredecessor*(sinkNode) and
30-
sink = getElementFromPathNode(predNode) and
3130
// Make sure the path is actually reachable from this predecessor.
3231
// Otherwise, we could pick `predNode` to be b when `source` is
3332
// `source1` in this dataflow graph:
3433
// source1 ---> a ---> c ---> sinkNode
3534
// ^
3635
// source2 ---> b --/
3736
source = getElementFromPathNode(getAPredecessor*(predNode)) and
38-
if sinkNode = predNode then tag = "ir-sink" else tag = "ir-path"
37+
if predNode = sinkNode then tag = "ir-sink" else tag = "ir-path"
3938
)
4039
}
4140

@@ -45,21 +44,25 @@ class IRDefaultTaintTrackingTest extends InlineExpectationsTest {
4544
override string getARelevantTag() { result = ["ir-path", "ir-sink"] }
4645

4746
override predicate hasActualResult(Location location, string element, string tag, string value) {
48-
exists(Element source, Element tainted, int n |
49-
irTaint(source, tainted, tag) and
50-
n = strictcount(Element otherSource | irTaint(otherSource, tainted, _)) and
51-
(
52-
n = 1 and value = ""
53-
or
54-
// If there is more than one source for this sink
55-
// we specify the source location explicitly.
56-
n > 1 and
47+
exists(Element source, Element elem, TaintedWithPath::PathNode node, int n |
48+
irTaint(source, node, tag) and
49+
elem = getElementFromPathNode(node) and
50+
n = count(int startline | getAPredecessor(node).hasLocationInfo(_, startline, _, _, _)) and
51+
location = elem.getLocation() and
52+
element = elem.toString()
53+
|
54+
// Zero predecessors means it's a source, and 1 predecessor means it has a unique predecessor.
55+
// In either of these cases we leave out the location.
56+
n = [0, 1] and value = ""
57+
or
58+
// If there is more than one predecessor for this node
59+
// we specify the source location explicitly.
60+
n > 1 and
61+
exists(TaintedWithPath::PathNode pred | pred = getAPredecessor(node) |
5762
value =
58-
source.getLocation().getStartLine().toString() + ":" +
59-
source.getLocation().getStartColumn()
60-
) and
61-
location = tainted.getLocation() and
62-
element = tainted.toString()
63+
getElementFromPathNode(pred).getLocation().getStartLine().toString() + ":" +
64+
getElementFromPathNode(pred).getLocation().getStartColumn()
65+
)
6366
)
6467
}
6568
}

cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/test_diff.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ struct S {
1313
}
1414
};
1515

16-
void calls_sink_with_argv(const char* a) { // $ ir-path=96:26 ir-path=98:18
17-
sink(a); // $ ast=96:26 ast=98:18 ir-sink=96:26 ir-sink=98:18
16+
void calls_sink_with_argv(const char* a) { // $ ir-path=96:26 ir-path=102:26
17+
sink(a); // $ ast=96:26 ast=98:18 ir-sink
1818
}
1919

2020
extern int i;
@@ -27,7 +27,7 @@ class BaseWithPureVirtual {
2727
class DerivedCallsSink : public BaseWithPureVirtual {
2828
public:
2929
void f(const char* p) override { // $ ir-path
30-
sink(p); // $ ir-sink ast=108:10 SPURIOUS: ast=111:10
30+
sink(p); // $ ast=108:10 ir-sink SPURIOUS: ast=111:10
3131
}
3232
};
3333

@@ -49,16 +49,16 @@ class DerivedDoesNotCallSinkDiamond2 : virtual public BaseWithPureVirtual {
4949
};
5050

5151
class DerivesMultiple : public DerivedCallsSinkDiamond1, public DerivedDoesNotCallSinkDiamond2 {
52-
void f(const char* p) override { // $ ir-path
53-
DerivedCallsSinkDiamond1::f(p);
52+
void f(const char* p) override { // $ ir-path=53:37 ir-path=115:11
53+
DerivedCallsSinkDiamond1::f(p); // $ ir-path
5454
}
5555
};
5656

5757
template<typename T>
5858
class CRTP {
5959
public:
6060
void f(const char* p) { // $ ir-path
61-
static_cast<T*>(this)->g(p);
61+
static_cast<T*>(this)->g(p); // $ ir-path
6262
}
6363
};
6464

@@ -79,7 +79,7 @@ class Derived2 : public Derived1 {
7979
class Derived3 : public Derived2 {
8080
public:
8181
void f(const char* p) override { // $ ir-path=124:19 ir-path=126:43 ir-path=128:44
82-
sink(p); // $ ast,ir-sink=124:19 ast,ir-sink=126:43 ast,ir-sink=128:44
82+
sink(p); // $ ast=124:19 ast=126:43 ast=128:44 ir-sink
8383
}
8484
};
8585

@@ -99,7 +99,7 @@ int main(int argc, char *argv[]) {
9999

100100
sink(*p[0]); // $ ast,ir-sink
101101

102-
calls_sink_with_argv(*p[i]); // $ MISSING: ast,ir-path
102+
calls_sink_with_argv(*p[i]); // $ ir-path MISSING:ast
103103

104104
sink(*(argv + 1)); // $ ast,ir-path ir-sink
105105

0 commit comments

Comments
 (0)