Skip to content

Commit 22f25e8

Browse files
committed
C++: Fix global variable flow for array types.
1 parent 7b56f9e commit 22f25e8

File tree

4 files changed

+41
-7
lines changed

4 files changed

+41
-7
lines changed

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,26 @@ class GlobalLikeVariable extends Variable {
645645
}
646646
}
647647

648+
/**
649+
* Returns the smallest indirection for `use`.
650+
*
651+
* For most types this is `1`, but for `ArrayType`s (which are allocated on
652+
* the stack) this is `0`
653+
*/
654+
private int getLowerForGlobalUse(Ssa::GlobalUse use) {
655+
if use.getUnspecifiedType() instanceof Cpp::ArrayType then result = 0 else result = 1
656+
}
657+
658+
/**
659+
* Returns the smallest indirection for `def`.
660+
*
661+
* For most types this is `1`, but for `ArrayType`s (which are allocated on
662+
* the stack) this is `0`
663+
*/
664+
private int getLowerForGlobalDef(Ssa::GlobalDef def) {
665+
if def.getUnspecifiedType() instanceof Cpp::ArrayType then result = 0 else result = 1
666+
}
667+
648668
/**
649669
* Holds if data can flow from `node1` to `node2` in a way that loses the
650670
* calling context. For example, this would happen with flow through a
@@ -656,7 +676,7 @@ predicate jumpStep(Node n1, Node n2) {
656676
v = globalUse.getVariable() and
657677
n1.(FinalGlobalValue).getGlobalUse() = globalUse
658678
|
659-
globalUse.getIndirection() = 1 and
679+
globalUse.getIndirection() = getLowerForGlobalUse(globalUse) and
660680
v = n2.asVariable()
661681
or
662682
v = n2.asIndirectVariable(globalUse.getIndirection())
@@ -666,7 +686,7 @@ predicate jumpStep(Node n1, Node n2) {
666686
v = globalDef.getVariable() and
667687
n2.(InitialGlobalValue).getGlobalDef() = globalDef
668688
|
669-
globalDef.getIndirection() = 1 and
689+
globalDef.getIndirection() = getLowerForGlobalDef(globalDef) and
670690
v = n1.asVariable()
671691
or
672692
v = n1.asIndirectVariable(globalDef.getIndirection())

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ cached
3434
private newtype TIRDataFlowNode =
3535
TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or
3636
TVariableNode(Variable var, int indirectionIndex) {
37-
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
37+
exists(int lower |
38+
if var.getUnspecifiedType() instanceof ArrayType then lower = 0 else lower = 1
39+
|
40+
indirectionIndex = [lower .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
41+
)
3842
} or
3943
TPostFieldUpdateNode(FieldAddress operand, int indirectionIndex) {
4044
indirectionIndex =
@@ -346,15 +350,23 @@ class Node extends TIRDataFlowNode {
346350
* Gets the variable corresponding to this node, if any. This can be used for
347351
* modeling flow in and out of global variables.
348352
*/
349-
Variable asVariable() { this = TVariableNode(result, 1) }
353+
Variable asVariable() {
354+
if result.getUnspecifiedType() instanceof ArrayType
355+
then this = TVariableNode(result, 0)
356+
else this = TVariableNode(result, 1)
357+
}
350358

351359
/**
352360
* Gets the `indirectionIndex`'th indirection of this node's underlying variable, if any.
353361
*
354362
* This can be used for modeling flow in and out of global variables.
355363
*/
356364
Variable asIndirectVariable(int indirectionIndex) {
357-
indirectionIndex > 1 and
365+
(
366+
if result.getUnspecifiedType() instanceof ArrayType
367+
then indirectionIndex > 0
368+
else indirectionIndex > 1
369+
) and
358370
this = TVariableNode(result, indirectionIndex)
359371
}
360372

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,11 @@ irFlow
286286
| test.cpp:853:55:853:62 | call to source | test.cpp:854:10:854:36 | * ... |
287287
| test.cpp:860:54:860:59 | call to source | test.cpp:861:10:861:37 | static_local_pointer_dynamic |
288288
| test.cpp:872:46:872:51 | call to source | test.cpp:875:10:875:31 | global_pointer_dynamic |
289+
| test.cpp:880:64:880:83 | indirect_source(1) indirection | test.cpp:883:10:883:45 | static_local_array_static_indirect_1 |
289290
| test.cpp:881:64:881:83 | indirect_source(2) indirection | test.cpp:886:19:886:54 | static_local_array_static_indirect_2 indirection |
290291
| test.cpp:890:54:890:61 | source | test.cpp:893:10:893:36 | static_local_pointer_static |
291292
| test.cpp:891:65:891:84 | indirect_source(1) indirection | test.cpp:895:19:895:56 | static_local_pointer_static_indirect_1 indirection |
293+
| test.cpp:901:56:901:75 | indirect_source(1) indirection | test.cpp:907:10:907:39 | global_array_static_indirect_1 |
292294
| test.cpp:902:56:902:75 | indirect_source(2) indirection | test.cpp:911:19:911:48 | global_array_static_indirect_2 indirection |
293295
| test.cpp:914:46:914:53 | source | test.cpp:919:10:919:30 | global_pointer_static |
294296
| test.cpp:915:57:915:76 | indirect_source(1) indirection | test.cpp:921:19:921:50 | global_pointer_static_indirect_1 indirection |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ namespace GlobalArrays {
880880
static const char static_local_array_static_indirect_1[] = "indirect_source(1)";
881881
static const char static_local_array_static_indirect_2[] = "indirect_source(2)";
882882
sink(static_local_array_static); // clean
883-
sink(static_local_array_static_indirect_1); // $ MISSING: ast,ir
883+
sink(static_local_array_static_indirect_1); // $ ir MISSING: ast
884884
indirect_sink(static_local_array_static_indirect_1); // clean
885885
sink(static_local_array_static_indirect_2); // clean
886886
indirect_sink(static_local_array_static_indirect_2); // $ ir MISSING: ast
@@ -904,7 +904,7 @@ namespace GlobalArrays {
904904
void test7() {
905905
sink(global_array_static); // clean
906906
sink(*global_array_static); // clean
907-
sink(global_array_static_indirect_1); // $ MISSING: ir,ast
907+
sink(global_array_static_indirect_1); // $ ir MISSING: ast
908908
sink(*global_array_static_indirect_1); // clean
909909
indirect_sink(global_array_static); // clean
910910
indirect_sink(global_array_static_indirect_1); // clean

0 commit comments

Comments
 (0)