Skip to content

Commit 2ceb4cf

Browse files
authored
Merge pull request github#14736 from MathiasVP/fix-global-indirect-flow
C++: Fix indirect global-variable flow
2 parents c71bdce + 39b9d2e commit 2ceb4cf

File tree

5 files changed

+89
-22
lines changed

5 files changed

+89
-22
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,20 +632,20 @@ predicate jumpStep(Node n1, Node n2) {
632632
v = globalUse.getVariable() and
633633
n1.(FinalGlobalValue).getGlobalUse() = globalUse
634634
|
635-
globalUse.getIndirectionIndex() = 1 and
635+
globalUse.getIndirection() = 1 and
636636
v = n2.asVariable()
637637
or
638-
v = n2.asIndirectVariable(globalUse.getIndirectionIndex())
638+
v = n2.asIndirectVariable(globalUse.getIndirection())
639639
)
640640
or
641641
exists(Ssa::GlobalDef globalDef |
642642
v = globalDef.getVariable() and
643643
n2.(InitialGlobalValue).getGlobalDef() = globalDef
644644
|
645-
globalDef.getIndirectionIndex() = 1 and
645+
globalDef.getIndirection() = 1 and
646646
v = n1.asVariable()
647647
or
648-
v = n1.asIndirectVariable(globalDef.getIndirectionIndex())
648+
v = n1.asIndirectVariable(globalDef.getIndirection())
649649
)
650650
)
651651
}

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

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -113,22 +113,12 @@ private newtype TDefOrUseImpl =
113113
TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
114114
// Represents a final "use" of a global variable to ensure that
115115
// the assignment to a global variable isn't ruled out as dead.
116-
exists(VariableAddressInstruction vai, int defIndex |
117-
vai.getEnclosingIRFunction() = f and
118-
vai.getAstVariable() = v and
119-
isDef(_, _, _, vai, _, defIndex) and
120-
indirectionIndex = [0 .. defIndex] + 1
121-
)
116+
isGlobalUse(v, f, _, indirectionIndex)
122117
} or
123118
TGlobalDefImpl(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
124119
// Represents the initial "definition" of a global variable when entering
125120
// a function body.
126-
exists(VariableAddressInstruction vai |
127-
vai.getEnclosingIRFunction() = f and
128-
vai.getAstVariable() = v and
129-
isUse(_, _, vai, _, indirectionIndex) and
130-
not isDef(_, _, vai.getAUse(), _, _, _)
131-
)
121+
isGlobalDefImpl(v, f, _, indirectionIndex)
132122
} or
133123
TIteratorDef(
134124
Operand iteratorDerefAddress, BaseSourceVariableInstruction container, int indirectionIndex
@@ -150,6 +140,27 @@ private newtype TDefOrUseImpl =
150140
)
151141
}
152142

