Skip to content

Commit 6bd31de

Browse files
authored
Merge pull request #15282 from MathiasVP/fix-duplicate-final-global-value
C++: Fix duplicate "final global value" nodes
2 parents a833632 + 8f36584 commit 6bd31de

File tree

4 files changed

+85
-5
lines changed

4 files changed

+85
-5
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll

+67-5
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,16 @@ private newtype TDefOrUseImpl =
149149
private predicate isGlobalUse(
150150
GlobalLikeVariable v, IRFunction f, int indirection, int indirectionIndex
151151
) {
152-
exists(VariableAddressInstruction vai |
153-
vai.getEnclosingIRFunction() = f and
154-
vai.getAstVariable() = v and
155-
isDef(_, _, _, vai, indirection, indirectionIndex)
156-
)
152+
// Generate a "global use" at the end of the function body if there's a
153+
// direct definition somewhere in the body of the function
154+
indirection =
155+
min(int cand, VariableAddressInstruction vai |
156+
vai.getEnclosingIRFunction() = f and
157+
vai.getAstVariable() = v and
158+
isDef(_, _, _, vai, cand, indirectionIndex)
159+
|
160+
cand
161+
)
157162
}
158163

159164
private predicate isGlobalDefImpl(
@@ -447,6 +452,57 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
447452
}
448453
}
449454

455+
/**
456+
* A use that models a synthetic "last use" of a global variable just before a
457+
* function returns.
458+
*
459+
* We model global variable flow by:
460+
* - Inserting a last use of any global variable that's modified by a function
461+
* - Flowing from the last use to the `VariableNode` that represents the global
462+
* variable.
463+
* - Flowing from the `VariableNode` to an "initial def" of the global variable
464+
* in any function that may read the global variable.
465+
* - Flowing from the initial definition to any subsequent uses of the global
466+
* variable in the function body.
467+
*
468+
* For example, consider the following pair of functions:
469+
* ```cpp
470+
* int global;
471+
* int source();
472+
* void sink(int);
473+
*
474+
* void set_global() {
475+
* global = source();
476+
* }
477+
*
478+
* void read_global() {
479+
* sink(global);
480+
* }
481+
* ```
482+
* we insert global uses and defs so that (from the point-of-view of dataflow)
483+
* the above scenario looks like:
484+
* ```cpp
485+
* int global; // (1)
486+
* int source();
487+
* void sink(int);
488+
*
489+
* void set_global() {
490+
* global = source();
491+
* __global_use(global); // (2)
492+
* }
493+
*
494+
* void read_global() {
495+
* global = __global_def; // (3)
496+
* sink(global); // (4)
497+
* }
498+
* ```
499+
* and flow from `source()` to the argument of `sink` is then modeled as
500+
* follows:
501+
* 1. Flow from `source()` to `(2)` (via SSA).
502+
* 2. Flow from `(2)` to `(1)` (via a `jumpStep`).
503+
* 3. Flow from `(1)` to `(3)` (via a `jumpStep`).
504+
* 4. Flow from `(3)` to `(4)` (via SSA).
505+
*/
450506
class GlobalUse extends UseImpl, TGlobalUse {
451507
GlobalLikeVariable global;
452508
IRFunction f;
@@ -494,6 +550,12 @@ class GlobalUse extends UseImpl, TGlobalUse {
494550
override BaseSourceVariableInstruction getBase() { none() }
495551
}
496552

553+
/**
554+
* A definition that models a synthetic "initial definition" of a global
555+
* variable just after the function entry point.
556+
*
557+
* See the QLDoc for `GlobalUse` for how this is used.
558+
*/
497559
class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
498560
GlobalLikeVariable global;
499561
IRFunction f;

cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected

+3
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ postWithInFlow
159159
| test.cpp:808:5:808:21 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
160160
| test.cpp:808:6:808:21 | global_indirect1 [inner post update] | PostUpdateNode should not be the target of local flow. |
161161
| test.cpp:832:5:832:17 | global_direct [post update] | PostUpdateNode should not be the target of local flow. |
162+
| test.cpp:931:5:931:18 | global_pointer [post update] | PostUpdateNode should not be the target of local flow. |
163+
| test.cpp:932:5:932:19 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
164+
| test.cpp:932:6:932:19 | global_pointer [inner post update] | PostUpdateNode should not be the target of local flow. |
162165
viableImplInCallContextTooLarge
163166
uniqueParameterNodeAtPosition
164167
uniqueParameterNodePosition

cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected

+1
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ irFlow
300300
| test.cpp:902:56:902:75 | *indirect_source(2) | test.cpp:911:19:911:48 | *global_array_static_indirect_2 |
301301
| test.cpp:914:46:914:53 | source | test.cpp:919:10:919:30 | global_pointer_static |
302302
| test.cpp:915:57:915:76 | *indirect_source(1) | test.cpp:921:19:921:50 | *global_pointer_static_indirect_1 |
303+
| test.cpp:932:23:932:28 | call to source | test.cpp:937:10:937:24 | * ... |
303304
| true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x |
304305
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
305306
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |

cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -922,4 +922,18 @@ namespace GlobalArrays {
922922
sink(global_pointer_static_indirect_2); // clean: global_pointer_static_indirect_2 does not have 2 indirections
923923
indirect_sink(global_pointer_static_indirect_2); // clean: global_pointer_static_indirect_2 does not have 2 indirections
924924
}
925+
}
926+
927+
namespace global_variable_conflation_test {
928+
int* global_pointer;
929+
930+
void def() {
931+
global_pointer = nullptr;
932+
*global_pointer = source();
933+
}
934+
935+
void use() {
936+
sink(global_pointer); // clean
937+
sink(*global_pointer); // $ ir MISSING: ast
938+
}
925939
}

0 commit comments

Comments
 (0)