Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 349c5cd

Browse files
authored
Merge pull request #11254 from MathiasVP/fix-ssa-flow
C++: Fix spurious reference flow
2 parents cfb8f28 + fc3d6a1 commit 349c5cd

14 files changed

Lines changed: 73 additions & 87 deletions

File tree

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

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,13 @@ class Node extends TIRDataFlowNode {
235235
Expr asIndirectArgument() { result = this.asIndirectArgument(_) }
236236

237237
/** Gets the positional parameter corresponding to this node, if any. */
238-
Parameter asParameter() { result = this.asParameter(0) }
238+
Parameter asParameter() {
239+
exists(int indirectionIndex | result = this.asParameter(indirectionIndex) |
240+
if result.getUnspecifiedType() instanceof ReferenceType
241+
then indirectionIndex = 1
242+
else indirectionIndex = 0
243+
)
244+
}
239245

240246
/**
241247
* Gets the uninitialized local variable corresponding to this node, if
@@ -1233,35 +1239,11 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
12331239
)
12341240
}
12351241

1236-
pragma[noinline]
1237-
private predicate getAddressType(LoadInstruction load, Type t) {
1238-
exists(Instruction address |
1239-
address = load.getSourceAddress() and
1240-
t = address.getResultType()
1241-
)
1242-
}
1243-
1244-
/**
1245-
* Like the AST dataflow library, we want to conflate the address and value of a reference. This class
1246-
* represents the `LoadInstruction` that is generated from a reference dereference.
1247-
*/
1248-
private class ReferenceDereferenceInstruction extends LoadInstruction {
1249-
ReferenceDereferenceInstruction() {
1250-
exists(ReferenceType ref |
1251-
getAddressType(this, ref) and
1252-
this.getResultType() = ref.getBaseType()
1253-
)
1254-
}
1255-
}
1256-
12571242
private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo) {
12581243
// Treat all conversions as flow, even conversions between different numeric types.
12591244
conversionFlow(opFrom, iTo, false)
12601245
or
12611246
iTo.(CopyInstruction).getSourceValueOperand() = opFrom
1262-
or
1263-
// Conflate references and values like in AST dataflow.
1264-
iTo.(ReferenceDereferenceInstruction).getSourceAddressOperand() = opFrom
12651247
}
12661248

