Merge pull request #3419 from MathiasVP/flat-structs

C++: Add reverse reads to IR field flow
This commit is contained in:
Robert Marsh
2020-06-10 14:31:00 -07:00
committed by GitHub
10 changed files with 874 additions and 143 deletions

View File

@@ -192,32 +192,14 @@ private class ArrayContent extends Content, TArrayContent {
override Type getType() { none() }
}
private predicate storeStepNoChi(Node node1, Content f, PostUpdateNode node2) {
exists(FieldAddressInstruction fa, StoreInstruction store |
store = node2.asInstruction() and
store.getDestinationAddress() = fa and
store.getSourceValue() = node1.asInstruction() and
f.(FieldContent).getField() = fa.getField()
)
}
private predicate storeStepChi(Node node1, Content f, PostUpdateNode node2) {
exists(FieldAddressInstruction fa, StoreInstruction store |
node1.asInstruction() = store and
store.getDestinationAddress() = fa and
node2.asInstruction().(ChiInstruction).getPartial() = store and
f.(FieldContent).getField() = fa.getField()
)
}
/**
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
* Thus, `node2` references an object with a field `f` that contains the
* value of `node1`.
*/
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
storeStepNoChi(node1, f, node2) or
storeStepChi(node1, f, node2)
predicate storeStep(Node node1, Content f, StoreStepNode node2) {
node2.getStoredValue() = node1 and
f.(FieldContent).getField() = node2.getAField()
}
/**
@@ -225,13 +207,9 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
* Thus, `node1` references an object with a field `f` whose value ends up in
* `node2`.
*/
predicate readStep(Node node1, Content f, Node node2) {
exists(FieldAddressInstruction fa, LoadInstruction load |
load.getSourceAddress() = fa and
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
fa.getField() = f.(FieldContent).getField() and
load = node2.asInstruction()
)
predicate readStep(Node node1, Content f, ReadStepNode node2) {
node2.getReadValue() = node1 and
f.(FieldContent).getField() = node2.getAField()
}
/**

View File

@@ -13,7 +13,9 @@ private import semmle.code.cpp.models.interfaces.DataFlow
private newtype TIRDataFlowNode =
TInstructionNode(Instruction i) or
TVariableNode(Variable var)
TVariableNode(Variable var) or
TStoreNode(StoreChain chain) or
TLoadNode(LoadChain load)
/**
* A node in a data flow graph.
@@ -271,7 +273,7 @@ deprecated class UninitializedNode extends Node {
* This class exists to match the interface used by Java. There are currently no non-abstract
* classes that extend it. When we implement field flow, we can revisit this.
*/
abstract class PostUpdateNode extends InstructionNode {
abstract class PostUpdateNode extends Node {
/**
* Gets the node before the state update.
*/
@@ -286,59 +288,15 @@ abstract class PostUpdateNode extends InstructionNode {
* value, but does not necessarily replace it entirely. For example:
* ```
* x.y = 1; // a partial definition of the object `x`.
* x.y.z = 1; // a partial definition of the object `x.y`.
* x.y.z = 1; // a partial definition of the objects `x.y` and `x`.
* x.setY(1); // a partial definition of the object `x`.
* setY(&x); // a partial definition of the object `x`.
* ```
*/
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode {
abstract private class PartialDefinitionNode extends PostUpdateNode {
abstract Expr getDefinedExpr();
}
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
override ChiInstruction instr;
FieldAddressInstruction field;
ExplicitFieldStoreQualifierNode() {
not instr.isResultConflated() and
exists(StoreInstruction store |
instr.getPartial() = store and field = store.getDestinationAddress()
)
}
// There might be multiple `ChiInstructions` that has a particular instruction as
// the total operand - so this definition gives consistency errors in
// DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
// this consistency failure has.
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
override Expr getDefinedExpr() {
result = field.getObjectAddress().getUnconvertedResultExpression()
}
}
/**
* Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
* For instance, an update to a field of a struct containing only one field. For these cases we
* attach the PostUpdateNode to the store instruction. There's no obvious pre update node for this case
* (as the entire memory is updated), so `getPreUpdateNode` is implemented as `none()`.
*/
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
override StoreInstruction instr;
FieldAddressInstruction field;
ExplicitSingleFieldStoreQualifierNode() {
field = instr.getDestinationAddress() and
not exists(ChiInstruction chi | chi.getPartial() = instr)
}
override Node getPreUpdateNode() { none() }
override Expr getDefinedExpr() {
result = field.getObjectAddress().getUnconvertedResultExpression()
}
}
/**
* A node that represents the value of a variable after a function call that
* may have changed the variable because it's passed by reference.
@@ -430,6 +388,413 @@ class VariableNode extends Node, TVariableNode {
override string toString() { result = v.toString() }
}
/** The target node of a `readStep`. */
abstract class ReadStepNode extends Node {
/** Get the field that is read. */
abstract Field getAField();
/** Get the node representing the value that is read. */
abstract Node getReadValue();
}
/** The target node of a `storeStep`. */
abstract class StoreStepNode extends PostUpdateNode {
/** Get the field that is stored into. */
abstract Field getAField();
/** Get the node representing the value that is stored. */
abstract Node getStoredValue();
}
/**
* Sometimes a sequence of `FieldAddressInstruction`s does not end with a `StoreInstruction`.
* This class abstracts out the information needed to end a `StoreChain`.
*/
abstract private class StoreChainEndInstruction extends Instruction {
abstract FieldAddressInstruction getFieldInstruction();
abstract Instruction getBeginInstruction();
abstract Node getPreUpdateNode();
}
/**
* A `StoreInstruction` that ends a sequence of `FieldAddressInstruction`s.
*/
private class StoreChainEndInstructionStoreWithChi extends StoreChainEndInstruction, ChiInstruction {
StoreInstruction store;
FieldAddressInstruction fi;
StoreChainEndInstructionStoreWithChi() {
not this.isResultConflated() and
this.getPartial() = store and
fi = skipConversion*(store.getDestinationAddress())
}
override FieldAddressInstruction getFieldInstruction() { result = fi }
override Node getPreUpdateNode() { result.asInstruction() = this.getTotal() }
override Instruction getBeginInstruction() { result = store }
}
/**
* Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
* For instance, an update to a field of a struct containing only one field. For these cases we
* attach the PostUpdateNode to the store instruction. There's no obvious pre update node for this case
* (as the entire memory is updated), so `getPreUpdateNode` is implemented as `none()`.
*/
private class StoreChainEndInstructionStoreWithoutChi extends StoreChainEndInstruction,
StoreInstruction {
FieldAddressInstruction fi;
StoreChainEndInstructionStoreWithoutChi() {
not exists(ChiInstruction chi | chi.getPartial() = this) and
fi = skipConversion*(this.getDestinationAddress())
}
override FieldAddressInstruction getFieldInstruction() { result = fi }
override Node getPreUpdateNode() { none() }
override Instruction getBeginInstruction() { result = this.getSourceValue() }
}
/**
* When traversing dependencies between an instruction and its operands
* it is sometimes convenient to ignore certain instructions. For instance,
* the `LoadChain` for `((B&)a.b).c` inserts a `CopyValueInstruction`
* between the computed address for `b` and the `FieldAddressInstruction`
* for `c`.
*/
private Instruction skipConversion(Instruction instr) {
result = instr.(CopyInstruction).getSourceValue()
or
result = instr.(ConvertInstruction).getUnary()
or
result = instr.(CheckedConvertOrNullInstruction).getUnary()
or
result = instr.(InheritanceConversionInstruction).getUnary()
}
/**
* Ends a `StoreChain` with a `WriteSideEffectInstruction` such that we build up
* the correct access paths. For example in:
* ```
* void setter(B *b, int data) {
* b->c = data;
* }
* ...
* setter(&a.b, source());
* sink(a.b.c)
* ```
* In order to register `a.b.c` as a `readStep`, the access path must
* contain `[a, b, c]`, and thus the access path must be `[a, b]`
* before entering `setter`.
*/
private class StoreChainEndInstructionSideEffect extends StoreChainEndInstruction, ChiInstruction {
WriteSideEffectInstruction sideEffect;
FieldAddressInstruction fi;
StoreChainEndInstructionSideEffect() {
not this.isResultConflated() and
this.getPartial() = sideEffect and
fi = skipConversion*(sideEffect.getArgumentDef())
}
override FieldAddressInstruction getFieldInstruction() { result = fi }
override Node getPreUpdateNode() { result.asInstruction() = this.getTotal() }
override Instruction getBeginInstruction() { result = sideEffect }
}
private newtype TStoreChain =
TStoreChainConsNil(FieldAddressInstruction f, StoreChainEndInstruction end) {
end.getFieldInstruction() = f
} or
TStoreChainConsCons(FieldAddressInstruction f, TStoreChain next) {
exists(FieldAddressInstruction g | skipConversion*(g.getObjectAddress()) = f |
next = TStoreChainConsCons(g, _) or
next = TStoreChainConsNil(g, _)
)
}
/**
* A `StoreChain` represents a series of field lookups that compute the destination of a store.
* For example, given an assignment such as `a.b.c = x`, there are two `StoreChain`s:
* One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent
* `StoreChain` of `c`.
*/
private class StoreChain extends TStoreChain {
string toString() { none() }
/**
* Gets the parent of this `StoreChain`, if any. For example, for the assignment
* ```
* a.b.c = x;
* ```
* the parent of `c` is `b`, and `b` has no parent.
*/
final StoreChainConsCons getParent() { result.getChild() = this }
/** Gets the child of this `StoreChain`, if any. */
StoreChain getChild() { none() }
/**
* Gets the instruction that receives flow from the outermost `StoreChain` of this chain (i.e.,
* the `StoreChain` with no parent).
*/
StoreChainEndInstruction getEndInstruction() { none() }
/**
* Gets the instruction that flows to the innermost `StoreChain` of this chain (i.e.,
* the `StoreChain` with no child).
*/
Instruction getBeginInstruction() { none() }
/** Gets the `FieldAddressInstruction` of this `StoreChain` */
FieldAddressInstruction getFieldInstruction() { none() }
/** Gets the `FieldAddressInstruction` of any `StoreChain` in this chain. */
FieldAddressInstruction getAFieldInstruction() { none() }
final Location getLocation() { result = getFieldInstruction().getLocation() }
}
private class StoreChainConsNil extends StoreChain, TStoreChainConsNil {
FieldAddressInstruction fi;
StoreChainEndInstruction end;
StoreChainConsNil() { this = TStoreChainConsNil(fi, end) }
override string toString() { result = fi.getField().toString() }
override StoreChainEndInstruction getEndInstruction() { result = end }
override Instruction getBeginInstruction() { result = end.getBeginInstruction() }
override FieldAddressInstruction getFieldInstruction() { result = fi }
override FieldAddressInstruction getAFieldInstruction() { result = fi }
}
private class StoreChainConsCons extends StoreChain, TStoreChainConsCons {
FieldAddressInstruction fi;
StoreChain next;
StoreChainConsCons() { this = TStoreChainConsCons(fi, next) }
override string toString() { result = fi.getField().toString() + "." + next.toString() }
override StoreChain getChild() { result = next }
override FieldAddressInstruction getFieldInstruction() { result = fi }
override FieldAddressInstruction getAFieldInstruction() {
result = [fi, next.getAFieldInstruction()]
}
override StoreChainEndInstruction getEndInstruction() { result = next.getEndInstruction() }
override Instruction getBeginInstruction() { result = next.getBeginInstruction() }
}
private newtype TLoadChain =
TLoadChainConsNil(FieldAddressInstruction fi, LoadChainEndInstruction end) {
end.getFieldInstruction() = fi
} or
TLoadChainConsCons(FieldAddressInstruction fi, TLoadChain next) {
exists(FieldAddressInstruction nextFi | skipConversion*(nextFi.getObjectAddress()) = fi |
next = TLoadChainConsCons(nextFi, _) or
next = TLoadChainConsNil(nextFi, _)
)
}
/** This class abstracts out the information needed to end a `LoadChain`. */
abstract private class LoadChainEndInstruction extends Instruction {
abstract FieldAddressInstruction getFieldInstruction();
abstract Instruction getReadValue();
}
/**
* A `LoadInstruction` that ends a sequence of `FieldAddressInstruction`s.
*/
private class LoadChainEndInstructionLoad extends LoadChainEndInstruction, LoadInstruction {
FieldAddressInstruction fi;
LoadChainEndInstructionLoad() { fi = skipConversion*(this.getSourceAddress()) }
override FieldAddressInstruction getFieldInstruction() { result = fi }
override Instruction getReadValue() { result = getSourceValueOperand().getAnyDef() }
}
/**
* Ends a `LoadChain` with a `ReadSideEffectInstruction`. This ensures that we pop content from the
* access path when passing an argument that reads a field. For example in:
* ```
* void read_f(Inner* inner) {
* sink(inner->f);
* }
* ...
* outer.inner.f = taint();
* read_f(&outer.inner);
* ```
* In order to register `inner->f` as a `readStep`, the head of the access path must
* be `f`, and thus reading `&outer.inner` must pop `inner` from the access path
* before entering `read_f`.
*/
private class LoadChainEndInstructionSideEffect extends LoadChainEndInstruction,
ReadSideEffectInstruction {
FieldAddressInstruction fi;
LoadChainEndInstructionSideEffect() { fi = skipConversion*(this.getArgumentDef()) }
override FieldAddressInstruction getFieldInstruction() { result = fi }
override Instruction getReadValue() { result = getSideEffectOperand().getAnyDef() }
}
/**
* A `LoadChain` represents a series of field lookups that compute the source address of a load.
* For example, given the field lookup in `f(a.b.c)`, there are two `LoadChains`s:
* One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent
* `LoadChain` of `c`.
*/
private class LoadChain extends TLoadChain {
string toString() { none() }
/**
* Gets the instruction that receives flow from the innermost `LoadChain` of this chain (i.e.,
* the `LoadChain` with no child).
*/
LoadChainEndInstruction getEndInstruction() { none() }
/**
* Gets the parent of this `LoadChain`, if any. For example in `f(a.b.c)` the parent of `c` is `b`,
* and `b` has no parent.
*/
final LoadChainConsCons getParent() { result.getChild() = this }
/** Gets the child of this `LoadChain`, if any. */
LoadChain getChild() { none() }
/** Gets the `FieldAddressInstruction` of this `LoadChain` */
FieldAddressInstruction getFieldInstruction() { none() }
final Location getLocation() { result = getFieldInstruction().getLocation() }
}
private class LoadChainConsNil extends LoadChain, TLoadChainConsNil {
FieldAddressInstruction fi;
LoadChainEndInstruction end;
LoadChainConsNil() { this = TLoadChainConsNil(fi, end) }
override string toString() { result = fi.getField().toString() }
override LoadChainEndInstruction getEndInstruction() { result = end }
override FieldAddressInstruction getFieldInstruction() { result = fi }
}
private class LoadChainConsCons extends LoadChain, TLoadChainConsCons {
FieldAddressInstruction fi;
LoadChain next;
LoadChainConsCons() { this = TLoadChainConsCons(fi, next) }
override string toString() { result = fi.getField().toString() + "." + next.toString() }
override LoadChainEndInstruction getEndInstruction() { result = next.getEndInstruction() }
override LoadChain getChild() { result = next }
override FieldAddressInstruction getFieldInstruction() { result = fi }
}
/**
* A dataflow node generated by a partial definition.
* The `StoreNode` class extends `ReadStepNode` to participate in reverse read steps.
* A reverse read is a store step that is "inferred" by the DataFlow library. For example in the
* assignment:
* ```
* a.b.c = x;
* ```
* Here, the access path after the store must reflect that a value has been stored into the field `c` of
* the object at field `b`. The field `c` is added to the access path through a `storeStep`, and the
* field `b` is inferred by the DataFlow library because there's a read step (reading the field `b`) from
* the pre update node for `b.c` to the pre update node for `c`.
*/
private class StoreNode extends TStoreNode, StoreStepNode, ReadStepNode, PartialDefinitionNode {
StoreChain storeChain;
StoreNode() { this = TStoreNode(storeChain) }
override string toString() { result = storeChain.toString() }
StoreChain getStoreChain() { result = storeChain }
override Node getPreUpdateNode() {
result.(StoreNode).getStoreChain() = storeChain.getParent()
or
not exists(storeChain.getParent()) and
result = storeChain.getEndInstruction().getPreUpdateNode()
}
override Field getAField() { result = storeChain.getFieldInstruction().getField() }
override Node getStoredValue() {
// Only the `StoreNode` attached to the end of the `StoreChain` has a `getStoredValue()`, so
// this is the only `StoreNode` that matches storeStep.
not exists(storeChain.getChild()) and result.asInstruction() = storeChain.getBeginInstruction()
}
override Node getReadValue() { result = getPreUpdateNode() }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Function getFunction() { result = storeChain.getEndInstruction().getEnclosingFunction() }
override Type getType() { result = storeChain.getEndInstruction().getResultType() }
override Location getLocation() { result = storeChain.getEndInstruction().getLocation() }
override Expr getDefinedExpr() {
result = storeChain.getAFieldInstruction().getObjectAddress().getUnconvertedResultExpression()
}
}
/** A dataflow node generated by loading from an address computed by a sequence of fields lookups. */
private class LoadNode extends TLoadNode, ReadStepNode {
LoadChain loadChain;
LoadNode() { this = TLoadNode(loadChain) }
override Field getAField() { result = loadChain.getFieldInstruction().getField() }
override Node getReadValue() {
result.(LoadNode).getLoadChain() = loadChain.getParent()
or
not exists(loadChain.getParent()) and
result.asInstruction() = loadChain.getEndInstruction().getReadValue()
}
LoadChain getLoadChain() { result = loadChain }
override string toString() { result = loadChain.toString() }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Function getFunction() { result = loadChain.getEndInstruction().getEnclosingFunction() }
override Type getType() { result = loadChain.getEndInstruction().getResultType() }
override Location getLocation() { result = loadChain.getEndInstruction().getLocation() }
}
/**
* Gets the node corresponding to `instr`.
*/
@@ -483,6 +848,22 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
*/
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
or
// When flow has gone all the way through the chain of field accesses
// `[f1,f2, ..., fn]` (from right to left) we add flow from f1 to the end instruction.
exists(StoreNode synthFrom |
synthFrom = nodeFrom and
not exists(synthFrom.getStoreChain().getParent()) and
synthFrom.getStoreChain().getEndInstruction() = nodeTo.asInstruction()
)
or
// When flow has gone all the way through the chain of field accesses
// `[f1, f2, ..., fn]` (from left to right) we add flow from fn to the end instruction.
exists(LoadNode synthFrom |
synthFrom = nodeFrom and
not exists(synthFrom.getLoadChain().getChild()) and
synthFrom.getLoadChain().getEndInstruction() = nodeTo.asInstruction()
)
}
pragma[noinline]

View File

@@ -20,7 +20,7 @@ unreachableNodeCCtx
localCallNodes
postIsNotPre
postHasUniquePre
| simple.cpp:65:5:65:22 | Store | PostUpdateNode should have one pre-update node but has 0. |
| simple.cpp:65:5:65:22 | i | PostUpdateNode should have one pre-update node but has 0. |
uniquePostUpdate
postIsInSameCallable
reverseRead

View File

@@ -1,34 +1,40 @@
edges
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Store |
| A.cpp:100:5:100:13 | Chi [a] | A.cpp:101:8:101:9 | Argument 0 indirection [a] |
| A.cpp:100:5:100:13 | Store | A.cpp:100:5:100:13 | Chi [a] |
| A.cpp:100:5:100:13 | Store | A.cpp:100:5:100:13 | a [a] |
| A.cpp:100:5:100:13 | a [a] | A.cpp:101:8:101:9 | Argument 0 indirection [a] |
| A.cpp:101:8:101:9 | Argument 0 indirection [a] | A.cpp:103:14:103:14 | *c [a] |
| A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a |
| A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a |
| A.cpp:107:16:107:16 | a | A.cpp:107:12:107:16 | (void *)... |
| A.cpp:107:16:107:16 | a | A.cpp:107:16:107:16 | a |
| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] |
| A.cpp:142:7:142:20 | Store | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:142:7:142:20 | Store | A.cpp:142:7:142:20 | c [c] |
| A.cpp:142:7:142:20 | c [c] | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Store |
| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c |
| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c |
| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] |
| A.cpp:154:13:154:13 | c | A.cpp:154:10:154:13 | (void *)... |
| A.cpp:154:13:154:13 | c | A.cpp:154:13:154:13 | c |
| aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] |
| aliasing.cpp:9:3:9:22 | Store | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:9:3:9:22 | Store | aliasing.cpp:9:3:9:22 | m1 [m1] |
| aliasing.cpp:9:3:9:22 | m1 [m1] | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Store |
| aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] |
| aliasing.cpp:13:3:13:21 | Store | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:13:3:13:21 | Store | aliasing.cpp:13:3:13:21 | m1 [m1] |
| aliasing.cpp:13:3:13:21 | m1 [m1] | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Store |
| aliasing.cpp:25:17:25:19 | Chi [m1] | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:25:17:25:19 | Chi [m1] |
| aliasing.cpp:26:19:26:20 | Chi [m1] | aliasing.cpp:30:11:30:12 | m1 |
| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:26:19:26:20 | Chi [m1] |
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:30:11:30:12 | m1 |
| aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 |
| aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] |
| aliasing.cpp:60:3:60:22 | Store | aliasing.cpp:60:3:60:22 | Chi [m1] |
| aliasing.cpp:60:3:60:22 | Store | aliasing.cpp:60:3:60:22 | m1 [m1] |
| aliasing.cpp:60:3:60:22 | m1 [m1] | aliasing.cpp:61:13:61:14 | Store [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Store |
| aliasing.cpp:61:13:61:14 | Store [m1] | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 |
| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 |
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 |
@@ -37,42 +43,113 @@ edges
| by_reference.cpp:69:22:69:23 | Argument 0 indirection [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:3:84:25 | Store | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:84:3:84:25 | Store | by_reference.cpp:84:3:84:25 | a [a] |
| by_reference.cpp:84:3:84:25 | a [a] | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | Store |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:3:88:24 | Store | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:88:3:88:24 | Store | by_reference.cpp:88:3:88:24 | a [a] |
| by_reference.cpp:88:3:88:24 | a [a] | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | Store |
| by_reference.cpp:102:21:102:39 | Chi [a] | by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:21:102:39 | Chi [a] |
| by_reference.cpp:106:21:106:41 | Chi [a] | by_reference.cpp:114:29:114:29 | a |
| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | by_reference.cpp:106:21:106:41 | Chi [a] |
| by_reference.cpp:122:21:122:38 | Chi [a] | by_reference.cpp:130:27:130:27 | a |
| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:122:21:122:38 | Chi [a] |
| by_reference.cpp:126:21:126:40 | Chi [a] | by_reference.cpp:134:29:134:29 | a |
| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | by_reference.cpp:126:21:126:40 | Chi [a] |
| simple.cpp:65:5:65:22 | Store [i] | simple.cpp:66:12:66:12 | Store [i] |
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] |
| by_reference.cpp:102:21:102:39 | Chi [inner_nested, a] | by_reference.cpp:110:27:110:27 | inner_nested.a [a] |
| by_reference.cpp:102:21:102:39 | inner_nested [inner_nested, a] | by_reference.cpp:102:21:102:39 | Chi [inner_nested, a] |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:21:102:39 | inner_nested [inner_nested, a] |
| by_reference.cpp:106:21:106:41 | Chi [inner_nested, a] | by_reference.cpp:114:29:114:29 | inner_nested.a [a] |
| by_reference.cpp:106:21:106:41 | inner_nested [inner_nested, a] | by_reference.cpp:106:21:106:41 | Chi [inner_nested, a] |
| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | by_reference.cpp:106:21:106:41 | inner_nested [inner_nested, a] |
| by_reference.cpp:110:27:110:27 | a | by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:110:27:110:27 | inner_nested.a [a] | by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:114:29:114:29 | a | by_reference.cpp:114:29:114:29 | a |
| by_reference.cpp:114:29:114:29 | inner_nested.a [a] | by_reference.cpp:114:29:114:29 | a |
| by_reference.cpp:122:21:122:38 | Chi [inner_nested, a] | by_reference.cpp:130:27:130:27 | inner_nested.a [a] |
| by_reference.cpp:122:21:122:38 | inner_nested [inner_nested, a] | by_reference.cpp:122:21:122:38 | Chi [inner_nested, a] |
| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:122:21:122:38 | inner_nested [inner_nested, a] |
| by_reference.cpp:126:21:126:40 | Chi [inner_nested, a] | by_reference.cpp:134:29:134:29 | inner_nested.a [a] |
| by_reference.cpp:126:21:126:40 | inner_nested [inner_nested, a] | by_reference.cpp:126:21:126:40 | Chi [inner_nested, a] |
| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | by_reference.cpp:126:21:126:40 | inner_nested [inner_nested, a] |
| by_reference.cpp:130:27:130:27 | a | by_reference.cpp:130:27:130:27 | a |
| by_reference.cpp:130:27:130:27 | inner_nested.a [a] | by_reference.cpp:130:27:130:27 | a |
| by_reference.cpp:134:29:134:29 | a | by_reference.cpp:134:29:134:29 | a |
| by_reference.cpp:134:29:134:29 | inner_nested.a [a] | by_reference.cpp:134:29:134:29 | a |
| simple.cpp:65:5:65:22 | i [i] | simple.cpp:66:12:66:12 | Store [i] |
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | i [i] |
| simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i |
| simple.cpp:83:9:83:28 | Chi [f1] | simple.cpp:84:14:84:20 | Argument -1 indirection [f1] |
| simple.cpp:83:9:83:28 | Store | simple.cpp:83:9:83:28 | Chi [f1] |
| simple.cpp:67:13:67:13 | i | simple.cpp:67:13:67:13 | i |
| simple.cpp:83:9:83:28 | Store | simple.cpp:83:9:83:28 | f1 [f1] |
| simple.cpp:83:9:83:28 | f1 [f1] | simple.cpp:83:9:83:28 | f2.f1 [f2, f1] |
| simple.cpp:83:9:83:28 | f2.f1 [f2, f1] | simple.cpp:84:14:84:20 | Argument -1 indirection [f2, f1] |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Store |
| simple.cpp:84:14:84:20 | Argument -1 indirection [f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| simple.cpp:84:14:84:20 | Argument -1 indirection [f2, f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| simple.cpp:108:30:108:31 | d2 [d1_2, y] | simple.cpp:111:18:111:18 | d1_2.y [y] |
| simple.cpp:111:18:111:18 | d1_2.y [y] | simple.cpp:111:18:111:18 | y |
| simple.cpp:111:18:111:18 | y | simple.cpp:111:18:111:18 | y |
| simple.cpp:114:37:114:38 | *d2 [d1_2, y] | simple.cpp:117:19:117:19 | d1_2.y [y] |
| simple.cpp:117:19:117:19 | d1_2.y [y] | simple.cpp:117:19:117:19 | y |
| simple.cpp:117:19:117:19 | y | simple.cpp:117:19:117:19 | y |
| simple.cpp:122:5:122:33 | Chi [d2_1, d1_1, ... (3)] | simple.cpp:123:27:123:30 | d2_1 [d1_1, x] |
| simple.cpp:122:5:122:33 | Store | simple.cpp:122:5:122:33 | x [x] |
| simple.cpp:122:5:122:33 | d1_1.x [d1_1, x] | simple.cpp:122:5:122:33 | d2_1.d1_1.x [d2_1, d1_1, ... (3)] |
| simple.cpp:122:5:122:33 | d2_1.d1_1.x [d2_1, d1_1, ... (3)] | simple.cpp:122:5:122:33 | Chi [d2_1, d1_1, ... (3)] |
| simple.cpp:122:5:122:33 | x [x] | simple.cpp:122:5:122:33 | d1_1.x [d1_1, x] |
| simple.cpp:122:22:122:31 | call to user_input | simple.cpp:122:5:122:33 | Store |
| simple.cpp:123:27:123:30 | Store [d1_1, x] | simple.cpp:124:20:124:20 | d1_1.x [x] |
| simple.cpp:123:27:123:30 | Store [d1_1, x] | simple.cpp:130:15:130:15 | d1_1.x [x] |
| simple.cpp:123:27:123:30 | d2_1 [d1_1, x] | simple.cpp:123:27:123:30 | Store [d1_1, x] |
| simple.cpp:124:20:124:20 | d1_1.x [x] | simple.cpp:124:20:124:20 | x |
| simple.cpp:124:20:124:20 | x | simple.cpp:124:20:124:20 | x |
| simple.cpp:130:15:130:15 | d1_1.x [x] | simple.cpp:130:15:130:15 | x |
| simple.cpp:130:15:130:15 | x | simple.cpp:130:15:130:15 | x |
| simple.cpp:136:21:136:28 | Chi [d2_1, d1_2, ... (3)] | simple.cpp:139:23:139:23 | d2_1.d1_2.y [d1_2, y] |
| simple.cpp:136:21:136:28 | Chi [d2_1, d1_2, ... (3)] | simple.cpp:141:20:141:23 | d2_1 [d1_2, y] |
| simple.cpp:136:21:136:28 | Chi [d2_1, d1_2, ... (3)] | simple.cpp:143:23:143:30 | d2_1 [d1_2, y] |
| simple.cpp:136:21:136:28 | Chi [d2_1, d1_2, ... (3)] | simple.cpp:143:23:143:30 | d2_1 [d1_2, y] |
| simple.cpp:136:21:136:28 | d2_1 [d2_1, d1_2, ... (3)] | simple.cpp:136:21:136:28 | Chi [d2_1, d1_2, ... (3)] |
| simple.cpp:136:21:136:28 | write_to_d1_2_y output argument [d1_2, y] | simple.cpp:136:21:136:28 | d2_1 [d2_1, d1_2, ... (3)] |
| simple.cpp:136:21:136:28 | write_to_d1_2_y output argument [d1_2, y] | simple.cpp:143:23:143:30 | Argument 0 indirection [d1_2, y] |
| simple.cpp:136:21:136:28 | write_to_d1_2_y output argument [d1_2, y] | simple.cpp:144:23:144:30 | Argument 0 indirection [d1_2, y] |
| simple.cpp:136:31:136:40 | call to user_input | simple.cpp:136:21:136:28 | write_to_d1_2_y output argument [d1_2, y] |
| simple.cpp:139:23:139:23 | d1_2.y [y] | simple.cpp:139:23:139:23 | y |
| simple.cpp:139:23:139:23 | d2_1.d1_2.y [d1_2, y] | simple.cpp:139:23:139:23 | d1_2.y [y] |
| simple.cpp:139:23:139:23 | y | simple.cpp:139:23:139:23 | y |
| simple.cpp:141:20:141:23 | d2_1 [d1_2, y] | simple.cpp:108:30:108:31 | d2 [d1_2, y] |
| simple.cpp:141:20:141:23 | d2_1 [d1_2, y] | simple.cpp:141:20:141:23 | d2_1 [d1_2, y] |
| simple.cpp:143:23:143:30 | Argument 0 indirection [d1_2, y] | simple.cpp:114:37:114:38 | *d2 [d1_2, y] |
| simple.cpp:143:23:143:30 | Argument 0 indirection [d1_2, y] | simple.cpp:143:23:143:30 | read_from_y_deref output argument [d1_2, y] |
| simple.cpp:143:23:143:30 | d2_1 [d1_2, y] | simple.cpp:143:23:143:30 | Argument 0 indirection [d1_2, y] |
| simple.cpp:143:23:143:30 | d2_1 [d1_2, y] | simple.cpp:144:23:144:30 | Argument 0 indirection [d1_2, y] |
| simple.cpp:143:23:143:30 | read_from_y_deref output argument [d1_2, y] | simple.cpp:144:23:144:30 | Argument 0 indirection [d1_2, y] |
| simple.cpp:144:23:144:30 | Argument 0 indirection [d1_2, y] | simple.cpp:114:37:114:38 | *d2 [d1_2, y] |
| simple.cpp:159:20:159:24 | *inner [f] | simple.cpp:161:17:161:17 | f |
| simple.cpp:161:17:161:17 | f | simple.cpp:161:17:161:17 | f |
| simple.cpp:167:5:167:32 | Chi [inner, f] | simple.cpp:168:12:168:23 | inner [f] |
| simple.cpp:167:5:167:32 | Store | simple.cpp:167:5:167:32 | f [f] |
| simple.cpp:167:5:167:32 | f [f] | simple.cpp:167:5:167:32 | inner.f [inner, f] |
| simple.cpp:167:5:167:32 | inner.f [inner, f] | simple.cpp:167:5:167:32 | Chi [inner, f] |
| simple.cpp:167:21:167:30 | call to user_input | simple.cpp:167:5:167:32 | Store |
| simple.cpp:168:12:168:23 | Argument 0 indirection [f] | simple.cpp:159:20:159:24 | *inner [f] |
| simple.cpp:168:12:168:23 | inner [f] | simple.cpp:168:12:168:23 | Argument 0 indirection [f] |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:20:20:29 | Chi [a] | struct_init.c:24:10:24:12 | Argument 0 indirection [a] |
| struct_init.c:20:20:20:29 | Store | struct_init.c:20:20:20:29 | Chi [a] |
| struct_init.c:15:12:15:12 | a | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:20:20:29 | Store | struct_init.c:20:20:20:29 | a [a] |
| struct_init.c:20:20:20:29 | a [a] | struct_init.c:24:10:24:12 | Argument 0 indirection [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | Store |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a |
| struct_init.c:24:10:24:12 | Argument 0 indirection [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:27:7:27:16 | Chi [a] | struct_init.c:36:10:36:24 | Argument 0 indirection [a] |
| struct_init.c:27:7:27:16 | Store | struct_init.c:27:7:27:16 | Chi [a] |
| struct_init.c:27:7:27:16 | Chi [nestedAB, a] | struct_init.c:27:21:27:21 | nestedAB.b [a] |
| struct_init.c:27:7:27:16 | Store | struct_init.c:27:7:27:16 | a [a] |
| struct_init.c:27:7:27:16 | a [a] | struct_init.c:27:7:27:16 | nestedAB.a [nestedAB, a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | Store |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a |
| struct_init.c:27:7:27:16 | nestedAB.a [nestedAB, a] | struct_init.c:27:7:27:16 | Chi [nestedAB, a] |
| struct_init.c:27:7:27:16 | nestedAB.a [nestedAB, a] | struct_init.c:28:5:28:7 | Chi [nestedAB, a] |
| struct_init.c:27:21:27:21 | nestedAB.b [a] | struct_init.c:36:10:36:24 | Argument 0 indirection [a] |
| struct_init.c:28:5:28:7 | Chi [nestedAB, a] | struct_init.c:36:10:36:24 | nestedAB [a] |
| struct_init.c:36:10:36:24 | Argument 0 indirection [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:36:10:36:24 | nestedAB [a] | struct_init.c:36:10:36:24 | Argument 0 indirection [a] |
nodes
| A.cpp:98:12:98:18 | new | semmle.label | new |
| A.cpp:100:5:100:13 | Chi [a] | semmle.label | Chi [a] |
| A.cpp:100:5:100:13 | Store | semmle.label | Store |
| A.cpp:100:5:100:13 | a [a] | semmle.label | a [a] |
| A.cpp:101:8:101:9 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] |
| A.cpp:103:14:103:14 | *c [a] | semmle.label | *c [a] |
| A.cpp:107:12:107:16 | (void *)... | semmle.label | (void *)... |
@@ -80,6 +157,7 @@ nodes
| A.cpp:107:16:107:16 | a | semmle.label | a |
| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:142:7:142:20 | Store | semmle.label | Store |
| A.cpp:142:7:142:20 | c [c] | semmle.label | c [c] |
| A.cpp:142:14:142:20 | new | semmle.label | new |
| A.cpp:151:18:151:18 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] |
@@ -88,25 +166,30 @@ nodes
| A.cpp:154:13:154:13 | c | semmle.label | c |
| aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:9:3:9:22 | Store | semmle.label | Store |
| aliasing.cpp:9:3:9:22 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:13:3:13:21 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:13:3:13:21 | Store | semmle.label | Store |
| aliasing.cpp:13:3:13:21 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:25:17:25:19 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] |
| aliasing.cpp:26:19:26:20 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | semmle.label | referenceSetter output argument [m1] |
| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 |
| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 |
| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 |
| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 |
| aliasing.cpp:37:13:37:22 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 |
| aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:60:3:60:22 | Store | semmle.label | Store |
| aliasing.cpp:60:3:60:22 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:61:13:61:14 | Store [m1] | semmle.label | Store [m1] |
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
| aliasing.cpp:79:11:79:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 |
| aliasing.cpp:86:10:86:19 | call to user_input | semmle.label | call to user_input |
@@ -119,43 +202,112 @@ nodes
| by_reference.cpp:69:22:69:23 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:84:3:84:25 | Store | semmle.label | Store |
| by_reference.cpp:84:3:84:25 | a [a] | semmle.label | a [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:88:3:88:24 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:88:3:88:24 | Store | semmle.label | Store |
| by_reference.cpp:88:3:88:24 | a [a] | semmle.label | a [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:102:21:102:39 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:102:21:102:39 | Chi [inner_nested, a] | semmle.label | Chi [inner_nested, a] |
| by_reference.cpp:102:21:102:39 | inner_nested [inner_nested, a] | semmle.label | inner_nested [inner_nested, a] |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:106:21:106:41 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:106:21:106:41 | Chi [inner_nested, a] | semmle.label | Chi [inner_nested, a] |
| by_reference.cpp:106:21:106:41 | inner_nested [inner_nested, a] | semmle.label | inner_nested [inner_nested, a] |
| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:110:27:110:27 | a | semmle.label | a |
| by_reference.cpp:110:27:110:27 | a | semmle.label | a |
| by_reference.cpp:110:27:110:27 | inner_nested.a [a] | semmle.label | inner_nested.a [a] |
| by_reference.cpp:114:29:114:29 | a | semmle.label | a |
| by_reference.cpp:122:21:122:38 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:114:29:114:29 | a | semmle.label | a |
| by_reference.cpp:114:29:114:29 | inner_nested.a [a] | semmle.label | inner_nested.a [a] |
| by_reference.cpp:122:21:122:38 | Chi [inner_nested, a] | semmle.label | Chi [inner_nested, a] |
| by_reference.cpp:122:21:122:38 | inner_nested [inner_nested, a] | semmle.label | inner_nested [inner_nested, a] |
| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] |
| by_reference.cpp:126:21:126:40 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:126:21:126:40 | Chi [inner_nested, a] | semmle.label | Chi [inner_nested, a] |
| by_reference.cpp:126:21:126:40 | inner_nested [inner_nested, a] | semmle.label | inner_nested [inner_nested, a] |
| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] |
| by_reference.cpp:130:27:130:27 | a | semmle.label | a |
| by_reference.cpp:130:27:130:27 | a | semmle.label | a |
| by_reference.cpp:130:27:130:27 | inner_nested.a [a] | semmle.label | inner_nested.a [a] |
| by_reference.cpp:134:29:134:29 | a | semmle.label | a |
| simple.cpp:65:5:65:22 | Store [i] | semmle.label | Store [i] |
| by_reference.cpp:134:29:134:29 | a | semmle.label | a |
| by_reference.cpp:134:29:134:29 | inner_nested.a [a] | semmle.label | inner_nested.a [a] |
| simple.cpp:65:5:65:22 | i [i] | semmle.label | i [i] |
| simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] |
| simple.cpp:67:13:67:13 | i | semmle.label | i |
| simple.cpp:83:9:83:28 | Chi [f1] | semmle.label | Chi [f1] |
| simple.cpp:67:13:67:13 | i | semmle.label | i |
| simple.cpp:83:9:83:28 | Store | semmle.label | Store |
| simple.cpp:83:9:83:28 | f1 [f1] | semmle.label | f1 [f1] |
| simple.cpp:83:9:83:28 | f2.f1 [f2, f1] | semmle.label | f2.f1 [f2, f1] |
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:84:14:84:20 | Argument -1 indirection [f1] | semmle.label | Argument -1 indirection [f1] |
| simple.cpp:84:14:84:20 | Argument -1 indirection [f2, f1] | semmle.label | Argument -1 indirection [f2, f1] |
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
| simple.cpp:108:30:108:31 | d2 [d1_2, y] | semmle.label | d2 [d1_2, y] |
| simple.cpp:111:18:111:18 | d1_2.y [y] | semmle.label | d1_2.y [y] |
| simple.cpp:111:18:111:18 | y | semmle.label | y |
| simple.cpp:111:18:111:18 | y | semmle.label | y |
| simple.cpp:114:37:114:38 | *d2 [d1_2, y] | semmle.label | *d2 [d1_2, y] |
| simple.cpp:117:19:117:19 | d1_2.y [y] | semmle.label | d1_2.y [y] |
| simple.cpp:117:19:117:19 | y | semmle.label | y |
| simple.cpp:117:19:117:19 | y | semmle.label | y |
| simple.cpp:122:5:122:33 | Chi [d2_1, d1_1, ... (3)] | semmle.label | Chi [d2_1, d1_1, ... (3)] |
| simple.cpp:122:5:122:33 | Store | semmle.label | Store |
| simple.cpp:122:5:122:33 | d1_1.x [d1_1, x] | semmle.label | d1_1.x [d1_1, x] |
| simple.cpp:122:5:122:33 | d2_1.d1_1.x [d2_1, d1_1, ... (3)] | semmle.label | d2_1.d1_1.x [d2_1, d1_1, ... (3)] |
| simple.cpp:122:5:122:33 | x [x] | semmle.label | x [x] |
| simple.cpp:122:22:122:31 | call to user_input | semmle.label | call to user_input |
| simple.cpp:123:27:123:30 | Store [d1_1, x] | semmle.label | Store [d1_1, x] |
| simple.cpp:123:27:123:30 | d2_1 [d1_1, x] | semmle.label | d2_1 [d1_1, x] |
| simple.cpp:124:20:124:20 | d1_1.x [x] | semmle.label | d1_1.x [x] |
| simple.cpp:124:20:124:20 | x | semmle.label | x |
| simple.cpp:124:20:124:20 | x | semmle.label | x |
| simple.cpp:130:15:130:15 | d1_1.x [x] | semmle.label | d1_1.x [x] |
| simple.cpp:130:15:130:15 | x | semmle.label | x |
| simple.cpp:130:15:130:15 | x | semmle.label | x |
| simple.cpp:136:21:136:28 | Chi [d2_1, d1_2, ... (3)] | semmle.label | Chi [d2_1, d1_2, ... (3)] |
| simple.cpp:136:21:136:28 | d2_1 [d2_1, d1_2, ... (3)] | semmle.label | d2_1 [d2_1, d1_2, ... (3)] |
| simple.cpp:136:21:136:28 | write_to_d1_2_y output argument [d1_2, y] | semmle.label | write_to_d1_2_y output argument [d1_2, y] |
| simple.cpp:136:31:136:40 | call to user_input | semmle.label | call to user_input |
| simple.cpp:139:23:139:23 | d1_2.y [y] | semmle.label | d1_2.y [y] |
| simple.cpp:139:23:139:23 | d2_1.d1_2.y [d1_2, y] | semmle.label | d2_1.d1_2.y [d1_2, y] |
| simple.cpp:139:23:139:23 | y | semmle.label | y |
| simple.cpp:139:23:139:23 | y | semmle.label | y |
| simple.cpp:141:20:141:23 | d2_1 [d1_2, y] | semmle.label | d2_1 [d1_2, y] |
| simple.cpp:141:20:141:23 | d2_1 [d1_2, y] | semmle.label | d2_1 [d1_2, y] |
| simple.cpp:143:23:143:30 | Argument 0 indirection [d1_2, y] | semmle.label | Argument 0 indirection [d1_2, y] |
| simple.cpp:143:23:143:30 | d2_1 [d1_2, y] | semmle.label | d2_1 [d1_2, y] |
| simple.cpp:143:23:143:30 | d2_1 [d1_2, y] | semmle.label | d2_1 [d1_2, y] |
| simple.cpp:143:23:143:30 | read_from_y_deref output argument [d1_2, y] | semmle.label | read_from_y_deref output argument [d1_2, y] |
| simple.cpp:144:23:144:30 | Argument 0 indirection [d1_2, y] | semmle.label | Argument 0 indirection [d1_2, y] |
| simple.cpp:159:20:159:24 | *inner [f] | semmle.label | *inner [f] |
| simple.cpp:161:17:161:17 | f | semmle.label | f |
| simple.cpp:161:17:161:17 | f | semmle.label | f |
| simple.cpp:167:5:167:32 | Chi [inner, f] | semmle.label | Chi [inner, f] |
| simple.cpp:167:5:167:32 | Store | semmle.label | Store |
| simple.cpp:167:5:167:32 | f [f] | semmle.label | f [f] |
| simple.cpp:167:5:167:32 | inner.f [inner, f] | semmle.label | inner.f [inner, f] |
| simple.cpp:167:21:167:30 | call to user_input | semmle.label | call to user_input |
| simple.cpp:168:12:168:23 | Argument 0 indirection [f] | semmle.label | Argument 0 indirection [f] |
| simple.cpp:168:12:168:23 | inner [f] | semmle.label | inner [f] |
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
| struct_init.c:20:20:20:29 | Chi [a] | semmle.label | Chi [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
| struct_init.c:20:20:20:29 | Store | semmle.label | Store |
| struct_init.c:20:20:20:29 | a [a] | semmle.label | a [a] |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:22:11:22:11 | a | semmle.label | a |
| struct_init.c:24:10:24:12 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] |
| struct_init.c:27:7:27:16 | Chi [a] | semmle.label | Chi [a] |
| struct_init.c:27:7:27:16 | Chi [nestedAB, a] | semmle.label | Chi [nestedAB, a] |
| struct_init.c:27:7:27:16 | Store | semmle.label | Store |
| struct_init.c:27:7:27:16 | a [a] | semmle.label | a [a] |
| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input |
| struct_init.c:27:7:27:16 | nestedAB.a [nestedAB, a] | semmle.label | nestedAB.a [nestedAB, a] |
| struct_init.c:27:21:27:21 | nestedAB.b [a] | semmle.label | nestedAB.b [a] |
| struct_init.c:28:5:28:7 | Chi [nestedAB, a] | semmle.label | Chi [nestedAB, a] |
| struct_init.c:31:23:31:23 | a | semmle.label | a |
| struct_init.c:36:10:36:24 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] |
| struct_init.c:36:10:36:24 | nestedAB [a] | semmle.label | nestedAB [a] |
#select
| A.cpp:107:12:107:16 | (void *)... | A.cpp:98:12:98:18 | new | A.cpp:107:12:107:16 | (void *)... | (void *)... flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:107:16:107:16 | a | A.cpp:98:12:98:18 | new | A.cpp:107:16:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
@@ -176,6 +328,12 @@ nodes
| by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
| simple.cpp:111:18:111:18 | y | simple.cpp:136:31:136:40 | call to user_input | simple.cpp:111:18:111:18 | y | y flows from $@ | simple.cpp:136:31:136:40 | call to user_input | call to user_input |
| simple.cpp:117:19:117:19 | y | simple.cpp:136:31:136:40 | call to user_input | simple.cpp:117:19:117:19 | y | y flows from $@ | simple.cpp:136:31:136:40 | call to user_input | call to user_input |
| simple.cpp:124:20:124:20 | x | simple.cpp:122:22:122:31 | call to user_input | simple.cpp:124:20:124:20 | x | x flows from $@ | simple.cpp:122:22:122:31 | call to user_input | call to user_input |
| simple.cpp:130:15:130:15 | x | simple.cpp:122:22:122:31 | call to user_input | simple.cpp:130:15:130:15 | x | x flows from $@ | simple.cpp:122:22:122:31 | call to user_input | call to user_input |
| simple.cpp:139:23:139:23 | y | simple.cpp:136:31:136:40 | call to user_input | simple.cpp:139:23:139:23 | y | y flows from $@ | simple.cpp:136:31:136:40 | call to user_input | call to user_input |
| simple.cpp:161:17:161:17 | f | simple.cpp:167:21:167:30 | call to user_input | simple.cpp:161:17:161:17 | f | f flows from $@ | simple.cpp:167:21:167:30 | 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: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 |

View File

@@ -155,7 +155,6 @@
| aliasing.cpp:72:5:72:6 | m1 | AST only |
| aliasing.cpp:79:6:79:7 | m1 | AST only |
| aliasing.cpp:86:5:86:6 | m1 | AST only |
| aliasing.cpp:92:3:92:3 | w | AST only |
| aliasing.cpp:92:7:92:8 | m1 | AST only |
| by_reference.cpp:12:8:12:8 | a | AST only |
| by_reference.cpp:16:11:16:11 | a | AST only |
@@ -178,17 +177,13 @@
| by_reference.cpp:84:10:84:10 | a | AST only |
| by_reference.cpp:88:9:88:9 | a | AST only |
| by_reference.cpp:102:21:102:39 | & ... | AST only |
| by_reference.cpp:102:22:102:26 | outer | AST only |
| by_reference.cpp:103:21:103:25 | outer | AST only |
| by_reference.cpp:103:27:103:35 | inner_ptr | AST only |
| by_reference.cpp:104:15:104:22 | & ... | AST only |
| by_reference.cpp:104:16:104:20 | outer | AST only |
| by_reference.cpp:106:21:106:41 | & ... | AST only |
| by_reference.cpp:106:22:106:27 | pouter | AST only |
| by_reference.cpp:107:21:107:26 | pouter | AST only |
| by_reference.cpp:107:29:107:37 | inner_ptr | AST only |
| by_reference.cpp:108:15:108:24 | & ... | AST only |
| by_reference.cpp:108:16:108:21 | pouter | AST only |
| by_reference.cpp:110:8:110:12 | outer | AST only |
| by_reference.cpp:110:14:110:25 | inner_nested | AST only |
| by_reference.cpp:110:27:110:27 | a | AST only |
@@ -205,17 +200,13 @@
| by_reference.cpp:115:27:115:27 | a | AST only |
| by_reference.cpp:116:8:116:13 | pouter | AST only |
| by_reference.cpp:116:16:116:16 | a | AST only |
| by_reference.cpp:122:21:122:25 | outer | AST only |
| by_reference.cpp:122:27:122:38 | inner_nested | AST only |
| by_reference.cpp:123:21:123:36 | * ... | AST only |
| by_reference.cpp:123:22:123:26 | outer | AST only |
| by_reference.cpp:124:15:124:19 | outer | AST only |
| by_reference.cpp:124:21:124:21 | a | AST only |
| by_reference.cpp:126:21:126:26 | pouter | AST only |
| by_reference.cpp:126:29:126:40 | inner_nested | AST only |
| by_reference.cpp:127:21:127:38 | * ... | AST only |
| by_reference.cpp:127:22:127:27 | pouter | AST only |
| by_reference.cpp:128:15:128:20 | pouter | AST only |
| by_reference.cpp:128:23:128:23 | a | AST only |
| by_reference.cpp:130:8:130:12 | outer | AST only |
| by_reference.cpp:130:14:130:25 | inner_nested | AST only |
@@ -235,23 +226,11 @@
| by_reference.cpp:136:16:136:16 | a | AST only |
| complex.cpp:11:22:11:23 | a_ | AST only |
| complex.cpp:12:22:12:23 | b_ | AST only |
| complex.cpp:51:8:51:8 | b | AST only |
| complex.cpp:51:10:51:14 | inner | AST only |
| complex.cpp:51:16:51:16 | f | AST only |
| complex.cpp:52:8:52:8 | b | AST only |
| complex.cpp:52:10:52:14 | inner | AST only |
| complex.cpp:52:16:52:16 | f | AST only |
| complex.cpp:62:3:62:4 | b1 | AST only |
| complex.cpp:62:6:62:10 | inner | AST only |
| complex.cpp:62:12:62:12 | f | AST only |
| complex.cpp:63:3:63:4 | b2 | AST only |
| complex.cpp:63:6:63:10 | inner | AST only |
| complex.cpp:63:12:63:12 | f | AST only |
| complex.cpp:64:3:64:4 | b3 | AST only |
| complex.cpp:64:6:64:10 | inner | AST only |
| complex.cpp:64:12:64:12 | f | AST only |
| complex.cpp:65:3:65:4 | b3 | AST only |
| complex.cpp:65:6:65:10 | inner | AST only |
| complex.cpp:65:12:65:12 | f | AST only |
| complex.cpp:68:7:68:8 | b1 | AST only |
| complex.cpp:71:7:71:8 | b2 | AST only |
@@ -317,9 +296,15 @@
| simple.cpp:51:9:51:9 | h | AST only |
| simple.cpp:54:9:54:9 | i | AST only |
| simple.cpp:65:7:65:7 | i | AST only |
| simple.cpp:83:9:83:10 | this | AST only |
| simple.cpp:83:12:83:13 | f1 | AST only |
| simple.cpp:84:14:84:20 | this | AST only |
| simple.cpp:105:14:105:14 | y | AST only |
| simple.cpp:122:18:122:18 | x | AST only |
| simple.cpp:136:21:136:28 | & ... | AST only |
| simple.cpp:143:23:143:30 | & ... | AST only |
| simple.cpp:144:23:144:30 | & ... | AST only |
| simple.cpp:167:17:167:17 | f | AST only |
| simple.cpp:168:12:168:23 | & ... | AST only |
| struct_init.c:15:8:15:9 | ab | AST only |
| struct_init.c:15:12:15:12 | a | AST only |
| struct_init.c:16:8:16:9 | ab | AST only |
@@ -342,6 +327,5 @@
| struct_init.c:34:14:34:22 | pointerAB | AST only |
| struct_init.c:34:25:34:25 | b | AST only |
| struct_init.c:36:10:36:24 | & ... | AST only |
| struct_init.c:36:11:36:15 | outer | AST only |
| struct_init.c:46:10:46:14 | outer | AST only |
| struct_init.c:46:16:46:24 | pointerAB | AST only |

View File

@@ -23,15 +23,38 @@
| aliasing.cpp:54:3:54:4 | s2 |
| aliasing.cpp:60:3:60:4 | s2 |
| aliasing.cpp:72:3:72:3 | s |
| aliasing.cpp:78:11:78:11 | w |
| aliasing.cpp:79:3:79:3 | s |
| aliasing.cpp:85:10:85:10 | w |
| aliasing.cpp:86:3:86:3 | s |
| aliasing.cpp:92:3:92:3 | w |
| aliasing.cpp:92:5:92:5 | s |
| by_reference.cpp:12:5:12:5 | s |
| by_reference.cpp:16:5:16:8 | this |
| by_reference.cpp:84:3:84:7 | inner |
| by_reference.cpp:88:3:88:7 | inner |
| by_reference.cpp:102:22:102:26 | outer |
| by_reference.cpp:104:16:104:20 | outer |
| by_reference.cpp:106:22:106:27 | pouter |
| by_reference.cpp:108:16:108:21 | pouter |
| by_reference.cpp:122:21:122:25 | outer |
| by_reference.cpp:124:15:124:19 | outer |
| by_reference.cpp:126:21:126:26 | pouter |
| by_reference.cpp:128:15:128:20 | pouter |
| complex.cpp:11:22:11:23 | this |
| complex.cpp:12:22:12:23 | this |
| complex.cpp:51:8:51:8 | b |
| complex.cpp:51:10:51:14 | inner |
| complex.cpp:52:8:52:8 | b |
| complex.cpp:52:10:52:14 | inner |
| complex.cpp:62:3:62:4 | b1 |
| complex.cpp:62:6:62:10 | inner |
| complex.cpp:63:3:63:4 | b2 |
| complex.cpp:63:6:63:10 | inner |
| complex.cpp:64:3:64:4 | b3 |
| complex.cpp:64:6:64:10 | inner |
| complex.cpp:65:3:65:4 | b3 |
| complex.cpp:65:6:65:10 | inner |
| constructors.cpp:20:24:20:25 | this |
| constructors.cpp:21:24:21:25 | this |
| qualifiers.cpp:9:30:9:33 | this |
@@ -41,3 +64,16 @@
| simple.cpp:21:24:21:25 | this |
| simple.cpp:65:5:65:5 | a |
| simple.cpp:83:9:83:10 | f2 |
| simple.cpp:83:9:83:10 | this |
| simple.cpp:105:5:105:6 | d2 |
| simple.cpp:105:9:105:12 | d1_2 |
| simple.cpp:122:5:122:6 | d3 |
| simple.cpp:122:8:122:11 | d2_1 |
| simple.cpp:122:13:122:16 | d1_1 |
| simple.cpp:136:22:136:23 | d3 |
| simple.cpp:143:24:143:25 | d3 |
| simple.cpp:144:24:144:25 | d3 |
| simple.cpp:167:5:167:9 | outer |
| simple.cpp:167:11:167:15 | inner |
| simple.cpp:168:13:168:17 | outer |
| struct_init.c:36:11:36:15 | outer |

View File

@@ -363,6 +363,24 @@
| simple.cpp:83:9:83:10 | this |
| simple.cpp:83:12:83:13 | f1 |
| simple.cpp:84:14:84:20 | this |
| simple.cpp:105:5:105:6 | d2 |
| simple.cpp:105:9:105:12 | d1_2 |
| simple.cpp:105:14:105:14 | y |
| simple.cpp:122:5:122:6 | d3 |
| simple.cpp:122:8:122:11 | d2_1 |
| simple.cpp:122:13:122:16 | d1_1 |
| simple.cpp:122:18:122:18 | x |
| simple.cpp:136:21:136:28 | & ... |
| simple.cpp:136:22:136:23 | d3 |
| simple.cpp:143:23:143:30 | & ... |
| simple.cpp:143:24:143:25 | d3 |
| simple.cpp:144:23:144:30 | & ... |
| simple.cpp:144:24:144:25 | d3 |
| simple.cpp:167:5:167:9 | outer |
| simple.cpp:167:11:167:15 | inner |
| simple.cpp:167:17:167:17 | f |
| simple.cpp:168:12:168:23 | & ... |
| simple.cpp:168:13:168:17 | outer |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:15:12:15:12 | a |
| struct_init.c:16:8:16:9 | ab |

View File

@@ -332,6 +332,48 @@ edges
| simple.cpp:83:9:83:28 | ... = ... | simple.cpp:83:9:83:10 | f2 [post update] [f1] |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | ... = ... |
| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| simple.cpp:108:30:108:31 | d2 [d1_2, y] | simple.cpp:111:10:111:11 | d2 [d1_2, y] |
| simple.cpp:111:10:111:11 | d2 [d1_2, y] | simple.cpp:111:13:111:16 | d1_2 [y] |
| simple.cpp:111:13:111:16 | d1_2 [y] | simple.cpp:111:18:111:18 | y |
| simple.cpp:114:37:114:38 | d2 [d1_2, y] | simple.cpp:117:10:117:11 | d2 [d1_2, y] |
| simple.cpp:117:10:117:11 | d2 [d1_2, y] | simple.cpp:117:14:117:17 | d1_2 [y] |
| simple.cpp:117:14:117:17 | d1_2 [y] | simple.cpp:117:19:117:19 | y |
| simple.cpp:122:5:122:6 | d3 [post update] [d2_1, d1_1, ... (3)] | simple.cpp:123:24:123:25 | d3 [d2_1, d1_1, ... (3)] |
| simple.cpp:122:5:122:33 | ... = ... | simple.cpp:122:13:122:16 | d1_1 [post update] [x] |
| simple.cpp:122:8:122:11 | d2_1 [post update] [d1_1, x] | simple.cpp:122:5:122:6 | d3 [post update] [d2_1, d1_1, ... (3)] |
| simple.cpp:122:13:122:16 | d1_1 [post update] [x] | simple.cpp:122:8:122:11 | d2_1 [post update] [d1_1, x] |
| simple.cpp:122:22:122:31 | call to user_input | simple.cpp:122:5:122:33 | ... = ... |
| simple.cpp:123:24:123:25 | d3 [d2_1, d1_1, ... (3)] | simple.cpp:123:27:123:30 | d2_1 [d1_1, x] |
| simple.cpp:123:27:123:30 | d2_1 [d1_1, x] | simple.cpp:124:10:124:13 | d2_1 [d1_1, x] |
| simple.cpp:123:27:123:30 | d2_1 [d1_1, x] | simple.cpp:129:25:129:28 | d2_1 [d1_1, x] |
| simple.cpp:124:10:124:13 | d2_1 [d1_1, x] | simple.cpp:124:15:124:18 | d1_1 [x] |
| simple.cpp:124:15:124:18 | d1_1 [x] | simple.cpp:124:20:124:20 | x |
| simple.cpp:129:25:129:28 | d2_1 [d1_1, x] | simple.cpp:129:30:129:33 | d1_1 [x] |
| simple.cpp:129:30:129:33 | d1_1 [x] | simple.cpp:130:10:130:12 | pd1 [x] |
| simple.cpp:130:10:130:12 | pd1 [x] | simple.cpp:130:15:130:15 | x |
| simple.cpp:136:21:136:28 | ref arg & ... [d1_2, y] | simple.cpp:136:25:136:28 | d2_1 [inner post update] [d1_2, y] |
| simple.cpp:136:22:136:23 | d3 [post update] [d2_1, d1_2, ... (3)] | simple.cpp:139:10:139:11 | d3 [d2_1, d1_2, ... (3)] |
| simple.cpp:136:22:136:23 | d3 [post update] [d2_1, d1_2, ... (3)] | simple.cpp:141:17:141:18 | d3 [d2_1, d1_2, ... (3)] |
| simple.cpp:136:22:136:23 | d3 [post update] [d2_1, d1_2, ... (3)] | simple.cpp:143:24:143:25 | d3 [d2_1, d1_2, ... (3)] |
| simple.cpp:136:25:136:28 | d2_1 [inner post update] [d1_2, y] | simple.cpp:136:22:136:23 | d3 [post update] [d2_1, d1_2, ... (3)] |
| simple.cpp:136:31:136:40 | call to user_input | simple.cpp:136:21:136:28 | ref arg & ... [d1_2, y] |
| simple.cpp:139:10:139:11 | d3 [d2_1, d1_2, ... (3)] | simple.cpp:139:13:139:16 | d2_1 [d1_2, y] |
| simple.cpp:139:13:139:16 | d2_1 [d1_2, y] | simple.cpp:139:18:139:21 | d1_2 [y] |
| simple.cpp:139:18:139:21 | d1_2 [y] | simple.cpp:139:23:139:23 | y |
| simple.cpp:141:17:141:18 | d3 [d2_1, d1_2, ... (3)] | simple.cpp:141:20:141:23 | d2_1 [d1_2, y] |
| simple.cpp:141:20:141:23 | d2_1 [d1_2, y] | simple.cpp:108:30:108:31 | d2 [d1_2, y] |
| simple.cpp:143:23:143:30 | & ... [d1_2, y] | simple.cpp:114:37:114:38 | d2 [d1_2, y] |
| simple.cpp:143:24:143:25 | d3 [d2_1, d1_2, ... (3)] | simple.cpp:143:27:143:30 | d2_1 [d1_2, y] |
| simple.cpp:143:27:143:30 | d2_1 [d1_2, y] | simple.cpp:143:23:143:30 | & ... [d1_2, y] |
| simple.cpp:159:20:159:24 | inner [f] | simple.cpp:161:10:161:14 | inner [f] |
| simple.cpp:161:10:161:14 | inner [f] | simple.cpp:161:17:161:17 | f |
| simple.cpp:167:5:167:9 | outer [post update] [inner, f] | simple.cpp:168:13:168:17 | outer [inner, f] |
| simple.cpp:167:5:167:32 | ... = ... | simple.cpp:167:11:167:15 | inner [post update] [f] |
| simple.cpp:167:11:167:15 | inner [post update] [f] | simple.cpp:167:5:167:9 | outer [post update] [inner, f] |
| simple.cpp:167:21:167:30 | call to user_input | simple.cpp:167:5:167:32 | ... = ... |
| simple.cpp:168:12:168:23 | & ... [f] | simple.cpp:159:20:159:24 | inner [f] |
| simple.cpp:168:13:168:17 | outer [inner, f] | simple.cpp:168:19:168:23 | inner [f] |
| simple.cpp:168:19:168:23 | inner [f] | simple.cpp:168:12:168:23 | & ... [f] |
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [a] |
| struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:17:20:36 | {...} [a] | struct_init.c:22:8:22:9 | ab [a] |
@@ -732,6 +774,51 @@ nodes
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
| simple.cpp:84:14:84:20 | this [f2, f1] | semmle.label | this [f2, f1] |
| simple.cpp:108:30:108:31 | d2 [d1_2, y] | semmle.label | d2 [d1_2, y] |
| simple.cpp:111:10:111:11 | d2 [d1_2, y] | semmle.label | d2 [d1_2, y] |
| simple.cpp:111:13:111:16 | d1_2 [y] | semmle.label | d1_2 [y] |
| simple.cpp:111:18:111:18 | y | semmle.label | y |
| simple.cpp:114:37:114:38 | d2 [d1_2, y] | semmle.label | d2 [d1_2, y] |
| simple.cpp:117:10:117:11 | d2 [d1_2, y] | semmle.label | d2 [d1_2, y] |
| simple.cpp:117:14:117:17 | d1_2 [y] | semmle.label | d1_2 [y] |
| simple.cpp:117:19:117:19 | y | semmle.label | y |
| simple.cpp:122:5:122:6 | d3 [post update] [d2_1, d1_1, ... (3)] | semmle.label | d3 [post update] [d2_1, d1_1, ... (3)] |
| simple.cpp:122:5:122:33 | ... = ... | semmle.label | ... = ... |
| simple.cpp:122:8:122:11 | d2_1 [post update] [d1_1, x] | semmle.label | d2_1 [post update] [d1_1, x] |
| simple.cpp:122:13:122:16 | d1_1 [post update] [x] | semmle.label | d1_1 [post update] [x] |
| simple.cpp:122:22:122:31 | call to user_input | semmle.label | call to user_input |
| simple.cpp:123:24:123:25 | d3 [d2_1, d1_1, ... (3)] | semmle.label | d3 [d2_1, d1_1, ... (3)] |
| simple.cpp:123:27:123:30 | d2_1 [d1_1, x] | semmle.label | d2_1 [d1_1, x] |
| simple.cpp:124:10:124:13 | d2_1 [d1_1, x] | semmle.label | d2_1 [d1_1, x] |
| simple.cpp:124:15:124:18 | d1_1 [x] | semmle.label | d1_1 [x] |
| simple.cpp:124:20:124:20 | x | semmle.label | x |
| simple.cpp:129:25:129:28 | d2_1 [d1_1, x] | semmle.label | d2_1 [d1_1, x] |
| simple.cpp:129:30:129:33 | d1_1 [x] | semmle.label | d1_1 [x] |
| simple.cpp:130:10:130:12 | pd1 [x] | semmle.label | pd1 [x] |
| simple.cpp:130:15:130:15 | x | semmle.label | x |
| simple.cpp:136:21:136:28 | ref arg & ... [d1_2, y] | semmle.label | ref arg & ... [d1_2, y] |
| simple.cpp:136:22:136:23 | d3 [post update] [d2_1, d1_2, ... (3)] | semmle.label | d3 [post update] [d2_1, d1_2, ... (3)] |
| simple.cpp:136:25:136:28 | d2_1 [inner post update] [d1_2, y] | semmle.label | d2_1 [inner post update] [d1_2, y] |
| simple.cpp:136:31:136:40 | call to user_input | semmle.label | call to user_input |
| simple.cpp:139:10:139:11 | d3 [d2_1, d1_2, ... (3)] | semmle.label | d3 [d2_1, d1_2, ... (3)] |
| simple.cpp:139:13:139:16 | d2_1 [d1_2, y] | semmle.label | d2_1 [d1_2, y] |
| simple.cpp:139:18:139:21 | d1_2 [y] | semmle.label | d1_2 [y] |
| simple.cpp:139:23:139:23 | y | semmle.label | y |
| simple.cpp:141:17:141:18 | d3 [d2_1, d1_2, ... (3)] | semmle.label | d3 [d2_1, d1_2, ... (3)] |
| simple.cpp:141:20:141:23 | d2_1 [d1_2, y] | semmle.label | d2_1 [d1_2, y] |
| simple.cpp:143:23:143:30 | & ... [d1_2, y] | semmle.label | & ... [d1_2, y] |
| simple.cpp:143:24:143:25 | d3 [d2_1, d1_2, ... (3)] | semmle.label | d3 [d2_1, d1_2, ... (3)] |
| simple.cpp:143:27:143:30 | d2_1 [d1_2, y] | semmle.label | d2_1 [d1_2, y] |
| simple.cpp:159:20:159:24 | inner [f] | semmle.label | inner [f] |
| simple.cpp:161:10:161:14 | inner [f] | semmle.label | inner [f] |
| simple.cpp:161:17:161:17 | f | semmle.label | f |
| simple.cpp:167:5:167:9 | outer [post update] [inner, f] | semmle.label | outer [post update] [inner, f] |
| simple.cpp:167:5:167:32 | ... = ... | semmle.label | ... = ... |
| simple.cpp:167:11:167:15 | inner [post update] [f] | semmle.label | inner [post update] [f] |
| simple.cpp:167:21:167:30 | call to user_input | semmle.label | call to user_input |
| simple.cpp:168:12:168:23 | & ... [f] | semmle.label | & ... [f] |
| simple.cpp:168:13:168:17 | outer [inner, f] | semmle.label | outer [inner, f] |
| simple.cpp:168:19:168:23 | inner [f] | semmle.label | inner [f] |
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
| struct_init.c:15:8:15:9 | ab [a] | semmle.label | ab [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
@@ -830,6 +917,12 @@ nodes
| simple.cpp:29:12:29:12 | call to b | simple.cpp:42:12:42:21 | call to user_input | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:42:12:42:21 | call to user_input | call to user_input |
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
| simple.cpp:111:18:111:18 | y | simple.cpp:136:31:136:40 | call to user_input | simple.cpp:111:18:111:18 | y | y flows from $@ | simple.cpp:136:31:136:40 | call to user_input | call to user_input |
| simple.cpp:117:19:117:19 | y | simple.cpp:136:31:136:40 | call to user_input | simple.cpp:117:19:117:19 | y | y flows from $@ | simple.cpp:136:31:136:40 | call to user_input | call to user_input |
| simple.cpp:124:20:124:20 | x | simple.cpp:122:22:122:31 | call to user_input | simple.cpp:124:20:124:20 | x | x flows from $@ | simple.cpp:122:22:122:31 | call to user_input | call to user_input |
| simple.cpp:130:15:130:15 | x | simple.cpp:122:22:122:31 | call to user_input | simple.cpp:130:15:130:15 | x | x flows from $@ | simple.cpp:122:22:122:31 | call to user_input | call to user_input |
| simple.cpp:139:23:139:23 | y | simple.cpp:136:31:136:40 | call to user_input | simple.cpp:139:23:139:23 | y | y flows from $@ | simple.cpp:136:31:136:40 | call to user_input | call to user_input |
| simple.cpp:161:17:161:17 | f | simple.cpp:167:21:167:30 | call to user_input | simple.cpp:161:17:161:17 | f | f flows from $@ | simple.cpp:167:21:167:30 | 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 |

View File

@@ -85,4 +85,87 @@ struct C2
}
};
struct DeepStruct1 {
int x;
int y;
};
struct DeepStruct2 {
DeepStruct1 d1_1;
DeepStruct1 d1_2;
};
struct DeepStruct3 {
DeepStruct2 d2_1;
DeepStruct2 d2_2;
DeepStruct1 d1_1;
};
void write_to_d1_2_y(DeepStruct2* d2, int val) {
d2->d1_2.y = val;
}
void read_from_y(DeepStruct2 d2) {
sink(d2.d1_1.y);
sink(d2.d1_2.y); //$ast,ir
}
void read_from_y_deref(DeepStruct2* d2) {
sink(d2->d1_1.y);
sink(d2->d1_2.y); //$ast,ir
}
void test_deep_structs() {
DeepStruct3 d3;
d3.d2_1.d1_1.x = user_input();
DeepStruct2 d2_1 = d3.d2_1;
sink(d2_1.d1_1.x); //$ast,ir
sink(d2_1.d1_1.y);
sink(d2_1.d1_2.x);
DeepStruct1* pd1 = &d2_1.d1_1;
sink(pd1->x); //$ast,ir
}
void test_deep_structs_setter() {
DeepStruct3 d3;
write_to_d1_2_y(&d3.d2_1, user_input());
sink(d3.d2_1.d1_1.y);
sink(d3.d2_1.d1_2.y); //$ast,ir
read_from_y(d3.d2_1);
read_from_y(d3.d2_2);
read_from_y_deref(&d3.d2_1);
read_from_y_deref(&d3.d2_2);
}
struct Inner
{
int f;
int g;
};
struct Outer
{
Inner inner;
int h;
};
void read_f(Inner *inner)
{
sink(inner->f); //$ast,ir
}
void test()
{
Outer outer;
outer.inner.f = user_input();
read_f(&outer.inner);
}
} // namespace Simple

View File

@@ -659,10 +659,10 @@ unreachableNodeCCtx
localCallNodes
postIsNotPre
postHasUniquePre
| assignexpr.cpp:9:2:9:12 | Store | PostUpdateNode should have one pre-update node but has 0. |
| bad_asts.cpp:15:10:15:12 | Store | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:65:19:65:45 | Store | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:531:14:531:14 | Store | PostUpdateNode should have one pre-update node but has 0. |
| assignexpr.cpp:9:2:9:12 | i | PostUpdateNode should have one pre-update node but has 0. |
| bad_asts.cpp:15:10:15:12 | x | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:65:19:65:45 | x | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:531:14:531:14 | d | PostUpdateNode should have one pre-update node but has 0. |
uniquePostUpdate
postIsInSameCallable
reverseRead