Skip to content

Commit ec95197

Browse files
author
Robert Marsh
authored
Merge pull request #2451 from dbartol/dbartol/May-Must
C++/C#: Consistent handling of "may" vs. "must" memory accesses
2 parents 73c8888 + cbb6797 commit ec95197

File tree

20 files changed

+528
-343
lines changed

20 files changed

+528
-343
lines changed

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

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
private newtype TMemoryAccessKind =
22
TIndirectMemoryAccess() or
3-
TIndirectMayMemoryAccess() or
43
TBufferMemoryAccess() or
5-
TBufferMayMemoryAccess() or
64
TEscapedMemoryAccess() or
7-
TEscapedMayMemoryAccess() or
8-
TNonLocalMayMemoryAccess() or
5+
TNonLocalMemoryAccess() or
96
TPhiMemoryAccess() or
107
TUnmodeledMemoryAccess() or
118
TChiTotalMemoryAccess() or
@@ -35,16 +32,6 @@ class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
3532
final override predicate usesAddressOperand() { any() }
3633
}
3734

38-
/**
39-
* The operand or result may access some, all, or none of the memory at the address specified by the
40-
* `AddressOperand` on the same instruction.
41-
*/
42-
class IndirectMayMemoryAccess extends MemoryAccessKind, TIndirectMayMemoryAccess {
43-
override string toString() { result = "indirect(may)" }
44-
45-
final override predicate usesAddressOperand() { any() }
46-
}
47-
4835
/**
4936
* The operand or result accesses memory starting at the address specified by the `AddressOperand`
5037
* on the same instruction, accessing a number of consecutive elements given by the
@@ -56,17 +43,6 @@ class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
5643
final override predicate usesAddressOperand() { any() }
5744
}
5845

59-
/**
60-
* The operand or result may access some, all, or none of the memory starting at the address
61-
* specified by the `AddressOperand` on the same instruction, accessing a number of consecutive
62-
* elements given by the `BufferSizeOperand`.
63-
*/
64-
class BufferMayMemoryAccess extends MemoryAccessKind, TBufferMayMemoryAccess {
65-
override string toString() { result = "buffer(may)" }
66-
67-
final override predicate usesAddressOperand() { any() }
68-
}
69-
7046
/**
7147
* The operand or result accesses all memory whose address has escaped.
7248
*/
@@ -75,18 +51,11 @@ class EscapedMemoryAccess extends MemoryAccessKind, TEscapedMemoryAccess {
7551
}
7652