12671249
private predicate simpleOperandLocalFlowStep(Instruction iFrom, Operand opTo) {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,10 @@ predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
275275
exists(IRBlock bb1, int i1, SourceVariable v |
276276
defOrUse1.asDefOrUse().hasIndexInBlock(bb1, i1, v)
277277
|
278-
exists(IRBlock bb2, int i2 |
279-
adjacentDefRead(_, pragma[only_bind_into](bb1), pragma[only_bind_into](i1),
280-
pragma[only_bind_into](bb2), pragma[only_bind_into](i2))
281-
|
278+
exists(IRBlock bb2, int i2, Definition def |
279+
adjacentDefRead(pragma[only_bind_into](def), pragma[only_bind_into](bb1),
280+
pragma[only_bind_into](i1), pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) and
281+
def.getSourceVariable() = v and
282282
use.asDefOrUse().(UseImpl).hasIndexInBlock(bb2, i2, v)
283283
)
284284
or

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,11 @@ private module Cached {
197197
predicate isUse(boolean certain, Operand op, Instruction base, int ind, int indirectionIndex) {
198198
not ignoreOperand(op) and
199199
certain = true and
200-
exists(LanguageType type, int m, int ind0 |
200+
exists(LanguageType type, int upper, int ind0 |
201201
type = getLanguageType(op) and
202-
m = countIndirectionsForCppType(type) and
202+
upper = countIndirectionsForCppType(type) and
203203
isUseImpl(op, base, ind0) and
204-
ind = ind0 + [0 .. m] and
204+
ind = ind0 + [0 .. upper] and
205205
indirectionIndex = ind - ind0
206206
)
207207
}
@@ -277,7 +277,7 @@ private module Cached {
277277
int indirectionIndex
278278
) {
279279
certain = true and
280-
exists(int ind0, CppType type, int m |
280+
exists(int ind0, CppType type, int lower, int upper |
281281
address =
282282
[
283283
instr.(StoreInstruction).getDestinationAddressOperand(),
@@ -288,9 +288,10 @@ private module Cached {
288288
|
289289
isDefImpl(address, base, ind0) and
290290
type = getLanguageType(address) and
291-
m = countIndirectionsForCppType(type) and
292-
ind = ind0 + [1 .. m] and
293-
indirectionIndex = ind - (ind0 + 1)
291+
upper = countIndirectionsForCppType(type) and
292+
ind = ind0 + [lower .. upper] and
293+
indirectionIndex = ind - (ind0 + lower) and
294+
if type.hasType(any(Cpp::ArrayType arrayType), true) then lower = 0 else lower = 1
294295
)
295296
}
296297

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ postWithInFlow
8585
| test.cpp:407:10:407:13 | ref arg & ... | PostUpdateNode should not be the target of local flow. |
8686
| test.cpp:407:11:407:13 | tmp [inner post update] | PostUpdateNode should not be the target of local flow. |
8787
| test.cpp:423:21:423:25 | local [inner post update] | PostUpdateNode should not be the target of local flow. |
88-
| test.cpp:436:19:436:23 | local [inner post update] | PostUpdateNode should not be the target of local flow. |
89-
| test.cpp:465:3:465:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
90-
| test.cpp:465:4:465:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
91-
| test.cpp:470:22:470:22 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
92-
| test.cpp:499:3:499:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
93-
| test.cpp:499:4:499:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
94-
| test.cpp:505:35:505:35 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
88+
| test.cpp:441:19:441:23 | local [inner post update] | PostUpdateNode should not be the target of local flow. |
89+
| test.cpp:472:3:472:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
90+
| test.cpp:472:4:472:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
91+
| test.cpp:477:22:477:22 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
92+
| test.cpp:506:3:506:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
93+
| test.cpp:506:4:506:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
94+
| test.cpp:512:35:512:35 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
9595
viableImplInCallContextTooLarge

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@
7171
| test.cpp:391:11:391:13 | tmp | test.cpp:391:10:391:13 | & ... |
7272
| test.cpp:391:17:391:23 | source1 | test.cpp:391:10:391:13 | ref arg & ... |
7373
| test.cpp:391:17:391:23 | source1 | test.cpp:391:16:391:23 | & ... |
74-
| test.cpp:480:67:480:67 | s | test.cpp:480:67:480:67 | s |
75-
| test.cpp:480:67:480:67 | s | test.cpp:481:21:481:21 | s |
76-
| test.cpp:480:67:480:67 | s | test.cpp:482:20:482:20 | s |
77-
| test.cpp:481:21:481:21 | s [post update] | test.cpp:480:67:480:67 | s |
78-
| test.cpp:481:21:481:21 | s [post update] | test.cpp:482:20:482:20 | s |
79-
| test.cpp:481:24:481:30 | ref arg content | test.cpp:482:23:482:29 | content |
80-
| test.cpp:482:23:482:29 | content | test.cpp:483:9:483:17 | p_content |
74+
| test.cpp:487:67:487:67 | s | test.cpp:487:67:487:67 | s |
75+
| test.cpp:487:67:487:67 | s | test.cpp:488:21:488:21 | s |
76+
| test.cpp:487:67:487:67 | s | test.cpp:489:20:489:20 | s |
77+
| test.cpp:488:21:488:21 | s [post update] | test.cpp:487:67:487:67 | s |
78+
| test.cpp:488:21:488:21 | s [post update] | test.cpp:489:20:489:20 | s |
79+
| test.cpp:488:24:488:30 | ref arg content | test.cpp:489:23:489:29 | content |
80+
| test.cpp:489:23:489:29 | content | test.cpp:490:9:490:17 | p_content |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ namespace withoutFields {
5656
sink(x1); // $ ast,ir=55:23 SPURIOUS: ast,ir=53:9
5757

5858
notAssign(x2, source());
59-
sink(x2); // $ SPURIOUS: ast ir=53:13 ir=58:19
59+
sink(x2); // $ SPURIOUS: ast ir
6060

6161
sourceToParamWrapper(x3);
6262
sink(x3); // $ ast,ir=29:11 SPURIOUS: ast,ir=53:17
6363

6464
notSource(x4);
65-
sink(x4); // $ SPURIOUS: ast ir=44:11 ir=53:21
65+
sink(x4); // $ SPURIOUS: ast ir
6666
}
6767
}
6868

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void trackUninitialized() {
8989
void local_references(int &source1, int clean1) {
9090
sink(source1); // $ ast,ir
9191
source1 = clean1;
92-
sink(source1); // $ SPURIOUS: ir
92+
sink(source1); // clean
9393

9494
// The next two test cases show that the analysis does not understand the "&"
9595
// on the type at all. It does not understand that the initialization creates
@@ -423,25 +423,32 @@ void intPointerSourceCaller() {
423423
intPointerSource(&local);
424424
sink(local); // $ ast,ir=422:7 ast,ir=423:20
425425
}
426-
426+
// The IR results for this test _are_ equivalent to the AST ones.
427+
// The IR annotation is just "ir" because the sink of the unitialized source at
428+
// `433:7` (i.e., the declaration `int local[1];`) is value of `local`, but the sink
429+
// of the source from `intPointerSource` value of `*local` (i.e., the indirection node
430+
// of `local`). So unlike AST dataflow, each of these two sinks correspond to a unique
431+
// source, and thus we don't need to attach a location annotation to it.
427432
void intPointerSourceCaller2() {
428433
int local[1];
429434
intPointerSource(local);
430-
sink(local); // $ ast,ir=428:7 ast,ir=429:20
431-
sink(*local); // $ ast,ir=428:7 ast,ir=429:20
435+
sink(local); // $ ast=433:7 ast=434:20 ir
436+
sink(*local); // $ ast=433:7 ast=434:20 ir
432437
}
433438

434439
void intArraySourceCaller() {
435440
int local;
436441
intArraySource(&local, 1);
437-
sink(local); // $ ast,ir=435:7 ast,ir=436:18
442+
sink(local); // $ ast,ir=440:7 ast,ir=441:18
438443
}
439444

445+
// The IR results for this test _are_ equivalent to the AST ones.
446+
// See the comment on `intPointerSourceCaller2` for an explanation.
440447
void intArraySourceCaller2() {
441448
int local[2];
442449
intArraySource(local, 2);
443-
sink(local); // $ ast,ir=441:7 ast,ir=442:18
444-
sink(*local); // $ ast,ir=441:7 ast,ir=442:18
450+
sink(local); // $ ast=448:7 ast=449:18 ir
451+
sink(*local); // $ ast=448:7 ast=449:18 ir
445452
}
446453

447454
///////////////////////////////////////////////////////////////////////////////

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
| test.cpp:416:7:416:11 | local | test.cpp:418:8:418:12 | local |
2727
| test.cpp:422:7:422:11 | local | test.cpp:423:21:423:25 | local |
2828
| test.cpp:422:7:422:11 | local | test.cpp:424:8:424:12 | local |
29-
| test.cpp:428:7:428:11 | local | test.cpp:429:20:429:24 | local |
30-
| test.cpp:428:7:428:11 | local | test.cpp:430:8:430:12 | local |
31-
| test.cpp:428:7:428:11 | local | test.cpp:431:9:431:13 | local |
32-
| test.cpp:435:7:435:11 | local | test.cpp:436:19:436:23 | local |
33-
| test.cpp:435:7:435:11 | local | test.cpp:437:8:437:12 | local |
34-
| test.cpp:441:7:441:11 | local | test.cpp:442:18:442:22 | local |
35-
| test.cpp:441:7:441:11 | local | test.cpp:443:8:443:12 | local |
36-
| test.cpp:441:7:441:11 | local | test.cpp:444:9:444:13 | local |
29+
| test.cpp:433:7:433:11 | local | test.cpp:434:20:434:24 | local |
30+
| test.cpp:433:7:433:11 | local | test.cpp:435:8:435:12 | local |
31+
| test.cpp:433:7:433:11 | local | test.cpp:436:9:436:13 | local |
32+
| test.cpp:440:7:440:11 | local | test.cpp:441:19:441:23 | local |
33+
| test.cpp:440:7:440:11 | local | test.cpp:442:8:442:12 | local |
34+
| test.cpp:448:7:448:11 | local | test.cpp:449:18:449:22 | local |
35+
| test.cpp:448:7:448:11 | local | test.cpp:450:8:450:12 | local |
36+
| test.cpp:448:7:448:11 | local | test.cpp:451:9:451:13 | local |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class A
5454
B *b = new B();
5555
b->set(new C1());
5656
sink(b->get()); // $ ast ir=55:12
57-
sink((new B(new C()))->get()); // $ ast ir=57:17
57+
sink((new B(new C()))->get()); // $ ast ir
5858
}
5959

6060
void f3()
@@ -129,7 +129,7 @@ class A
129129
{
130130
B *b = new B();
131131
f7(b);
132-
sink(b->c); // $ ast ir=126:12
132+
sink(b->c); // $ ast ir
133133
}
134134

135135
class D

cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ edges
3535
| A.cpp:57:11:57:24 | new indirection [c] | A.cpp:57:11:57:24 | new indirection [c] |
3636
| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c |
3737
| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | call to B [c] |
38-
| A.cpp:57:17:57:23 | new | A.cpp:57:17:57:23 | new |
3938
| A.cpp:64:10:64:15 | call to setOnB indirection [c] | A.cpp:66:10:66:11 | Load indirection [c] |
4039
| A.cpp:64:21:64:28 | new | A.cpp:64:10:64:15 | call to setOnB indirection [c] |
4140
| A.cpp:64:21:64:28 | new | A.cpp:64:21:64:28 | new |
@@ -77,7 +76,6 @@ edges
7776
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:131:8:131:8 | f7 output argument [c] |
7877
| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c |
7978
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | set output argument [c] |
80-
| A.cpp:126:12:126:18 | new | A.cpp:126:12:126:18 | new |
8179
| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:132:10:132:10 | Load indirection [c] |
8280
| A.cpp:132:10:132:10 | Load indirection [c] | A.cpp:132:10:132:13 | c |
8381
| A.cpp:132:10:132:10 | Load indirection [c] | A.cpp:132:13:132:13 | FieldAddress indirection |
@@ -924,7 +922,6 @@ nodes
924922
| A.cpp:57:11:57:24 | call to B [c] | semmle.label | call to B [c] |
925923
| A.cpp:57:11:57:24 | new indirection [c] | semmle.label | new indirection [c] |
926924
| A.cpp:57:17:57:23 | new | semmle.label | new |
927-
| A.cpp:57:17:57:23 | new | semmle.label | new |
928925
| A.cpp:64:10:64:15 | call to setOnB indirection [c] | semmle.label | call to setOnB indirection [c] |
929926
| A.cpp:64:21:64:28 | new | semmle.label | new |
930927
| A.cpp:64:21:64:28 | new | semmle.label | new |
@@ -962,7 +959,6 @@ nodes
962959
| A.cpp:120:16:120:16 | a | semmle.label | a |
963960
| A.cpp:126:5:126:5 | set output argument [c] | semmle.label | set output argument [c] |
964961
| A.cpp:126:12:126:18 | new | semmle.label | new |
965-
| A.cpp:126:12:126:18 | new | semmle.label | new |
966962
| A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] |
967963
| A.cpp:132:10:132:10 | Load indirection [c] | semmle.label | Load indirection [c] |
968964
| A.cpp:132:10:132:13 | c | semmle.label | c |
@@ -1772,7 +1768,6 @@ subpaths
17721768
| A.cpp:56:10:56:17 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:10:56:17 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new |
17731769
| A.cpp:56:10:56:17 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:10:56:17 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new |
17741770
| A.cpp:57:10:57:32 | call to get | A.cpp:57:17:57:23 | new | A.cpp:57:10:57:32 | call to get | call to get flows from $@ | A.cpp:57:17:57:23 | new | new |
1775-
| A.cpp:57:10:57:32 | call to get | A.cpp:57:17:57:23 | new | A.cpp:57:10:57:32 | call to get | call to get flows from $@ | A.cpp:57:17:57:23 | new | new |
17761771
| A.cpp:66:10:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:10:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new |
17771772
| A.cpp:66:10:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:10:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new |
17781773
| A.cpp:66:14:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:14:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new |
@@ -1786,8 +1781,6 @@ subpaths
17861781
| A.cpp:120:12:120:16 | a | A.cpp:98:12:98:18 | new | A.cpp:120:12:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
17871782
| A.cpp:120:16:120:16 | a | A.cpp:98:12:98:18 | new | A.cpp:120:16:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
17881783
| A.cpp:132:10:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:10:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new |
1789-
| A.cpp:132:10:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:10:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new |
1790-
| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new |
17911784
| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new |
17921785
| A.cpp:152:10:152:13 | b | A.cpp:143:25:143:31 | new | A.cpp:152:10:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new | new |
17931786
| A.cpp:152:10:152:13 | b | A.cpp:150:12:150:18 | new | A.cpp:152:10:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new | new |

0 commit comments

Comments
 (0)