Skip to content

Commit fbc47ae

Browse files
committed
C++: Eliminate the old way of skipping past copy value instructions in read step.
1 parent 597ae83 commit fbc47ae

7 files changed

Lines changed: 370 additions & 394 deletions

File tree

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

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -301,41 +301,36 @@ predicate storeStep(Node node1, Content c, Node node2) {
301301
arrayStoreStepChi(node1, c, node2)
302302
}
303303

304-
private class ArrayToPointerConvertInstruction extends ConvertInstruction {
305-
ArrayToPointerConvertInstruction() {
306-
this.getUnary().getResultType() instanceof ArrayType and
307-
this.getResultType() instanceof PointerType
308-
}
309-
}
310-
311-
private Instruction skipOneCopyValueInstructionRec(CopyValueInstruction copy) {
312-
copy.getUnary() = result and not result instanceof CopyValueInstruction
313-
or
314-
result = skipOneCopyValueInstructionRec(copy.getUnary())
315-
}
316-
317-
private Instruction skipCopyValueInstructions(Operand op) {
318-
not result instanceof CopyValueInstruction and result = op.getDef()
319-
or
320-
result = skipOneCopyValueInstructionRec(op.getDef())
321-
}
322-
323-
private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) {
304+
private predicate arrayReadStep(Node node1, ArrayContent a, AddressNodeRead node2) {
324305
a = TArrayContent() and
325306
// Explicit dereferences such as `*p` or `p[i]` where `p` is a pointer or array.
326-
exists(LoadOperand operand, Instruction address |
307+
// Note that we don't register read side effects as read steps since we have dataflow from the
308+
// side effect operand's definition to the side effect operand even without a read step. So we only
309+
// use `LoadInstruction`s here.
310+
exists(Operand operand, LoadInstruction load |
311+
operand.getAnyDef() = getSourceValue(load) and
327312
operand.isDefinitionInexact() and
328313
node1.asInstruction() = operand.getAnyDef() and
329-
operand = node2.asOperand() and
330-
address = skipCopyValueInstructions(operand.getAddressOperand()) and
331314
(
332-
address instanceof LoadInstruction or
333-
address instanceof ArrayToPointerConvertInstruction or
334-
address instanceof PointerOffsetInstruction
315+
// `use(p[i])`
316+
exists(PointerAddInstruction add |
317+
add = getSourceAddress(load) and
318+
node2.getInstruction() = add
319+
)
320+
or
321+
// `use(*p)`
322+
// Search backwards through `CopyValue` instructions and check if there's an address instruction
323+
// that is not just a glvalue.
324+
exists(Instruction i | i = instructionOrUnaryDefinition(getSourceAddress(load)) |
325+
not i.isGLValue() and
326+
i.getResultIRType() instanceof IRAddressType and
327+
node2.getInstruction() = getSourceAddress(load)
328+
)
335329
) and
330+
// Don't perform an array read step if we're already performing a field read step.
336331
not exists(Instruction i |
337332
fieldReadStep(addressNodeRead(i), _, _) and
338-
AddressFlow::addressFlowInstrTC(i, operand.getUse())
333+
AddressFlow::addressFlowInstrTC(i, load)
339334
)
340335
)
341336
}

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

Lines changed: 44 additions & 97 deletions
Large diffs are not rendered by default.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ void sink(int x)
3939

4040
void bar(Outer &b)
4141
{
42-
sink(b.inner.f.a()); // $ ast=53:19 ast=55:19 MISSING: ir
43-
sink(b.inner.f.b()); // $ ast=54:19 ast=56:19 MISSING: ir
42+
sink(b.inner.f.a()); // $ ast,ir=53:19 ast,ir=55:19
43+
sink(b.inner.f.b()); // $ ast,ir=54:19 ast,ir=56:19
4444
}
4545

4646
void foo()

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

Lines changed: 123 additions & 165 deletions
Large diffs are not rendered by default.

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

Lines changed: 173 additions & 97 deletions
Large diffs are not rendered by default.

cpp/ql/test/library-tests/dataflow/fields/struct_init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct Outer {
1212
};
1313

1414
void absink(struct AB *ab) {
15-
sink(ab->a); //$ ast=20:20 ast=27:7 ast=40:20 ir
15+
sink(ab->a); //$ ast,ir=20:20 ast,ir=27:7 ast=40:20
1616
sink(ab->b); // no flow
1717
}
1818

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ void test_copy_assignment_operator()
7575

7676
y = x;
7777

78-
sink(y.data1); // $ ast=71:15 SPURIOUS: ast=69:23 MISSING: ir
78+
sink(y.data1); // $ ast=71:15 ir SPURIOUS: ast=69:23
7979
sink(x.data1); // $ ast,ir
8080

8181
IntWrapper::Class z1, z2;
@@ -84,7 +84,7 @@ void test_copy_assignment_operator()
8484

8585
swap(z1, z2);
8686

87-
sink(z2.data1); // $ MISSING: ast,ir
87+
sink(z2.data1); // $ ir MISSING: ast
8888
sink(z1.data1); // $ SPURIOUS: ir ast=81:27 ast=82:16
8989
}
9090

@@ -99,7 +99,7 @@ void test_move_assignment_operator()
9999

100100
y = std::move(x);
101101

102-
sink(y.data1); // $ ast=95:15 SPURIOUS: ast=93:23 MISSING: ir
102+
sink(y.data1); // $ ast=95:15 ir SPURIOUS: ast=93:23
103103
sink(x.data1); // $ ast,ir
104104
}
105105

@@ -126,7 +126,7 @@ void test_copy_assignment_method()
126126

127127
y.copy_assign(x);
128128

129-
sink(y.data1); // $ ast=122:15 SPURIOUS: ast=120:23 MISSING: ir
129+
sink(y.data1); // $ ast=122:15 ir SPURIOUS: ast=120:23
130130
sink(x.data1); // $ ast,ir
131131
}
132132

@@ -141,7 +141,7 @@ void test_move_assignment_method()
141141

142142
y.move_assign(std::move(x));
143143

144-
sink(y.data1); // $ ast=137:15 SPURIOUS: ast=135:23 MISSING: ir
144+
sink(y.data1); // $ ast=137:15 ir SPURIOUS: ast=135:23
145145
sink(x.data1); // $ ast,ir
146146
}
147147

0 commit comments

Comments
 (0)