mirror of
https://github.com/github/codeql.git
synced 2025-12-17 09:13:20 +01:00
C++: Flow from parameters to ConstructorFieldInit
Because `ConstructorFieldInit` (member initializer lists) are not part of the control flow graph, there was no data flow from the initial value of parameters to their uses in member initializers. This commit adds the necessary flow under the assumption that parameters are not overwritten in member initializers.
This commit is contained in:
@@ -249,6 +249,9 @@ module FlowVar_internal {
|
||||
result = descendentDef.getAUse(v)
|
||||
)
|
||||
)
|
||||
or
|
||||
parameterUsedInConstructorFieldInit(v, result) and
|
||||
def.definedByParameter(v)
|
||||
}
|
||||
|
||||
override predicate definedByExpr(Expr e, ControlFlowNode node) {
|
||||
@@ -314,6 +317,9 @@ module FlowVar_internal {
|
||||
override VariableAccess getAnAccess() {
|
||||
variableAccessInSBB(v, getAReachedBlockVarSBB(this), result) and
|
||||
result != sbb
|
||||
or
|
||||
parameterUsedInConstructorFieldInit(v, result) and
|
||||
sbb = v.(Parameter).getFunction().getEntryPoint()
|
||||
}
|
||||
|
||||
override predicate definedByInitialValue(LocalScopeVariable lsv) {
|
||||
@@ -692,6 +698,21 @@ module FlowVar_internal {
|
||||
assignedExpr = init.getExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` is a parameter to a constructor that is used in a
|
||||
* `ConstructorFieldInit` at `va`. This ignores the corner case that `p`
|
||||
* might have been overwritten to have a different value before this happens.
|
||||
*/
|
||||
predicate parameterUsedInConstructorFieldInit(Parameter p, VariableAccess va) {
|
||||
exists(Constructor constructor |
|
||||
constructor.getInitializer(_).(ConstructorFieldInit).getExpr().getAChild*() = va and
|
||||
va = p.getAnAccess()
|
||||
// We don't require that `constructor` has `p` as a parameter because
|
||||
// that follows from the two other conditions and would likely just
|
||||
// confuse the join orderer.
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A point in a basic block where a non-SSA variable may have a different value
|
||||
* than it did elsewhere in the same basic block. Extending this class
|
||||
|
||||
@@ -25,8 +25,8 @@ public:
|
||||
|
||||
void bar(Foo &f)
|
||||
{
|
||||
sink(f.a()); // flow (through `f` and `h`) [NOT DETECTED]
|
||||
sink(f.b()); // flow (through `g` and `h`) [NOT DETECTED]
|
||||
sink(f.a()); // flow (through `f` and `h`)
|
||||
sink(f.b()); // flow (through `g` and `h`)
|
||||
}
|
||||
|
||||
void foo()
|
||||
|
||||
@@ -86,6 +86,22 @@ edges
|
||||
| C.cpp:24:16:24:25 | new [void] | C.cpp:24:5:24:25 | ... = ... [void] |
|
||||
| C.cpp:27:8:27:11 | `this` parameter in func [s1, ... (1)] | file://:0:0:0:0 | this [s1, ... (1)] |
|
||||
| C.cpp:27:8:27:11 | `this` parameter in func [s3, ... (1)] | file://:0:0:0:0 | this [s3, ... (1)] |
|
||||
| constructors.cpp:26:15:26:15 | f [a_, ... (1)] | constructors.cpp:28:10:28:10 | f [a_, ... (1)] |
|
||||
| constructors.cpp:26:15:26:15 | f [b_, ... (1)] | constructors.cpp:29:10:29:10 | f [b_, ... (1)] |
|
||||
| constructors.cpp:28:10:28:10 | f [a_, ... (1)] | constructors.cpp:28:12:28:12 | call to a |
|
||||
| constructors.cpp:29:10:29:10 | f [b_, ... (1)] | constructors.cpp:29:12:29:12 | call to b |
|
||||
| constructors.cpp:34:11:34:20 | call to user_input [void] | constructors.cpp:34:11:34:26 | call to Foo [a_, ... (1)] |
|
||||
| constructors.cpp:34:11:34:26 | call to Foo [a_, ... (1)] | constructors.cpp:40:9:40:9 | f [a_, ... (1)] |
|
||||
| constructors.cpp:35:11:35:26 | call to Foo [b_, ... (1)] | constructors.cpp:43:9:43:9 | g [b_, ... (1)] |
|
||||
| constructors.cpp:35:14:35:23 | call to user_input [void] | constructors.cpp:35:11:35:26 | call to Foo [b_, ... (1)] |
|
||||
| constructors.cpp:36:11:36:20 | call to user_input [void] | constructors.cpp:36:11:36:37 | call to Foo [a_, ... (1)] |
|
||||
| constructors.cpp:36:11:36:37 | call to Foo [a_, ... (1)] | constructors.cpp:46:9:46:9 | h [a_, ... (1)] |
|
||||
| constructors.cpp:36:11:36:37 | call to Foo [b_, ... (1)] | constructors.cpp:46:9:46:9 | h [b_, ... (1)] |
|
||||
| constructors.cpp:36:25:36:34 | call to user_input [void] | constructors.cpp:36:11:36:37 | call to Foo [b_, ... (1)] |
|
||||
| constructors.cpp:40:9:40:9 | f [a_, ... (1)] | constructors.cpp:26:15:26:15 | f [a_, ... (1)] |
|
||||
| constructors.cpp:43:9:43:9 | g [b_, ... (1)] | constructors.cpp:26:15:26:15 | f [b_, ... (1)] |
|
||||
| constructors.cpp:46:9:46:9 | h [a_, ... (1)] | constructors.cpp:26:15:26:15 | f [a_, ... (1)] |
|
||||
| constructors.cpp:46:9:46:9 | h [b_, ... (1)] | constructors.cpp:26:15:26:15 | f [b_, ... (1)] |
|
||||
| file://:0:0:0:0 | this [s1, ... (1)] | C.cpp:29:10:29:11 | s1 |
|
||||
| file://:0:0:0:0 | this [s3, ... (1)] | C.cpp:31:10:31:11 | s3 |
|
||||
| simple.cpp:26:15:26:15 | f [a_, ... (1)] | simple.cpp:28:10:28:10 | f [a_, ... (1)] |
|
||||
@@ -124,6 +140,10 @@ edges
|
||||
| B.cpp:19:20:19:24 | elem2 | B.cpp:15:15:15:27 | new [void] | B.cpp:19:20:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new [void] | new [void] |
|
||||
| C.cpp:29:10:29:11 | s1 | C.cpp:22:12:22:21 | new [void] | C.cpp:29:10:29:11 | s1 | s1 flows from $@ | C.cpp:22:12:22:21 | new [void] | new [void] |
|
||||
| C.cpp:31:10:31:11 | s3 | C.cpp:24:16:24:25 | new [void] | C.cpp:31:10:31:11 | s3 | s3 flows from $@ | C.cpp:24:16:24:25 | new [void] | new [void] |
|
||||
| constructors.cpp:28:12:28:12 | call to a | constructors.cpp:34:11:34:20 | call to user_input [void] | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:34:11:34:20 | call to user_input [void] | call to user_input [void] |
|
||||
| constructors.cpp:28:12:28:12 | call to a | constructors.cpp:36:11:36:20 | call to user_input [void] | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:36:11:36:20 | call to user_input [void] | call to user_input [void] |
|
||||
| constructors.cpp:29:12:29:12 | call to b | constructors.cpp:35:14:35:23 | call to user_input [void] | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:35:14:35:23 | call to user_input [void] | call to user_input [void] |
|
||||
| constructors.cpp:29:12:29:12 | call to b | constructors.cpp:36:25:36:34 | call to user_input [void] | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:36:25:36:34 | call to user_input [void] | call to user_input [void] |
|
||||
| simple.cpp:28:12:28:12 | call to a | simple.cpp:39:12:39:21 | call to user_input [void] | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:39:12:39:21 | call to user_input [void] | call to user_input [void] |
|
||||
| simple.cpp:28:12:28:12 | call to a | simple.cpp:41:12:41:21 | call to user_input [void] | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:41:12:41:21 | call to user_input [void] | call to user_input [void] |
|
||||
| simple.cpp:29:12:29:12 | call to b | simple.cpp:40:12:40:21 | call to user_input [void] | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:40:12:40:21 | call to user_input [void] | call to user_input [void] |
|
||||
|
||||
Reference in New Issue
Block a user