7753
/**
78-
* The operand or result may access all memory whose address has escaped.
79-
*/
80-
class EscapedMayMemoryAccess extends MemoryAccessKind, TEscapedMayMemoryAccess {
81-
override string toString() { result = "escaped(may)" }
82-
}
83-
84-
/**
85-
* The operand or result may access all memory whose address has escaped, other than data on the
86-
* stack frame of the current function.
54+
* The operand or result access all memory whose address has escaped, other than data on the stack
55+
* frame of the current function.
8756
*/
88-
class NonLocalMayMemoryAccess extends MemoryAccessKind, TNonLocalMayMemoryAccess {
89-
override string toString() { result = "nonlocal(may)" }
57+
class NonLocalMemoryAccess extends MemoryAccessKind, TNonLocalMemoryAccess {
58+
override string toString() { result = "nonlocal" }
9059
}
9160

9261
/**

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

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,16 @@ class Instruction extends Construction::TInstruction {
550550
*/
551551
MemoryAccessKind getResultMemoryAccess() { none() }
552552

553+
/**
554+
* Holds if the memory access performed by this instruction's result will not always write to
555+
* every bit in the memory location. This is most commonly used for memory accesses that may or
556+
* may not actually occur depending on runtime state (for example, the write side effect of an
557+
* output parameter that is not written to on all paths), or for accesses where the memory
558+
* location is a conservative estimate of the memory that might actually be accessed at runtime
559+
* (for example, the global side effects of a function call).
560+
*/
561+
predicate hasResultMayMemoryAccess() { none() }
562+
553563
/**
554564
* Gets the operand that holds the memory address to which this instruction stores its
555565
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
@@ -1206,9 +1216,9 @@ class SideEffectInstruction extends Instruction {
12061216
class CallSideEffectInstruction extends SideEffectInstruction {
12071217
CallSideEffectInstruction() { getOpcode() instanceof Opcode::CallSideEffect }
12081218

1209-
final override MemoryAccessKind getResultMemoryAccess() {
1210-
result instanceof EscapedMayMemoryAccess
1211-
}
1219+
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
1220+
1221+
final override predicate hasResultMayMemoryAccess() { any() }
12121222
}
12131223

12141224
/**
@@ -1306,9 +1316,9 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
13061316
getOpcode() instanceof Opcode::IndirectMayWriteSideEffect
13071317
}
13081318

1309-
final override MemoryAccessKind getResultMemoryAccess() {
1310-
result instanceof IndirectMayMemoryAccess
1311-
}
1319+
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
1320+
1321+
final override predicate hasResultMayMemoryAccess() { any() }
13121322
}
13131323

13141324
/**
@@ -1318,9 +1328,9 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
13181328
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
13191329
BufferMayWriteSideEffectInstruction() { getOpcode() instanceof Opcode::BufferMayWriteSideEffect }
13201330

1321-
final override MemoryAccessKind getResultMemoryAccess() {
1322-
result instanceof BufferMayMemoryAccess
1323-
}
1331+
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
1332+
1333+
final override predicate hasResultMayMemoryAccess() { any() }
13241334
}
13251335

13261336
/**
@@ -1332,9 +1342,9 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
13321342
getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect
13331343
}
13341344

1335-
final override MemoryAccessKind getResultMemoryAccess() {
1336-
result instanceof BufferMayMemoryAccess
1337-
}
1345+
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
1346+
1347+
final override predicate hasResultMayMemoryAccess() { any() }
13381348

13391349
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
13401350
}
@@ -1345,9 +1355,9 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
13451355
class InlineAsmInstruction extends Instruction {
13461356
InlineAsmInstruction() { getOpcode() instanceof Opcode::InlineAsm }
13471357

1348-
final override MemoryAccessKind getResultMemoryAccess() {
1349-
result instanceof EscapedMayMemoryAccess
1350-
}
1358+
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
1359+
1360+
final override predicate hasResultMayMemoryAccess() { any() }
13511361
}
13521362

13531363
/**

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

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,16 @@ class MemoryOperand extends Operand {
194194
*/
195195
MemoryAccessKind getMemoryAccess() { none() }
196196

197+
/**
198+
* Holds if the memory access performed by this operand will not always read from every bit in the
199+
* memory location. This is most commonly used for memory accesses that may or may not actually
200+
* occur depending on runtime state (for example, the write side effect of an output parameter
201+
* that is not written to on all paths), or for accesses where the memory location is a
202+
* conservative estimate of the memory that might actually be accessed at runtime (for example,
203+
* the global side effects of a function call).
204+
*/
205+
predicate hasMayMemoryAccess() { none() }
206+
197207
/**
198208
* Returns the operand that holds the memory address from which the current operand loads its
199209
* value, if any. For example, in `r3 = Load r1, m2`, the result of `getAddressOperand()` for `m2`
@@ -397,13 +407,13 @@ class SideEffectOperand extends TypedOperand {
397407

398408
override MemoryAccessKind getMemoryAccess() {
399409
useInstr instanceof AliasedUseInstruction and
400-
result instanceof NonLocalMayMemoryAccess
410+
result instanceof NonLocalMemoryAccess
401411
or
402412
useInstr instanceof CallSideEffectInstruction and
403-
result instanceof EscapedMayMemoryAccess
413+
result instanceof EscapedMemoryAccess
404414
or
405415
useInstr instanceof CallReadSideEffectInstruction and
406-
result instanceof EscapedMayMemoryAccess
416+
result instanceof EscapedMemoryAccess
407417
or
408418
useInstr instanceof IndirectReadSideEffectInstruction and
409419
result instanceof IndirectMemoryAccess
@@ -418,10 +428,22 @@ class SideEffectOperand extends TypedOperand {
418428
result instanceof BufferMemoryAccess
419429
or
420430
useInstr instanceof IndirectMayWriteSideEffectInstruction and
421-
result instanceof IndirectMayMemoryAccess
431+
result instanceof IndirectMemoryAccess
422432
or
423433
useInstr instanceof BufferMayWriteSideEffectInstruction and
424-
result instanceof BufferMayMemoryAccess
434+
result instanceof BufferMemoryAccess
435+
}
436+
437+
final override predicate hasMayMemoryAccess() {
438+
useInstr instanceof AliasedUseInstruction
439+
or
440+
useInstr instanceof CallSideEffectInstruction
441+
or
442+
useInstr instanceof CallReadSideEffectInstruction
443+
or
444+
useInstr instanceof IndirectMayWriteSideEffectInstruction
445+
or
446+
useInstr instanceof BufferMayWriteSideEffectInstruction
425447
}
426448
}
427449

0 commit comments

Comments
 (0)