Skip to content

Commit b40fd95

Browse files
C++: Better tracking of SSA memory accesses
This change fixes a few key problems with the existing SSA implementations: For unaliased SSA, we were incorrectly choosing to model a local variable that had accesses that did not cover the entire variable. This has been changed to ensure that all accesses to the variable are at offset zero and have the same type as the variable itself. This was only possible to fix now that every `MemoryOperand` has its own type. For aliased SSA, we now correctly track the offset and size of each memory access using an interval of bit offsets covered by the access. The offset interval makes the overlap computation more straightforward. Again, this is only possible now that operands have types. The `getXXXMemoryAccess` predicates are now driven by the `MemoryAccessKind` on the operands and results, instead of by specific opcodes. This change does fix an existing false negative in the IR dataflow tests. I added a few simple test cases to the SSA IR tests, covering the various kinds of overlap (MustExcactly, MustTotally, and MayPartially). I added "PrintSSA.qll", which can dump the SSA memory accesses as part of an IR dump.
1 parent 055485d commit b40fd95

File tree

20 files changed

+722
-130
lines changed

20 files changed

+722
-130
lines changed

config/identical-files.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@
6868
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
6969
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"
7070
],
71+
"C++ SSA PrintSSA": [
72+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll",
73+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll"
74+
],
7175
"C++ IR ValueNumber": [
7276
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll",
7377
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll",

cpp/ql/src/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ private newtype TMemoryAccessKind =
66
TBufferMemoryAccess() or
77
TBufferMayMemoryAccess() or
88
TEscapedMemoryAccess() or
9+
TEscapedMayMemoryAccess() or
910
TPhiMemoryAccess() or
1011
TUnmodeledMemoryAccess() or
1112
TChiTotalMemoryAccess() or
@@ -16,7 +17,17 @@ private newtype TMemoryAccessKind =
1617
* memory result.
1718
*/
1819
class MemoryAccessKind extends TMemoryAccessKind {
19-
abstract string toString();
20+
string toString() {
21+
none()
22+
}
23+
24+
/**
25+
* Holds if the operand or result accesses memory pointed to by the `AddressOperand` on the
26+
* same instruction.
27+
*/
28+
predicate usesAddressOperand() {
29+
none()
30+
}
2031
}
2132

2233
/**
@@ -27,6 +38,10 @@ class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
2738
override string toString() {
2839
result = "indirect"
2940
}
41+
42+
override final predicate usesAddressOperand() {
43+
any()
44+
}
3045
}
3146

3247
/**
@@ -37,6 +52,10 @@ class IndirectMayMemoryAccess extends MemoryAccessKind, TIndirectMayMemoryAccess
3752
override string toString() {
3853
result = "indirect(may)"
3954
}
55+
56+
override final predicate usesAddressOperand() {
57+
any()
58+
}
4059
}
4160

4261
/**
@@ -48,6 +67,10 @@ class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
4867
override string toString() {
4968
result = "buffer"
5069
}
70+
71+
override final predicate usesAddressOperand() {
72+
any()
73+
}
5174
}
5275

5376
/**
@@ -59,6 +82,10 @@ class BufferMayMemoryAccess extends MemoryAccessKind, TBufferMayMemoryAccess {
5982
override string toString() {
6083
result = "buffer(may)"
6184
}
85+
86+
override final predicate usesAddressOperand() {
87+
any()
88+
}
6289
}
6390

6491
/**
@@ -70,6 +97,15 @@ class EscapedMemoryAccess extends MemoryAccessKind, TEscapedMemoryAccess {
7097
}
7198
}
7299

100+
/**
101+
* The operand or result may access all memory whose address has escaped.
102+
*/
103+
class EscapedMayMemoryAccess extends MemoryAccessKind, TEscapedMayMemoryAccess {
104+
override string toString() {
105+
result = "escaped(may)"
106+
}
107+
}
108+
73109
/**
74110
* The operand is a Phi operand, which accesses the same memory as its
75111
* definition.

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,16 @@ class Instruction extends Construction::TInstruction {
498498
none()
499499
}
500500

501+
/**
502+
* Returns the operand that holds the memory address to which the instruction stores its
503+
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
504+
* is `r1`.
505+
*/
506+
final AddressOperand getResultAddressOperand() {
507+
getResultMemoryAccess().usesAddressOperand() and
508+
result.getUseInstruction() = this
509+
}
510+
501511
/**
502512
* Holds if the result of this instruction is precisely modeled in SSA. Always
503513
* holds for a register result. For a memory result, a modeled result is
@@ -1340,7 +1350,7 @@ class CallSideEffectInstruction extends SideEffectInstruction {
13401350
}
13411351

13421352
override final MemoryAccessKind getResultMemoryAccess() {
1343-
result instanceof EscapedMemoryAccess
1353+
result instanceof EscapedMayMemoryAccess
13441354
}
13451355
}
13461356

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class MemoryOperand extends Operand {
128128
* is `r1`.
129129
*/
130130
final AddressOperand getAddressOperand() {
131-
getMemoryAccess() instanceof IndirectMemoryAccess and
131+
getMemoryAccess().usesAddressOperand() and
132132
result.getUseInstruction() = getUseInstruction()
133133
}
134134
}
@@ -351,10 +351,10 @@ class SideEffectOperand extends TypedOperand {
351351

352352
override MemoryAccessKind getMemoryAccess() {
353353
useInstr instanceof CallSideEffectInstruction and
354-
result instanceof EscapedMemoryAccess
354+
result instanceof EscapedMayMemoryAccess
355355
or
356356
useInstr instanceof CallReadSideEffectInstruction and
357-
result instanceof EscapedMemoryAccess
357+
result instanceof EscapedMayMemoryAccess
358358
or
359359
useInstr instanceof IndirectReadSideEffectInstruction and
360360
result instanceof IndirectMemoryAccess

0 commit comments

Comments
 (0)