143+
private predicate isGlobalUse(
144+
GlobalLikeVariable v, IRFunction f, int indirection, int indirectionIndex
145+
) {
146+
exists(VariableAddressInstruction vai |
147+
vai.getEnclosingIRFunction() = f and
148+
vai.getAstVariable() = v and
149+
isDef(_, _, _, vai, indirection, indirectionIndex)
150+
)
151+
}
152+
153+
private predicate isGlobalDefImpl(
154+
GlobalLikeVariable v, IRFunction f, int indirection, int indirectionIndex
155+
) {
156+
exists(VariableAddressInstruction vai |
157+
vai.getEnclosingIRFunction() = f and
158+
vai.getAstVariable() = v and
159+
isUse(_, _, vai, indirection, indirectionIndex) and
160+
not isDef(_, _, _, vai, _, indirectionIndex)
161+
)
162+
}
163+
153164
private predicate unspecifiedTypeIsModifiableAt(Type unspecified, int indirectionIndex) {
154165
indirectionIndex = [1 .. getIndirectionForUnspecifiedType(unspecified).getNumberOfIndirections()] and
155166
exists(CppType cppType |
@@ -438,7 +449,7 @@ class GlobalUse extends UseImpl, TGlobalUse {
438449

439450
override FinalGlobalValue getNode() { result.getGlobalUse() = this }
440451

441-
override int getIndirection() { result = ind + 1 }
452+
override int getIndirection() { isGlobalUse(global, f, result, ind) }
442453

443454
/** Gets the global variable associated with this use. */
444455
GlobalLikeVariable getVariable() { result = global }
@@ -460,7 +471,9 @@ class GlobalUse extends UseImpl, TGlobalUse {
460471
)
461472
}
462473

463-
override SourceVariable getSourceVariable() { sourceVariableIsGlobal(result, global, f, ind) }
474+
override SourceVariable getSourceVariable() {
475+
sourceVariableIsGlobal(result, global, f, this.getIndirection())
476+
}
464477

465478
final override Cpp::Location getLocation() { result = f.getLocation() }
466479

@@ -501,16 +514,18 @@ class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
501514

502515
/** Gets the global variable associated with this definition. */
503516
override SourceVariable getSourceVariable() {
504-
sourceVariableIsGlobal(result, global, f, indirectionIndex)
517+
sourceVariableIsGlobal(result, global, f, this.getIndirection())
505518
}
506519

520+
int getIndirection() { result = indirectionIndex }
521+
507522
/**
508523
* Gets the type of this use after specifiers have been deeply stripped
509524
* and typedefs have been resolved.
510525
*/
511526
Type getUnspecifiedType() { result = global.getUnspecifiedType() }
512527

513-
override string toString() { result = "GlobalDef" }
528+
override string toString() { result = "Def of " + this.getSourceVariable() }
514529

515530
override Location getLocation() { result = f.getLocation() }
516531

@@ -980,7 +995,7 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse {
980995
final override Location getLocation() { result = global.getLocation() }
981996

982997
/** Gets a textual representation of this definition. */
983-
override string toString() { result = "GlobalDef" }
998+
override string toString() { result = global.toString() }
984999

9851000
/**
9861001
* Holds if this definition has index `index` in block `block`, and
@@ -990,6 +1005,9 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse {
9901005
global.hasIndexInBlock(block, index, sv)
9911006
}
9921007

1008+
/** Gets the indirection index of this definition. */
1009+
int getIndirection() { result = global.getIndirection() }
1010+
9931011
/** Gets the indirection index of this definition. */
9941012
int getIndirectionIndex() { result = global.getIndirectionIndex() }
9951013

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ argHasPostUpdate
2323
| lambdas.cpp:38:2:38:2 | d | ArgumentNode is missing PostUpdateNode. |
2424
| lambdas.cpp:45:2:45:2 | e | ArgumentNode is missing PostUpdateNode. |
2525
| test.cpp:67:29:67:35 | source1 | ArgumentNode is missing PostUpdateNode. |
26+
| test.cpp:813:19:813:35 | * ... | ArgumentNode is missing PostUpdateNode. |
2627
postWithInFlow
2728
| BarrierGuard.cpp:49:6:49:6 | x [post update] | PostUpdateNode should not be the target of local flow. |
2829
| BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. |
@@ -136,6 +137,9 @@ postWithInFlow
136137
| test.cpp:728:3:728:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
137138
| test.cpp:728:4:728:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
138139
| test.cpp:734:41:734:41 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
140+
| test.cpp:808:5:808:21 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
141+
| test.cpp:808:6:808:21 | global_indirect1 [inner post update] | PostUpdateNode should not be the target of local flow. |
142+
| test.cpp:832:5:832:17 | global_direct [post update] | PostUpdateNode should not be the target of local flow. |
139143
viableImplInCallContextTooLarge
140144
uniqueParameterNodeAtPosition
141145
uniqueParameterNodePosition

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,4 +796,44 @@ void test() {
796796
MyStruct a;
797797
intPointerSource(a.content, a.content);
798798
indirect_sink(a.content); // $ ast ir
799+
}
800+
801+
namespace MoreGlobalTests {
802+
int **global_indirect1;
803+
int **global_indirect2;
804+
int **global_direct;
805+
806+
void set_indirect1()
807+
{
808+
*global_indirect1 = indirect_source();
809+
}
810+
811+
void read_indirect1() {
812+
sink(global_indirect1); // clean
813+
indirect_sink(*global_indirect1); // $ ir MISSING: ast
814+
}
815+
816+
void set_indirect2()
817+
{
818+
**global_indirect2 = source();
819+
}
820+
821+
void read_indirect2() {
822+
sink(global_indirect2); // clean
823+
sink(**global_indirect2); // $ ir MISSING: ast
824+
}
825+
826+
// overload source with a boolean parameter so
827+
// that we can define a variant that return an int**.
828+
int** source(bool);
829+
830+
void set_direct()
831+
{
832+
global_direct = source(true);
833+
}
834+
835+
void read_direct() {
836+
sink(global_direct); // $ ir MISSING: ast
837+
indirect_sink(global_direct); // clean
838+
}
799839
}

cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ uniqueType
44
uniqueNodeLocation
55
missingLocation
66
uniqueNodeToString
7-
| cpp11.cpp:50:15:50:16 | (no string representation) | Node should have one toString but has 0. |
7+
| builtin.c:5:5:5:11 | (no string representation) | Node should have one toString but has 0. |
8+
| misc.c:227:7:227:28 | (no string representation) | Node should have one toString but has 0. |
9+
| static_init_templates.cpp:80:18:80:23 | (no string representation) | Node should have one toString but has 0. |
10+
| static_init_templates.cpp:80:18:80:23 | (no string representation) | Node should have one toString but has 0. |
11+
| static_init_templates.cpp:89:18:89:23 | (no string representation) | Node should have one toString but has 0. |
12+
| static_init_templates.cpp:89:18:89:23 | (no string representation) | Node should have one toString but has 0. |
813
parameterCallable
914
localFlowIsLocal
1015
readStepIsLocal

0 commit comments

Comments
 (0)