diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 626e81e095c2..d33bfd903dee 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -484,8 +484,9 @@ module TaintedWithPath { /** Gets the element that `pathNode` wraps, if any. */ Element getElementFromPathNode(PathNode pathNode) { exists(DataFlow::Node node | node = pathNode.(WrapPathNode).inner().getNode() | - result = node.asExpr() or - result = node.asParameter() + result = node.asInstruction().getAST() + or + result = node.asOperand().getDef().getAST() ) or result = pathNode.(EndpointPathNode).inner() diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index c3455d4790ad..bb434fd7ef2b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -806,7 +806,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand()) or // Flow into, through, and out of store nodes - StoreNodeFlow::flowInto(nodeFrom, nodeTo) + StoreNodeFlow::flowInto(nodeFrom.asInstruction(), nodeTo) or StoreNodeFlow::flowThrough(nodeFrom, nodeTo) or @@ -831,18 +831,11 @@ private predicate adjacentDefUseFlow(Node nodeFrom, Node nodeTo) { //Def-use flow Ssa::ssaFlow(nodeFrom, nodeTo) or - exists(Instruction loadAddress | loadAddress = Ssa::getSourceAddressFromNode(nodeFrom) | - // Use-use flow through reads - exists(Node address | - Ssa::addressFlowTC(address.asInstruction(), loadAddress) and - Ssa::ssaFlow(address, nodeTo) - ) - or - // Use-use flow through stores. - exists(Node store | - Ssa::explicitWrite(_, store.asInstruction(), loadAddress) and - Ssa::ssaFlow(store, nodeTo) - ) + // Use-use flow through stores. + exists(Instruction loadAddress, Node store | + loadAddress = Ssa::getSourceAddressFromNode(nodeFrom) and + Ssa::explicitWrite(_, store.asInstruction(), loadAddress) and + Ssa::ssaFlow(store, nodeTo) ) ) } @@ -906,10 +899,13 @@ private module ReadNodeFlow { } } -private module StoreNodeFlow { +/** + * INTERNAL: Do not use. + */ +module StoreNodeFlow { /** Holds if the store node `nodeTo` should receive flow from `nodeFrom`. */ - predicate flowInto(Node nodeFrom, StoreNode nodeTo) { - nodeTo.flowInto(Ssa::getDestinationAddress(nodeFrom.asInstruction())) + predicate flowInto(Instruction instrFrom, StoreNode nodeTo) { + nodeTo.flowInto(Ssa::getDestinationAddress(instrFrom)) } /** Holds if the store node `nodeTo` should receive flow from `nodeFom`. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll index 1a353072be5b..b3a68278903b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll @@ -244,17 +244,6 @@ Instruction getDestinationAddress(Instruction instr) { ] } -class ReferenceToInstruction extends CopyValueInstruction { - ReferenceToInstruction() { - this.getResultType() instanceof Cpp::ReferenceType and - not this.getUnary().getResultType() instanceof Cpp::ReferenceType - } - - Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } - - Operand getSourceAddressOperand() { result = this.getUnaryOperand() } -} - /** Gets the source address of `instr` if it is an instruction that behaves like a `LoadInstruction`. */ Instruction getSourceAddress(Instruction instr) { result = getSourceAddressOperand(instr).getDef() } @@ -266,11 +255,7 @@ Operand getSourceAddressOperand(Instruction instr) { result = [ instr.(LoadInstruction).getSourceAddressOperand(), - instr.(ReadSideEffectInstruction).getArgumentOperand(), - // `ReferenceToInstruction` is really more of an address-of operation, - // but by including it in this list we break out of `flowOutOfAddressStep` at an - // instruction that, at the source level, looks like a use of a variable. - instr.(ReferenceToInstruction).getSourceAddressOperand() + instr.(ReadSideEffectInstruction).getArgumentOperand() ] } @@ -295,10 +280,6 @@ Operand getSourceValueOperand(Instruction instr) { result = instr.(LoadInstruction).getSourceValueOperand() or result = instr.(ReadSideEffectInstruction).getSideEffectOperand() - or - // See the comment on the `ReferenceToInstruction` disjunct in `getSourceAddressOperand` for why - // this case is included. - result = instr.(ReferenceToInstruction).getSourceValueOperand() } /** @@ -513,6 +494,64 @@ private module Cached { explicitWrite(false, storeNode.getStoreInstruction(), def) ) or + // The destination of a store operation has undergone lvalue-to-rvalue conversion and is now a + // right-hand-side of a store operation. + // Find the next use of the variable in that store operation, and recursively find the load of that + // pointer. For example, consider this case: + // + // ```cpp + // int x = source(); + // int* p = &x; + // sink(*p); + // ``` + // + // if we want to find the load of the address of `x`, we see that the pointer is stored into `p`, + // and we then need to recursively look for the load of `p`. + exists( + Def def, StoreInstruction store, IRBlock block1, int rnk1, Use use, IRBlock block2, int rnk2 + | + store = def.getInstruction() and + store.getSourceValueOperand() = operand and + def.hasRankInBlock(block1, rnk1) and + use.hasRankInBlock(block2, rnk2) and + adjacentDefRead(_, block1, rnk1, block2, rnk2) + | + // The shared SSA library has determined that `use` is the next use of the operand + // so we find the next load of that use (but only if there is no `PostUpdateNode`) we + // need to flow into first. + not StoreNodeFlow::flowInto(store, _) and + flowOutOfAddressStep(use.getOperand(), nodeTo) + or + // It may also be the case that `store` gives rise to another store step. So let's make sure that + // we also take those into account. + StoreNodeFlow::flowInto(store, nodeTo) + ) + or + // As we find the next load of an address, we might come across another use of the same variable. + // In that case, we recursively find the next use of _that_ operand, and continue searching for + // the next load of that operand. For example, consider this case: + // + // ```cpp + // int x = source(); + // use(&x); + // int* p = &x; + // sink(*p); + // ``` + // + // The next use of `x` after its definition is `use(&x)`, but there is a later load of the address + // of `x` that we want to flow to. So we use the shared SSA library to find the next load. + not operand = getSourceAddressOperand(_) and + exists(Use use1, Use use2, IRBlock block1, int rnk1, IRBlock block2, int rnk2 | + use1.getOperand() = operand and + use1.hasRankInBlock(block1, rnk1) and + // Don't flow to the next use if this use is part of a store operation that totally + // overrides a variable. + not explicitWrite(true, _, use1.getOperand().getDef()) and + adjacentDefRead(_, block1, rnk1, block2, rnk2) and + use2.hasRankInBlock(block2, rnk2) and + flowOutOfAddressStep(use2.getOperand(), nodeTo) + ) + or operand = getSourceAddressOperand(nodeTo.asInstruction()) or exists(ReturnIndirectionInstruction ret | diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/dispatch.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/dispatch.cpp index d8bd607afe81..95f7f790f693 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/dispatch.cpp +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/dispatch.cpp @@ -4,8 +4,8 @@ using SinkFunction = void (*)(int); void notSink(int notSinkParam); -void callsSink(int sinkParam) { // $ ir-path=31:28 ir-path=32:31 ir-path=34:22 - 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 +void callsSink(int sinkParam) { // $ ir-path=31:23 ir-path=32:26 ir-path=34:17 + sink(sinkParam); // $ ast=31:28 ast=32:31 ast=34:22 ir-sink } struct { @@ -25,7 +25,7 @@ void assignGlobals() { }; void testStruct() { - globalStruct.sinkPtr(atoi(getenv("TAINTED"))); // $ ir MISSING: ast + globalStruct.sinkPtr(atoi(getenv("TAINTED"))); // $ MISSING: ir-path,ast globalStruct.notSinkPtr(atoi(getenv("TAINTED"))); // clean globalUnion.sinkPtr(atoi(getenv("TAINTED"))); // $ ast ir-path @@ -48,8 +48,8 @@ class D2 : public D1 { class D3 : public D2 { public: - 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 - 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 + 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 + sink(p); // $ ast=58:10 ast=60:17 ast=61:28 ast=62:29 ast=63:33 ir-sink SPURIOUS: ast=73:30 } }; diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/tainted.ql b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/tainted.ql index fd3245a33749..c1477d788ca3 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/tainted.ql +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/tainted.ql @@ -23,11 +23,10 @@ class SourceConfiguration extends TaintedWithPath::TaintTrackingConfiguration { override predicate isSink(Element e) { isSinkArgument(e) } } -predicate irTaint(Element source, Element sink, string tag) { - exists(TaintedWithPath::PathNode sinkNode, TaintedWithPath::PathNode predNode | +predicate irTaint(Element source, TaintedWithPath::PathNode predNode, string tag) { + exists(TaintedWithPath::PathNode sinkNode | TaintedWithPath::taintedWithPath(source, _, _, sinkNode) and predNode = getAPredecessor*(sinkNode) and - sink = getElementFromPathNode(predNode) and // Make sure the path is actually reachable from this predecessor. // Otherwise, we could pick `predNode` to be b when `source` is // `source1` in this dataflow graph: @@ -35,7 +34,7 @@ predicate irTaint(Element source, Element sink, string tag) { // ^ // source2 ---> b --/ source = getElementFromPathNode(getAPredecessor*(predNode)) and - if sinkNode = predNode then tag = "ir-sink" else tag = "ir-path" + if predNode = sinkNode then tag = "ir-sink" else tag = "ir-path" ) } @@ -45,21 +44,25 @@ class IRDefaultTaintTrackingTest extends InlineExpectationsTest { override string getARelevantTag() { result = ["ir-path", "ir-sink"] } override predicate hasActualResult(Location location, string element, string tag, string value) { - exists(Element source, Element tainted, int n | - irTaint(source, tainted, tag) and - n = strictcount(Element otherSource | irTaint(otherSource, tainted, _)) and - ( - n = 1 and value = "" - or - // If there is more than one source for this sink - // we specify the source location explicitly. - n > 1 and + exists(Element source, Element elem, TaintedWithPath::PathNode node, int n | + irTaint(source, node, tag) and + elem = getElementFromPathNode(node) and + n = count(int startline | getAPredecessor(node).hasLocationInfo(_, startline, _, _, _)) and + location = elem.getLocation() and + element = elem.toString() + | + // Zero predecessors means it's a source, and 1 predecessor means it has a unique predecessor. + // In either of these cases we leave out the location. + n = [0, 1] and value = "" + or + // If there is more than one predecessor for this node + // we specify the source location explicitly. + n > 1 and + exists(TaintedWithPath::PathNode pred | pred = getAPredecessor(node) | value = - source.getLocation().getStartLine().toString() + ":" + - source.getLocation().getStartColumn() - ) and - location = tainted.getLocation() and - element = tainted.toString() + getElementFromPathNode(pred).getLocation().getStartLine().toString() + ":" + + getElementFromPathNode(pred).getLocation().getStartColumn() + ) ) } } diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/test_diff.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/test_diff.cpp index 059b96f5c131..667eef4ac91e 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/test_diff.cpp +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/test_diff.cpp @@ -13,8 +13,8 @@ struct S { } }; -void calls_sink_with_argv(const char* a) { // $ ir-path=96:26 ir-path=98:18 - sink(a); // $ ast=96:26 ast=98:18 ir-sink=96:26 ir-sink=98:18 +void calls_sink_with_argv(const char* a) { // $ ir-path=96:26 ir-path=102:26 + sink(a); // $ ast=96:26 ast=98:18 ir-sink } extern int i; @@ -27,7 +27,7 @@ class BaseWithPureVirtual { class DerivedCallsSink : public BaseWithPureVirtual { public: void f(const char* p) override { // $ ir-path - sink(p); // $ ir-sink ast=108:10 SPURIOUS: ast=111:10 + sink(p); // $ ast=108:10 ir-sink SPURIOUS: ast=111:10 } }; @@ -49,8 +49,8 @@ class DerivedDoesNotCallSinkDiamond2 : virtual public BaseWithPureVirtual { }; class DerivesMultiple : public DerivedCallsSinkDiamond1, public DerivedDoesNotCallSinkDiamond2 { - void f(const char* p) override { // $ ir-path - DerivedCallsSinkDiamond1::f(p); + void f(const char* p) override { // $ ir-path=53:37 ir-path=115:11 + DerivedCallsSinkDiamond1::f(p); // $ ir-path } }; @@ -58,7 +58,7 @@ template class CRTP { public: void f(const char* p) { // $ ir-path - static_cast(this)->g(p); + static_cast(this)->g(p); // $ ir-path } }; @@ -79,7 +79,7 @@ class Derived2 : public Derived1 { class Derived3 : public Derived2 { public: void f(const char* p) override { // $ ir-path=124:19 ir-path=126:43 ir-path=128:44 - sink(p); // $ ast,ir-sink=124:19 ast,ir-sink=126:43 ast,ir-sink=128:44 + sink(p); // $ ast=124:19 ast=126:43 ast=128:44 ir-sink } }; @@ -97,11 +97,11 @@ int main(int argc, char *argv[]) { char*** p = &argv; // $ ast,ir-path - sink(*p[0]); // $ ast,ir-sink + sink(*p[0]); // $ ast ir-sink=96:26 ir-sink=98:18 - calls_sink_with_argv(*p[i]); // $ MISSING: ast,ir-path + calls_sink_with_argv(*p[i]); // $ ir-path=96:26 ir-path=98:18 MISSING:ast - sink(*(argv + 1)); // $ ast,ir-path ir-sink + sink(*(argv + 1)); // $ ast ir-path ir-sink BaseWithPureVirtual* b = new DerivedCallsSink; diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp index 834ef057b2bd..ce758af691be 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp @@ -190,9 +190,9 @@ void test_pointers1() sink(ptr1); // $ ast MISSING: ir sink(ptr2); // $ SPURIOUS: ast sink(*ptr2); // $ ast MISSING: ir - sink(ptr3); // $ ast MISSING: ir - sink(ptr4); // $ SPURIOUS: ast - sink(*ptr4); // $ ast MISSING: ir + sink(ptr3); // $ ast,ir + sink(ptr4); // $ SPURIOUS: ast,ir + sink(*ptr4); // $ ast,ir } void test_pointers2() diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected index 8f070732ab30..f613f3f439c6 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected @@ -537,8 +537,8 @@ edges | complex.cpp:11:22:11:23 | a_ [post update] | complex.cpp:11:22:11:23 | this [post update] [a_] | | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | b_ [post update] | | complex.cpp:12:22:12:23 | b_ [post update] | complex.cpp:12:22:12:23 | this [post update] [b_] | -| complex.cpp:40:17:40:17 | b [inner, f, a_] | complex.cpp:42:8:42:8 | (reference dereference) [read] [inner, f, a_] | -| complex.cpp:40:17:40:17 | b [inner, f, b_] | complex.cpp:43:8:43:8 | (reference dereference) [read] [inner, f, b_] | +| complex.cpp:40:17:40:17 | *b [inner, f, a_] | complex.cpp:42:8:42:8 | (reference dereference) [read] [inner, f, a_] | +| complex.cpp:40:17:40:17 | *b [inner, f, b_] | complex.cpp:43:8:43:8 | (reference dereference) [read] [inner, f, b_] | | complex.cpp:42:8:42:8 | (reference dereference) [read] [inner, f, a_] | complex.cpp:42:10:42:14 | inner [read] [f, a_] | | complex.cpp:42:10:42:14 | inner [read] [f, a_] | complex.cpp:42:16:42:16 | f [read] [a_] | | complex.cpp:42:16:42:16 | f [read] [a_] | complex.cpp:42:18:42:18 | f [a_] | @@ -549,38 +549,38 @@ edges | complex.cpp:43:16:43:16 | f [read] [b_] | complex.cpp:43:18:43:18 | f [b_] | | complex.cpp:43:18:43:18 | f [b_] | complex.cpp:10:7:10:7 | this [b_] | | complex.cpp:43:18:43:18 | f [b_] | complex.cpp:43:18:43:18 | call to b | -| complex.cpp:53:3:53:4 | b1 [post update] [inner, f, a_] | complex.cpp:59:3:59:5 | b1 [inner, f, a_] | +| complex.cpp:53:3:53:4 | b1 [post update] [inner, f, a_] | complex.cpp:59:7:59:8 | b1 indirection [inner, f, a_] | | complex.cpp:53:6:53:10 | inner [post update] [f, a_] | complex.cpp:53:3:53:4 | b1 [post update] [inner, f, a_] | | complex.cpp:53:12:53:12 | f [post update] [a_] | complex.cpp:53:6:53:10 | inner [post update] [f, a_] | | complex.cpp:53:14:53:17 | call to user_input | complex.cpp:11:17:11:17 | a | | complex.cpp:53:14:53:17 | call to user_input | complex.cpp:53:14:53:17 | f [post update] [a_] | | complex.cpp:53:14:53:17 | f [post update] [a_] | complex.cpp:53:12:53:12 | f [post update] [a_] | | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:14:53:17 | call to user_input | -| complex.cpp:54:3:54:4 | b2 [post update] [inner, f, b_] | complex.cpp:62:3:62:5 | b2 [inner, f, b_] | +| complex.cpp:54:3:54:4 | b2 [post update] [inner, f, b_] | complex.cpp:62:7:62:8 | b2 indirection [inner, f, b_] | | complex.cpp:54:6:54:10 | inner [post update] [f, b_] | complex.cpp:54:3:54:4 | b2 [post update] [inner, f, b_] | | complex.cpp:54:12:54:12 | f [post update] [b_] | complex.cpp:54:6:54:10 | inner [post update] [f, b_] | | complex.cpp:54:14:54:17 | call to user_input | complex.cpp:12:17:12:17 | b | | complex.cpp:54:14:54:17 | call to user_input | complex.cpp:54:14:54:17 | f [post update] [b_] | | complex.cpp:54:14:54:17 | f [post update] [b_] | complex.cpp:54:12:54:12 | f [post update] [b_] | | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:14:54:17 | call to user_input | -| complex.cpp:55:3:55:4 | b3 [post update] [inner, f, a_] | complex.cpp:65:3:65:5 | b3 [inner, f, a_] | +| complex.cpp:55:3:55:4 | b3 [post update] [inner, f, a_] | complex.cpp:65:7:65:8 | b3 indirection [inner, f, a_] | | complex.cpp:55:6:55:10 | inner [post update] [f, a_] | complex.cpp:55:3:55:4 | b3 [post update] [inner, f, a_] | | complex.cpp:55:12:55:12 | f [post update] [a_] | complex.cpp:55:6:55:10 | inner [post update] [f, a_] | | complex.cpp:55:14:55:17 | call to user_input | complex.cpp:11:17:11:17 | a | | complex.cpp:55:14:55:17 | call to user_input | complex.cpp:55:14:55:17 | f [post update] [a_] | | complex.cpp:55:14:55:17 | f [post update] [a_] | complex.cpp:55:12:55:12 | f [post update] [a_] | | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:14:55:17 | call to user_input | -| complex.cpp:56:3:56:4 | b3 [post update] [inner, f, b_] | complex.cpp:65:3:65:5 | b3 [inner, f, b_] | +| complex.cpp:56:3:56:4 | b3 [post update] [inner, f, b_] | complex.cpp:65:7:65:8 | b3 indirection [inner, f, b_] | | complex.cpp:56:6:56:10 | inner [post update] [f, b_] | complex.cpp:56:3:56:4 | b3 [post update] [inner, f, b_] | | complex.cpp:56:12:56:12 | f [post update] [b_] | complex.cpp:56:6:56:10 | inner [post update] [f, b_] | | complex.cpp:56:14:56:17 | call to user_input | complex.cpp:12:17:12:17 | b | | complex.cpp:56:14:56:17 | call to user_input | complex.cpp:56:14:56:17 | f [post update] [b_] | | complex.cpp:56:14:56:17 | f [post update] [b_] | complex.cpp:56:12:56:12 | f [post update] [b_] | | complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:14:56:17 | call to user_input | -| complex.cpp:59:3:59:5 | b1 [inner, f, a_] | complex.cpp:40:17:40:17 | b [inner, f, a_] | -| complex.cpp:62:3:62:5 | b2 [inner, f, b_] | complex.cpp:40:17:40:17 | b [inner, f, b_] | -| complex.cpp:65:3:65:5 | b3 [inner, f, a_] | complex.cpp:40:17:40:17 | b [inner, f, a_] | -| complex.cpp:65:3:65:5 | b3 [inner, f, b_] | complex.cpp:40:17:40:17 | b [inner, f, b_] | +| complex.cpp:59:7:59:8 | b1 indirection [inner, f, a_] | complex.cpp:40:17:40:17 | *b [inner, f, a_] | +| complex.cpp:62:7:62:8 | b2 indirection [inner, f, b_] | complex.cpp:40:17:40:17 | *b [inner, f, b_] | +| complex.cpp:65:7:65:8 | b3 indirection [inner, f, a_] | complex.cpp:40:17:40:17 | *b [inner, f, a_] | +| complex.cpp:65:7:65:8 | b3 indirection [inner, f, b_] | complex.cpp:40:17:40:17 | *b [inner, f, b_] | | conflated.cpp:10:4:10:5 | (reference dereference) [post update] [p] | conflated.cpp:11:9:11:10 | (reference dereference) [read] [p] | | conflated.cpp:10:7:10:7 | FieldAddress [post update] | conflated.cpp:10:4:10:5 | (reference dereference) [post update] [p] | | conflated.cpp:10:11:10:20 | call to user_input | conflated.cpp:10:7:10:7 | FieldAddress [post update] | @@ -616,7 +616,8 @@ edges | conflated.cpp:61:12:61:15 | FieldAddress [read] [y] | conflated.cpp:61:12:61:15 | next [read] [y] | | conflated.cpp:61:12:61:15 | next [read] [y] | conflated.cpp:61:18:61:18 | FieldAddress [read] | | conflated.cpp:61:18:61:18 | FieldAddress [read] | conflated.cpp:61:18:61:18 | y | -| constructors.cpp:18:9:18:9 | this [a_] | constructors.cpp:18:22:18:23 | this [read] [a_] | +| constructors.cpp:18:9:18:9 | *#this [a_] | constructors.cpp:18:22:18:23 | this [read] [a_] | +| constructors.cpp:18:9:18:9 | *#this [b_] | constructors.cpp:18:9:18:9 | ReturnIndirection [b_] | | constructors.cpp:18:22:18:23 | FieldAddress [read] | constructors.cpp:18:9:18:9 | ReturnValue | | constructors.cpp:18:22:18:23 | this [read] [a_] | constructors.cpp:18:22:18:23 | FieldAddress [read] | | constructors.cpp:19:9:19:9 | this [b_] | constructors.cpp:19:22:19:23 | this [read] [b_] | @@ -626,32 +627,36 @@ edges | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:32:23:36 | FieldAddress [post update] | | constructors.cpp:23:25:23:29 | FieldAddress [post update] | constructors.cpp:23:5:23:7 | this [post update] [a_] | | constructors.cpp:23:32:23:36 | FieldAddress [post update] | constructors.cpp:23:5:23:7 | this [post update] [b_] | -| constructors.cpp:26:15:26:15 | f [a_] | constructors.cpp:28:12:28:12 | f [a_] | -| constructors.cpp:26:15:26:15 | f [b_] | constructors.cpp:29:12:29:12 | f [b_] | -| constructors.cpp:28:12:28:12 | f [a_] | constructors.cpp:18:9:18:9 | this [a_] | -| constructors.cpp:28:12:28:12 | f [a_] | constructors.cpp:28:12:28:12 | call to a | +| constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:10:28:10 | f indirection [a_] | +| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:28:10:28:10 | f indirection [b_] | +| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:29:12:29:12 | f [b_] | +| constructors.cpp:28:10:28:10 | a output argument [b_] | constructors.cpp:29:12:29:12 | f [b_] | +| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:18:9:18:9 | *#this [a_] | +| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:28:12:28:12 | call to a | +| constructors.cpp:28:10:28:10 | f indirection [b_] | constructors.cpp:18:9:18:9 | *#this [b_] | +| constructors.cpp:28:10:28:10 | f indirection [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] | | constructors.cpp:29:12:29:12 | f [b_] | constructors.cpp:19:9:19:9 | this [b_] | | constructors.cpp:29:12:29:12 | f [b_] | constructors.cpp:29:12:29:12 | call to b | | constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:34:11:34:26 | call to user_input | -| constructors.cpp:34:11:34:26 | Argument this [post update] [a_] | constructors.cpp:40:5:40:7 | f [a_] | +| constructors.cpp:34:11:34:26 | Argument this [post update] [a_] | constructors.cpp:40:9:40:9 | f indirection [a_] | | constructors.cpp:34:11:34:26 | call to user_input | constructors.cpp:23:13:23:13 | a | | constructors.cpp:34:11:34:26 | call to user_input | constructors.cpp:34:11:34:26 | Argument this [post update] [a_] | -| constructors.cpp:35:11:35:26 | Argument this [post update] [b_] | constructors.cpp:43:5:43:7 | g [b_] | +| constructors.cpp:35:11:35:26 | Argument this [post update] [b_] | constructors.cpp:43:9:43:9 | g indirection [b_] | | constructors.cpp:35:11:35:26 | call to user_input | constructors.cpp:23:20:23:20 | b | | constructors.cpp:35:11:35:26 | call to user_input | constructors.cpp:35:11:35:26 | Argument this [post update] [b_] | | constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:35:11:35:26 | call to user_input | | constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:36:11:36:37 | call to user_input | -| constructors.cpp:36:11:36:37 | Argument this [post update] [a_] | constructors.cpp:46:5:46:7 | h [a_] | -| constructors.cpp:36:11:36:37 | Argument this [post update] [b_] | constructors.cpp:46:5:46:7 | h [b_] | +| constructors.cpp:36:11:36:37 | Argument this [post update] [a_] | constructors.cpp:46:9:46:9 | h indirection [a_] | +| constructors.cpp:36:11:36:37 | Argument this [post update] [b_] | constructors.cpp:46:9:46:9 | h indirection [b_] | | constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:23:13:23:13 | a | | constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:23:20:23:20 | b | | constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:36:11:36:37 | Argument this [post update] [a_] | | constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:36:11:36:37 | Argument this [post update] [b_] | | constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:36:11:36:37 | call to user_input | -| constructors.cpp:40:5:40:7 | f [a_] | constructors.cpp:26:15:26:15 | f [a_] | -| constructors.cpp:43:5:43:7 | g [b_] | constructors.cpp:26:15:26:15 | f [b_] | -| constructors.cpp:46:5:46:7 | h [a_] | constructors.cpp:26:15:26:15 | f [a_] | -| constructors.cpp:46:5:46:7 | h [b_] | constructors.cpp:26:15:26:15 | f [b_] | +| constructors.cpp:40:9:40:9 | f indirection [a_] | constructors.cpp:26:15:26:15 | *f [a_] | +| constructors.cpp:43:9:43:9 | g indirection [b_] | constructors.cpp:26:15:26:15 | *f [b_] | +| constructors.cpp:46:9:46:9 | h indirection [a_] | constructors.cpp:26:15:26:15 | *f [a_] | +| constructors.cpp:46:9:46:9 | h indirection [b_] | constructors.cpp:26:15:26:15 | *f [b_] | | qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:36:9:36 | a [post update] | | qualifiers.cpp:9:36:9:36 | a [post update] | qualifiers.cpp:9:30:9:33 | this [post update] [a] | | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:56:12:56 | a [post update] | @@ -730,7 +735,8 @@ edges | realistic.cpp:61:32:61:34 | baz [read] [userInput, bufferLen] | realistic.cpp:61:37:61:45 | userInput [read] [bufferLen] | | realistic.cpp:61:37:61:45 | userInput [read] [bufferLen] | realistic.cpp:61:47:61:55 | FieldAddress [read] | | realistic.cpp:61:47:61:55 | FieldAddress [read] | realistic.cpp:61:14:61:55 | (void *)... | -| simple.cpp:18:9:18:9 | this [a_] | simple.cpp:18:22:18:23 | this [read] [a_] | +| simple.cpp:18:9:18:9 | *#this [a_] | simple.cpp:18:22:18:23 | this [read] [a_] | +| simple.cpp:18:9:18:9 | *#this [b_] | simple.cpp:18:9:18:9 | ReturnIndirection [b_] | | simple.cpp:18:22:18:23 | FieldAddress [read] | simple.cpp:18:9:18:9 | ReturnValue | | simple.cpp:18:22:18:23 | this [read] [a_] | simple.cpp:18:22:18:23 | FieldAddress [read] | | simple.cpp:19:9:19:9 | this [b_] | simple.cpp:19:22:19:23 | this [read] [b_] | @@ -741,36 +747,40 @@ edges | simple.cpp:21:10:21:13 | *#this [a_] | simple.cpp:21:10:21:13 | ReturnIndirection [a_] | | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | b_ [post update] | | simple.cpp:21:24:21:25 | b_ [post update] | simple.cpp:21:24:21:25 | this [post update] [b_] | -| simple.cpp:26:15:26:15 | f [a_] | simple.cpp:28:12:28:12 | f [a_] | -| simple.cpp:26:15:26:15 | f [b_] | simple.cpp:29:12:29:12 | f [b_] | -| simple.cpp:28:12:28:12 | f [a_] | simple.cpp:18:9:18:9 | this [a_] | -| simple.cpp:28:12:28:12 | f [a_] | simple.cpp:28:12:28:12 | call to a | +| simple.cpp:26:15:26:15 | *f [a_] | simple.cpp:28:10:28:10 | f indirection [a_] | +| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:28:10:28:10 | f indirection [b_] | +| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:29:12:29:12 | f [b_] | +| simple.cpp:28:10:28:10 | a output argument [b_] | simple.cpp:29:12:29:12 | f [b_] | +| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:18:9:18:9 | *#this [a_] | +| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:28:12:28:12 | call to a | +| simple.cpp:28:10:28:10 | f indirection [b_] | simple.cpp:18:9:18:9 | *#this [b_] | +| simple.cpp:28:10:28:10 | f indirection [b_] | simple.cpp:28:10:28:10 | a output argument [b_] | | simple.cpp:29:12:29:12 | f [b_] | simple.cpp:19:9:19:9 | this [b_] | | simple.cpp:29:12:29:12 | f [b_] | simple.cpp:29:12:29:12 | call to b | | simple.cpp:39:7:39:10 | call to user_input | simple.cpp:20:19:20:19 | a | | simple.cpp:39:7:39:10 | call to user_input | simple.cpp:39:7:39:10 | f [post update] [a_] | -| simple.cpp:39:7:39:10 | f [post update] [a_] | simple.cpp:45:5:45:7 | f [a_] | +| simple.cpp:39:7:39:10 | f [post update] [a_] | simple.cpp:45:9:45:9 | f indirection [a_] | | simple.cpp:39:12:39:21 | call to user_input | simple.cpp:39:7:39:10 | call to user_input | | simple.cpp:40:7:40:10 | call to user_input | simple.cpp:21:19:21:19 | b | | simple.cpp:40:7:40:10 | call to user_input | simple.cpp:40:7:40:10 | g [post update] [b_] | -| simple.cpp:40:7:40:10 | g [post update] [b_] | simple.cpp:48:5:48:7 | g [b_] | +| simple.cpp:40:7:40:10 | g [post update] [b_] | simple.cpp:48:9:48:9 | g indirection [b_] | | simple.cpp:40:12:40:21 | call to user_input | simple.cpp:40:7:40:10 | call to user_input | | simple.cpp:41:7:41:10 | call to user_input | simple.cpp:20:19:20:19 | a | | simple.cpp:41:7:41:10 | call to user_input | simple.cpp:41:7:41:10 | h [post update] [a_] | | simple.cpp:41:7:41:10 | h [post update] [a_] | simple.cpp:42:5:42:5 | h indirection [a_] | -| simple.cpp:41:7:41:10 | h [post update] [a_] | simple.cpp:51:5:51:7 | h [a_] | +| simple.cpp:41:7:41:10 | h [post update] [a_] | simple.cpp:51:9:51:9 | h indirection [a_] | | simple.cpp:41:12:41:21 | call to user_input | simple.cpp:41:7:41:10 | call to user_input | | simple.cpp:42:5:42:5 | h indirection [a_] | simple.cpp:21:10:21:13 | *#this [a_] | | simple.cpp:42:5:42:5 | h indirection [a_] | simple.cpp:42:5:42:5 | setB output argument [a_] | -| simple.cpp:42:5:42:5 | setB output argument [a_] | simple.cpp:51:5:51:7 | h [a_] | +| simple.cpp:42:5:42:5 | setB output argument [a_] | simple.cpp:51:9:51:9 | h indirection [a_] | | simple.cpp:42:7:42:10 | call to user_input | simple.cpp:21:19:21:19 | b | | simple.cpp:42:7:42:10 | call to user_input | simple.cpp:42:7:42:10 | h [post update] [b_] | -| simple.cpp:42:7:42:10 | h [post update] [b_] | simple.cpp:51:5:51:7 | h [b_] | +| simple.cpp:42:7:42:10 | h [post update] [b_] | simple.cpp:51:9:51:9 | h indirection [b_] | | simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:7:42:10 | call to user_input | -| simple.cpp:45:5:45:7 | f [a_] | simple.cpp:26:15:26:15 | f [a_] | -| simple.cpp:48:5:48:7 | g [b_] | simple.cpp:26:15:26:15 | f [b_] | -| simple.cpp:51:5:51:7 | h [a_] | simple.cpp:26:15:26:15 | f [a_] | -| simple.cpp:51:5:51:7 | h [b_] | simple.cpp:26:15:26:15 | f [b_] | +| simple.cpp:45:9:45:9 | f indirection [a_] | simple.cpp:26:15:26:15 | *f [a_] | +| simple.cpp:48:9:48:9 | g indirection [b_] | simple.cpp:26:15:26:15 | *f [b_] | +| simple.cpp:51:9:51:9 | h indirection [a_] | simple.cpp:26:15:26:15 | *f [a_] | +| simple.cpp:51:9:51:9 | h indirection [b_] | simple.cpp:26:15:26:15 | *f [b_] | | simple.cpp:65:5:65:5 | a [post update] [i] | simple.cpp:67:10:67:11 | a2 [read] [i] | | simple.cpp:65:7:65:7 | i [post update] | simple.cpp:65:5:65:5 | a [post update] [i] | | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:7:65:7 | i [post update] | @@ -791,28 +801,48 @@ edges | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:7:92:7 | i [post update] | | simple.cpp:94:10:94:11 | a2 [read] [i] | simple.cpp:94:13:94:13 | FieldAddress [read] | | simple.cpp:94:13:94:13 | FieldAddress [read] | simple.cpp:94:13:94:13 | i | +| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | ReturnIndirection [a] | | struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:8:15:9 | ab [read] [a] | | struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [read] [a] | | struct_init.c:15:8:15:9 | ab [read] [a] | struct_init.c:15:12:15:12 | FieldAddress [read] | +| struct_init.c:15:8:15:9 | ab [read] [a] | struct_init.c:15:12:15:12 | FieldAddress [read] | +| struct_init.c:15:12:15:12 | FieldAddress [read] | struct_init.c:15:12:15:12 | a | | struct_init.c:15:12:15:12 | FieldAddress [read] | struct_init.c:15:12:15:12 | a | | struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | struct_init.c:22:8:22:9 | ab [read] [a] | | struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | struct_init.c:24:10:24:12 | & ... indirection [a] | +| struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | | struct_init.c:20:17:20:36 | FieldAddress [post update] | struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:17:20:36 | FieldAddress [post update] | | struct_init.c:22:8:22:9 | ab [read] [a] | struct_init.c:22:11:22:11 | FieldAddress [read] | | struct_init.c:22:11:22:11 | FieldAddress [read] | struct_init.c:22:11:22:11 | a | | struct_init.c:24:10:24:12 | & ... indirection [a] | struct_init.c:14:24:14:25 | *ab [a] | +| struct_init.c:24:10:24:12 | & ... indirection [a] | struct_init.c:24:10:24:12 | absink output argument [a] | +| struct_init.c:24:10:24:12 | absink output argument [a] | struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | | struct_init.c:26:16:26:20 | VariableAddress [post update] [nestedAB, a] | struct_init.c:31:8:31:12 | outer [read] [nestedAB, a] | | struct_init.c:26:16:26:20 | VariableAddress [post update] [nestedAB, a] | struct_init.c:36:11:36:15 | outer [read] [nestedAB, a] | +| struct_init.c:26:16:26:20 | VariableAddress [post update] [pointerAB, a] | struct_init.c:33:8:33:12 | outer [read] [pointerAB, a] | | struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | struct_init.c:26:16:26:20 | VariableAddress [post update] [nestedAB, a] | +| struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | struct_init.c:26:16:26:20 | VariableAddress [post update] [pointerAB, a] | | struct_init.c:27:5:27:23 | FieldAddress [post update] | struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:5:27:23 | FieldAddress [post update] | | struct_init.c:31:8:31:12 | outer [read] [nestedAB, a] | struct_init.c:31:14:31:21 | nestedAB [read] [a] | | struct_init.c:31:14:31:21 | nestedAB [read] [a] | struct_init.c:31:23:31:23 | FieldAddress [read] | | struct_init.c:31:23:31:23 | FieldAddress [read] | struct_init.c:31:23:31:23 | a | +| struct_init.c:33:8:33:12 | outer [read] [pointerAB, a] | struct_init.c:33:14:33:22 | FieldAddress [read] [a] | +| struct_init.c:33:14:33:22 | FieldAddress [read] [a] | struct_init.c:33:14:33:22 | pointerAB [read] [a] | +| struct_init.c:33:14:33:22 | pointerAB [read] [a] | struct_init.c:33:25:33:25 | FieldAddress [read] | +| struct_init.c:33:25:33:25 | FieldAddress [read] | struct_init.c:33:25:33:25 | a | | struct_init.c:36:3:36:8 | & ... [a] | struct_init.c:14:24:14:25 | ab [a] | | struct_init.c:36:11:36:15 | outer [read] [nestedAB, a] | struct_init.c:36:17:36:24 | nestedAB [read] [a] | | struct_init.c:36:17:36:24 | nestedAB [read] [a] | struct_init.c:36:3:36:8 | & ... [a] | +| struct_init.c:40:13:40:14 | VariableAddress [post update] [a] | struct_init.c:41:23:44:3 | FieldAddress [post update] [a] | +| struct_init.c:40:17:40:36 | FieldAddress [post update] | struct_init.c:40:13:40:14 | VariableAddress [post update] [a] | +| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:40:17:40:36 | FieldAddress [post update] | +| struct_init.c:41:16:41:20 | VariableAddress [post update] [pointerAB, a] | struct_init.c:46:10:46:14 | outer [read] [pointerAB, a] | +| struct_init.c:41:23:44:3 | FieldAddress [post update] [a] | struct_init.c:41:16:41:20 | VariableAddress [post update] [pointerAB, a] | +| struct_init.c:46:3:46:8 | pointerAB [a] | struct_init.c:14:24:14:25 | ab [a] | +| struct_init.c:46:10:46:14 | outer [read] [pointerAB, a] | struct_init.c:46:16:46:24 | FieldAddress [read] [a] | +| struct_init.c:46:16:46:24 | FieldAddress [read] [a] | struct_init.c:46:3:46:8 | pointerAB [a] | nodes | A.cpp:23:10:23:10 | c | semmle.label | c | | A.cpp:25:7:25:10 | this [post update] [c] | semmle.label | this [post update] [c] | @@ -1366,8 +1396,8 @@ nodes | complex.cpp:12:17:12:17 | b | semmle.label | b | | complex.cpp:12:22:12:23 | b_ [post update] | semmle.label | b_ [post update] | | complex.cpp:12:22:12:23 | this [post update] [b_] | semmle.label | this [post update] [b_] | -| complex.cpp:40:17:40:17 | b [inner, f, a_] | semmle.label | b [inner, f, a_] | -| complex.cpp:40:17:40:17 | b [inner, f, b_] | semmle.label | b [inner, f, b_] | +| complex.cpp:40:17:40:17 | *b [inner, f, a_] | semmle.label | *b [inner, f, a_] | +| complex.cpp:40:17:40:17 | *b [inner, f, b_] | semmle.label | *b [inner, f, b_] | | complex.cpp:42:8:42:8 | (reference dereference) [read] [inner, f, a_] | semmle.label | (reference dereference) [read] [inner, f, a_] | | complex.cpp:42:10:42:14 | inner [read] [f, a_] | semmle.label | inner [read] [f, a_] | | complex.cpp:42:16:42:16 | f [read] [a_] | semmle.label | f [read] [a_] | @@ -1402,10 +1432,10 @@ nodes | complex.cpp:56:14:56:17 | call to user_input | semmle.label | call to user_input | | complex.cpp:56:14:56:17 | f [post update] [b_] | semmle.label | f [post update] [b_] | | complex.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:59:3:59:5 | b1 [inner, f, a_] | semmle.label | b1 [inner, f, a_] | -| complex.cpp:62:3:62:5 | b2 [inner, f, b_] | semmle.label | b2 [inner, f, b_] | -| complex.cpp:65:3:65:5 | b3 [inner, f, a_] | semmle.label | b3 [inner, f, a_] | -| complex.cpp:65:3:65:5 | b3 [inner, f, b_] | semmle.label | b3 [inner, f, b_] | +| complex.cpp:59:7:59:8 | b1 indirection [inner, f, a_] | semmle.label | b1 indirection [inner, f, a_] | +| complex.cpp:62:7:62:8 | b2 indirection [inner, f, b_] | semmle.label | b2 indirection [inner, f, b_] | +| complex.cpp:65:7:65:8 | b3 indirection [inner, f, a_] | semmle.label | b3 indirection [inner, f, a_] | +| complex.cpp:65:7:65:8 | b3 indirection [inner, f, b_] | semmle.label | b3 indirection [inner, f, b_] | | conflated.cpp:10:4:10:5 | (reference dereference) [post update] [p] | semmle.label | (reference dereference) [post update] [p] | | conflated.cpp:10:7:10:7 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | | conflated.cpp:10:11:10:20 | call to user_input | semmle.label | call to user_input | @@ -1447,8 +1477,10 @@ nodes | conflated.cpp:61:12:61:15 | next [read] [y] | semmle.label | next [read] [y] | | conflated.cpp:61:18:61:18 | FieldAddress [read] | semmle.label | FieldAddress [read] | | conflated.cpp:61:18:61:18 | y | semmle.label | y | +| constructors.cpp:18:9:18:9 | *#this [a_] | semmle.label | *#this [a_] | +| constructors.cpp:18:9:18:9 | *#this [b_] | semmle.label | *#this [b_] | +| constructors.cpp:18:9:18:9 | ReturnIndirection [b_] | semmle.label | ReturnIndirection [b_] | | constructors.cpp:18:9:18:9 | ReturnValue | semmle.label | ReturnValue | -| constructors.cpp:18:9:18:9 | this [a_] | semmle.label | this [a_] | | constructors.cpp:18:22:18:23 | FieldAddress [read] | semmle.label | FieldAddress [read] | | constructors.cpp:18:22:18:23 | this [read] [a_] | semmle.label | this [read] [a_] | | constructors.cpp:19:9:19:9 | ReturnValue | semmle.label | ReturnValue | @@ -1461,10 +1493,12 @@ nodes | constructors.cpp:23:20:23:20 | b | semmle.label | b | | constructors.cpp:23:25:23:29 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | | constructors.cpp:23:32:23:36 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | -| constructors.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] | -| constructors.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] | +| constructors.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] | +| constructors.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] | +| constructors.cpp:28:10:28:10 | a output argument [b_] | semmle.label | a output argument [b_] | +| constructors.cpp:28:10:28:10 | f indirection [a_] | semmle.label | f indirection [a_] | +| constructors.cpp:28:10:28:10 | f indirection [b_] | semmle.label | f indirection [b_] | | constructors.cpp:28:12:28:12 | call to a | semmle.label | call to a | -| constructors.cpp:28:12:28:12 | f [a_] | semmle.label | f [a_] | | constructors.cpp:29:12:29:12 | call to b | semmle.label | call to b | | constructors.cpp:29:12:29:12 | f [b_] | semmle.label | f [b_] | | constructors.cpp:34:11:34:20 | call to user_input | semmle.label | call to user_input | @@ -1479,10 +1513,10 @@ nodes | constructors.cpp:36:11:36:37 | call to user_input | semmle.label | call to user_input | | constructors.cpp:36:11:36:37 | call to user_input | semmle.label | call to user_input | | constructors.cpp:36:25:36:34 | call to user_input | semmle.label | call to user_input | -| constructors.cpp:40:5:40:7 | f [a_] | semmle.label | f [a_] | -| constructors.cpp:43:5:43:7 | g [b_] | semmle.label | g [b_] | -| constructors.cpp:46:5:46:7 | h [a_] | semmle.label | h [a_] | -| constructors.cpp:46:5:46:7 | h [b_] | semmle.label | h [b_] | +| constructors.cpp:40:9:40:9 | f indirection [a_] | semmle.label | f indirection [a_] | +| constructors.cpp:43:9:43:9 | g indirection [b_] | semmle.label | g indirection [b_] | +| constructors.cpp:46:9:46:9 | h indirection [a_] | semmle.label | h indirection [a_] | +| constructors.cpp:46:9:46:9 | h indirection [b_] | semmle.label | h indirection [b_] | | qualifiers.cpp:9:21:9:25 | value | semmle.label | value | | qualifiers.cpp:9:30:9:33 | this [post update] [a] | semmle.label | this [post update] [a] | | qualifiers.cpp:9:36:9:36 | a [post update] | semmle.label | a [post update] | @@ -1568,8 +1602,10 @@ nodes | realistic.cpp:61:32:61:34 | baz [read] [userInput, bufferLen] | semmle.label | baz [read] [userInput, bufferLen] | | realistic.cpp:61:37:61:45 | userInput [read] [bufferLen] | semmle.label | userInput [read] [bufferLen] | | realistic.cpp:61:47:61:55 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| simple.cpp:18:9:18:9 | *#this [a_] | semmle.label | *#this [a_] | +| simple.cpp:18:9:18:9 | *#this [b_] | semmle.label | *#this [b_] | +| simple.cpp:18:9:18:9 | ReturnIndirection [b_] | semmle.label | ReturnIndirection [b_] | | simple.cpp:18:9:18:9 | ReturnValue | semmle.label | ReturnValue | -| simple.cpp:18:9:18:9 | this [a_] | semmle.label | this [a_] | | simple.cpp:18:22:18:23 | FieldAddress [read] | semmle.label | FieldAddress [read] | | simple.cpp:18:22:18:23 | this [read] [a_] | semmle.label | this [read] [a_] | | simple.cpp:19:9:19:9 | ReturnValue | semmle.label | ReturnValue | @@ -1584,10 +1620,12 @@ nodes | simple.cpp:21:19:21:19 | b | semmle.label | b | | simple.cpp:21:24:21:25 | b_ [post update] | semmle.label | b_ [post update] | | simple.cpp:21:24:21:25 | this [post update] [b_] | semmle.label | this [post update] [b_] | -| simple.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] | -| simple.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] | +| simple.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] | +| simple.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] | +| simple.cpp:28:10:28:10 | a output argument [b_] | semmle.label | a output argument [b_] | +| simple.cpp:28:10:28:10 | f indirection [a_] | semmle.label | f indirection [a_] | +| simple.cpp:28:10:28:10 | f indirection [b_] | semmle.label | f indirection [b_] | | simple.cpp:28:12:28:12 | call to a | semmle.label | call to a | -| simple.cpp:28:12:28:12 | f [a_] | semmle.label | f [a_] | | simple.cpp:29:12:29:12 | call to b | semmle.label | call to b | | simple.cpp:29:12:29:12 | f [b_] | semmle.label | f [b_] | | simple.cpp:39:7:39:10 | call to user_input | semmle.label | call to user_input | @@ -1604,10 +1642,10 @@ nodes | simple.cpp:42:7:42:10 | call to user_input | semmle.label | call to user_input | | simple.cpp:42:7:42:10 | h [post update] [b_] | semmle.label | h [post update] [b_] | | simple.cpp:42:12:42:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:45:5:45:7 | f [a_] | semmle.label | f [a_] | -| simple.cpp:48:5:48:7 | g [b_] | semmle.label | g [b_] | -| simple.cpp:51:5:51:7 | h [a_] | semmle.label | h [a_] | -| simple.cpp:51:5:51:7 | h [b_] | semmle.label | h [b_] | +| simple.cpp:45:9:45:9 | f indirection [a_] | semmle.label | f indirection [a_] | +| simple.cpp:48:9:48:9 | g indirection [b_] | semmle.label | g indirection [b_] | +| simple.cpp:51:9:51:9 | h indirection [a_] | semmle.label | h indirection [a_] | +| simple.cpp:51:9:51:9 | h indirection [b_] | semmle.label | h indirection [b_] | | simple.cpp:65:5:65:5 | a [post update] [i] | semmle.label | a [post update] [i] | | simple.cpp:65:7:65:7 | i [post update] | semmle.label | i [post update] | | simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input | @@ -1632,8 +1670,11 @@ nodes | simple.cpp:94:13:94:13 | FieldAddress [read] | semmle.label | FieldAddress [read] | | simple.cpp:94:13:94:13 | i | semmle.label | i | | struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] | +| struct_init.c:14:24:14:25 | ReturnIndirection [a] | semmle.label | ReturnIndirection [a] | | struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] | | struct_init.c:15:8:15:9 | ab [read] [a] | semmle.label | ab [read] [a] | +| struct_init.c:15:8:15:9 | ab [read] [a] | semmle.label | ab [read] [a] | +| struct_init.c:15:12:15:12 | FieldAddress [read] | semmle.label | FieldAddress [read] | | struct_init.c:15:12:15:12 | FieldAddress [read] | semmle.label | FieldAddress [read] | | struct_init.c:15:12:15:12 | a | semmle.label | a | | struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | semmle.label | VariableAddress [post update] [a] | @@ -1643,7 +1684,10 @@ nodes | struct_init.c:22:11:22:11 | FieldAddress [read] | semmle.label | FieldAddress [read] | | struct_init.c:22:11:22:11 | a | semmle.label | a | | struct_init.c:24:10:24:12 | & ... indirection [a] | semmle.label | & ... indirection [a] | +| struct_init.c:24:10:24:12 | absink output argument [a] | semmle.label | absink output argument [a] | | struct_init.c:26:16:26:20 | VariableAddress [post update] [nestedAB, a] | semmle.label | VariableAddress [post update] [nestedAB, a] | +| struct_init.c:26:16:26:20 | VariableAddress [post update] [pointerAB, a] | semmle.label | VariableAddress [post update] [pointerAB, a] | +| struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | | struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | | struct_init.c:27:5:27:23 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | | struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input | @@ -1651,9 +1695,22 @@ nodes | struct_init.c:31:14:31:21 | nestedAB [read] [a] | semmle.label | nestedAB [read] [a] | | struct_init.c:31:23:31:23 | FieldAddress [read] | semmle.label | FieldAddress [read] | | struct_init.c:31:23:31:23 | a | semmle.label | a | +| struct_init.c:33:8:33:12 | outer [read] [pointerAB, a] | semmle.label | outer [read] [pointerAB, a] | +| struct_init.c:33:14:33:22 | FieldAddress [read] [a] | semmle.label | FieldAddress [read] [a] | +| struct_init.c:33:14:33:22 | pointerAB [read] [a] | semmle.label | pointerAB [read] [a] | +| struct_init.c:33:25:33:25 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| struct_init.c:33:25:33:25 | a | semmle.label | a | | struct_init.c:36:3:36:8 | & ... [a] | semmle.label | & ... [a] | | struct_init.c:36:11:36:15 | outer [read] [nestedAB, a] | semmle.label | outer [read] [nestedAB, a] | | struct_init.c:36:17:36:24 | nestedAB [read] [a] | semmle.label | nestedAB [read] [a] | +| struct_init.c:40:13:40:14 | VariableAddress [post update] [a] | semmle.label | VariableAddress [post update] [a] | +| struct_init.c:40:17:40:36 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | +| struct_init.c:40:20:40:29 | call to user_input | semmle.label | call to user_input | +| struct_init.c:41:16:41:20 | VariableAddress [post update] [pointerAB, a] | semmle.label | VariableAddress [post update] [pointerAB, a] | +| struct_init.c:41:23:44:3 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | +| struct_init.c:46:3:46:8 | pointerAB [a] | semmle.label | pointerAB [a] | +| struct_init.c:46:10:46:14 | outer [read] [pointerAB, a] | semmle.label | outer [read] [pointerAB, a] | +| struct_init.c:46:16:46:24 | FieldAddress [read] [a] | semmle.label | FieldAddress [read] [a] | subpaths | A.cpp:31:14:31:21 | c | A.cpp:23:10:23:10 | c | A.cpp:25:7:25:10 | this [post update] [c] | A.cpp:31:14:31:21 | new [post update] [c] | | A.cpp:48:12:48:18 | c | A.cpp:29:23:29:23 | c | A.cpp:29:15:29:18 | ReturnValue [c] | A.cpp:48:12:48:18 | call to make [c] | @@ -1698,7 +1755,8 @@ subpaths | complex.cpp:54:14:54:17 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | this [post update] [b_] | complex.cpp:54:14:54:17 | f [post update] [b_] | | complex.cpp:55:14:55:17 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | this [post update] [a_] | complex.cpp:55:14:55:17 | f [post update] [a_] | | complex.cpp:56:14:56:17 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | this [post update] [b_] | complex.cpp:56:14:56:17 | f [post update] [b_] | -| constructors.cpp:28:12:28:12 | f [a_] | constructors.cpp:18:9:18:9 | this [a_] | constructors.cpp:18:9:18:9 | ReturnValue | constructors.cpp:28:12:28:12 | call to a | +| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:18:9:18:9 | *#this [a_] | constructors.cpp:18:9:18:9 | ReturnValue | constructors.cpp:28:12:28:12 | call to a | +| constructors.cpp:28:10:28:10 | f indirection [b_] | constructors.cpp:18:9:18:9 | *#this [b_] | constructors.cpp:18:9:18:9 | ReturnIndirection [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] | | constructors.cpp:29:12:29:12 | f [b_] | constructors.cpp:19:9:19:9 | this [b_] | constructors.cpp:19:9:19:9 | ReturnValue | constructors.cpp:29:12:29:12 | call to b | | constructors.cpp:34:11:34:26 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | this [post update] [a_] | constructors.cpp:34:11:34:26 | Argument this [post update] [a_] | | constructors.cpp:35:11:35:26 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | this [post update] [b_] | constructors.cpp:35:11:35:26 | Argument this [post update] [b_] | @@ -1708,7 +1766,8 @@ subpaths | qualifiers.cpp:32:5:32:15 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:53 | inner [post update] [a] | qualifiers.cpp:32:5:32:15 | call to getInner [post update] [a] | | qualifiers.cpp:37:5:37:17 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:55 | (reference dereference) [post update] [a] | qualifiers.cpp:37:5:37:17 | * ... [post update] [a] | | qualifiers.cpp:37:5:37:17 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:55 | inner [post update] [a] | qualifiers.cpp:37:5:37:17 | * ... [post update] [a] | -| simple.cpp:28:12:28:12 | f [a_] | simple.cpp:18:9:18:9 | this [a_] | simple.cpp:18:9:18:9 | ReturnValue | simple.cpp:28:12:28:12 | call to a | +| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:18:9:18:9 | *#this [a_] | simple.cpp:18:9:18:9 | ReturnValue | simple.cpp:28:12:28:12 | call to a | +| simple.cpp:28:10:28:10 | f indirection [b_] | simple.cpp:18:9:18:9 | *#this [b_] | simple.cpp:18:9:18:9 | ReturnIndirection [b_] | simple.cpp:28:10:28:10 | a output argument [b_] | | simple.cpp:29:12:29:12 | f [b_] | simple.cpp:19:9:19:9 | this [b_] | simple.cpp:19:9:19:9 | ReturnValue | simple.cpp:29:12:29:12 | call to b | | simple.cpp:39:7:39:10 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | this [post update] [a_] | simple.cpp:39:7:39:10 | f [post update] [a_] | | simple.cpp:40:7:40:10 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | this [post update] [b_] | simple.cpp:40:7:40:10 | g [post update] [b_] | @@ -1716,6 +1775,7 @@ subpaths | simple.cpp:42:5:42:5 | h indirection [a_] | simple.cpp:21:10:21:13 | *#this [a_] | simple.cpp:21:10:21:13 | ReturnIndirection [a_] | simple.cpp:42:5:42:5 | setB output argument [a_] | | simple.cpp:42:7:42:10 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | this [post update] [b_] | simple.cpp:42:7:42:10 | h [post update] [b_] | | simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:78:9:78:15 | this [f2, f1] | simple.cpp:78:9:78:15 | ReturnValue | simple.cpp:84:14:84:20 | call to getf2f1 | +| struct_init.c:24:10:24:12 | & ... indirection [a] | struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | ReturnIndirection [a] | struct_init.c:24:10:24:12 | absink output argument [a] | #select | A.cpp:49:10:49:13 | (void *)... | A.cpp:47:12:47:18 | new | A.cpp:49:10:49:13 | (void *)... | (void *)... flows from $@ | A.cpp:47:12:47:18 | new | new | | A.cpp:56:10:56:17 | (void *)... | A.cpp:55:12:55:19 | (C *)... | A.cpp:56:10:56:17 | (void *)... | (void *)... flows from $@ | A.cpp:55:12:55:19 | (C *)... | (C *)... | @@ -1822,5 +1882,7 @@ subpaths | simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input | | struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input | | struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input | +| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | 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 | +| struct_init.c:33:25:33:25 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:33:25:33:25 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input | diff --git a/cpp/ql/test/library-tests/dataflow/fields/struct_init.c b/cpp/ql/test/library-tests/dataflow/fields/struct_init.c index 862a3ed42828..d2abfeefc086 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/struct_init.c +++ b/cpp/ql/test/library-tests/dataflow/fields/struct_init.c @@ -12,7 +12,7 @@ struct Outer { }; void absink(struct AB *ab) { - sink(ab->a); //$ ast,ir=20:20 ast,ir=27:7 ast=40:20 MISSING: ir + sink(ab->a); //$ ast,ir=20:20 ast,ir=27:7 ast,ir=40:20 sink(ab->b); // no flow } @@ -30,7 +30,7 @@ int struct_init(void) { sink(outer.nestedAB.a); //$ ast,ir sink(outer.nestedAB.b); // no flow - sink(outer.pointerAB->a); //$ ast MISSING: ir + sink(outer.pointerAB->a); //$ ast,ir sink(outer.pointerAB->b); // no flow absink(&outer.nestedAB); diff --git a/cpp/ql/test/library-tests/dataflow/smart-pointers-taint/test.cpp b/cpp/ql/test/library-tests/dataflow/smart-pointers-taint/test.cpp index 0e890f8aec46..532a39ea7b21 100644 --- a/cpp/ql/test/library-tests/dataflow/smart-pointers-taint/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/smart-pointers-taint/test.cpp @@ -21,9 +21,9 @@ void test_unique_ptr_struct() { std::unique_ptr p1(new A{source(), 0}); std::unique_ptr p2 = std::make_unique(source(), 0); - sink(p1->x); // $ ir MISSING: ast + sink(p1->x); // $ MISSING: ast,ir sink(p1->y); - sink(p2->x); // $ ir=22:46 MISSING: ast + sink(p2->x); // $ MISSING: ast,ir=22:46 sink(p2->y); } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index c2a70eae4fec..ebbde802ff3f 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -126,15 +126,15 @@ void pointer_test() { *p2 = source(); - sink(*p1); // $ ast MISSING: ir + sink(*p1); // $ ast,ir sink(*p2); // $ ast,ir sink(*p3); p3 = &t1; - sink(*p3); // $ ast MISSING: ir + sink(*p3); // $ ast,ir *p3 = 0; - sink(*p3); // $ SPURIOUS: ast + sink(*p3); // $ SPURIOUS: ast,ir } // --- return values --- diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected index b9a0f7b36317..a33270b0b6a7 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected @@ -26,9 +26,35 @@ edges | test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | (const char *)... | | test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | | test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer indirection | +| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | (const char *)... | +| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | +| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | +| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data indirection | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | (const char *)... | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | (reference dereference) | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref indirection | +| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | (const char *)... | +| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | +| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | +| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 indirection | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | (const char *)... | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | (const char *)... | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (const char *)... | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (reference dereference) | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | (const char *)... | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection | | test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | (const char *)... | | test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | | test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer indirection | @@ -78,6 +104,29 @@ nodes | test.cpp:62:10:62:15 | buffer | semmle.label | buffer | | test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection | | test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection | +| test.cpp:63:10:63:13 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:63:10:63:13 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:63:10:63:13 | data | semmle.label | data | +| test.cpp:63:10:63:13 | data | semmle.label | data | +| test.cpp:63:10:63:13 | data | semmle.label | data | +| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection | +| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection | +| test.cpp:64:10:64:16 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:64:10:64:16 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:64:10:64:16 | (reference dereference) | semmle.label | (reference dereference) | +| test.cpp:64:10:64:16 | (reference dereference) | semmle.label | (reference dereference) | +| test.cpp:64:10:64:16 | dataref | semmle.label | dataref | +| test.cpp:64:10:64:16 | dataref | semmle.label | dataref | +| test.cpp:64:10:64:16 | dataref | semmle.label | dataref | +| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection | +| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection | +| test.cpp:65:10:65:14 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:65:10:65:14 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:65:10:65:14 | data2 | semmle.label | data2 | +| test.cpp:65:10:65:14 | data2 | semmle.label | data2 | +| test.cpp:65:10:65:14 | data2 | semmle.label | data2 | +| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection | +| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection | | test.cpp:76:12:76:17 | buffer | semmle.label | buffer | | test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument | | test.cpp:78:10:78:15 | (const char *)... | semmle.label | (const char *)... | @@ -103,6 +152,9 @@ nodes | test.cpp:26:10:26:16 | command | test.cpp:42:18:42:23 | call to getenv | test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system | test.cpp:42:18:42:23 | call to getenv | call to getenv | | test.cpp:31:10:31:16 | command | test.cpp:43:18:43:23 | call to getenv | test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system | test.cpp:43:18:43:23 | call to getenv | call to getenv | | test.cpp:62:10:62:15 | buffer | test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | The value of this argument may come from $@ and is being passed to system | test.cpp:56:12:56:17 | buffer | buffer | +| test.cpp:63:10:63:13 | data | test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | The value of this argument may come from $@ and is being passed to system | test.cpp:56:12:56:17 | buffer | buffer | +| test.cpp:64:10:64:16 | dataref | test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | The value of this argument may come from $@ and is being passed to system | test.cpp:56:12:56:17 | buffer | buffer | +| test.cpp:65:10:65:14 | data2 | test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | The value of this argument may come from $@ and is being passed to system | test.cpp:56:12:56:17 | buffer | buffer | | test.cpp:78:10:78:15 | buffer | test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | The value of this argument may come from $@ and is being passed to system | test.cpp:76:12:76:17 | buffer | buffer | | test.cpp:99:15:99:20 | buffer | test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary | test.cpp:98:17:98:22 | buffer | buffer | | test.cpp:107:15:107:20 | buffer | test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary | test.cpp:106:17:106:22 | buffer | buffer | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/test.cpp index 26aff44f3d8c..e1d738813246 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/test.cpp @@ -61,8 +61,8 @@ void testReferencePointer1() system(buffer); // BAD system(data); // BAD - system(dataref); // BAD [NOT DETECTED] - system(data2); // BAD [NOT DETECTED] + system(dataref); // BAD + system(data2); // BAD } } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected index 5a4a8eae9e29..8c1d61dcf5f8 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected @@ -108,10 +108,45 @@ edges | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:10 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:10 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:17:136:18 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:17:136:18 | i4 | | argvLocal.c:117:15:117:16 | i3 indirection | argvLocal.c:9:25:9:31 | *correct | | argvLocal.c:117:15:117:16 | i3 indirection | argvLocal.c:117:15:117:16 | printWrapper output argument | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | (const char *)... | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 | +| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 indirection | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | @@ -317,6 +352,8 @@ nodes | argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | +| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | +| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | | argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection | | argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |