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

Skip to content

Commit 1fb36ff

Browse files
C++: Add conservative side effects for function calls
1 parent f9ed399 commit 1fb36ff

17 files changed

Lines changed: 2689 additions & 1785 deletions

File tree

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

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import cpp
22

3-
newtype TMemoryAccessKind =
3+
private newtype TMemoryAccessKind =
44
TIndirectMemoryAccess() or
5+
TIndirectMayMemoryAccess() or
6+
TBufferMemoryAccess() or
7+
TBufferMayMemoryAccess() or
58
TEscapedMemoryAccess() or
69
TPhiMemoryAccess() or
710
TUnmodeledMemoryAccess()
@@ -15,15 +18,47 @@ class MemoryAccessKind extends TMemoryAccessKind {
1518
}
1619

1720
/**
18-
* The operand or result accesses memory at the address specified by the
19-
* `AddressOperand` on the same instruction.
21+
* The operand or result accesses memory at the address specified by the `AddressOperand` on the
22+
* same instruction.
2023
*/
2124
class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
2225
override string toString() {
2326
result = "indirect"
2427
}
2528
}
2629

30+
/**
31+
* The operand or result may access some, all, or none of the memory at the address specified by the
32+
* `AddressOperand` on the same instruction.
33+
*/
34+
class IndirectMayMemoryAccess extends MemoryAccessKind, TIndirectMayMemoryAccess {
35+
override string toString() {
36+
result = "indirect(may)"
37+
}
38+
}
39+
40+
/**
41+
* The operand or result accesses memory starting at the address specified by the `AddressOperand`
42+
* on the same instruction, accessing a number of consecutive elements given by the
43+
* `BufferSizeOperand`.
44+
*/
45+
class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
46+
override string toString() {
47+
result = "buffer"
48+
}
49+
}
50+
51+
/**
52+
* The operand or result may access some, all, or none of the memory starting at the address
53+
* specified by the `AddressOperand` on the same instruction, accessing a number of consecutive
54+
* elements given by the `BufferSizeOperand`.
55+
*/
56+
class BufferMayMemoryAccess extends MemoryAccessKind, TBufferMayMemoryAccess {
57+
override string toString() {
58+
result = "buffer(may)"
59+
}
60+
}
61+
2762
/**
2863
* The operand or result accesses all memory whose address has escaped.
2964
*/

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,15 @@ private newtype TOpcode =
5858
TVarArgsStart() or
5959
TVarArgsEnd() or
6060
TVarArg() or
61-
TVarArgCopy()
61+
TVarArgCopy() or
62+
TCallSideEffect() or
63+
TCallReadSideEffect() or
64+
TIndirectReadSideEffect() or
65+
TIndirectWriteSideEffect() or
66+
TIndirectMayWriteSideEffect() or
67+
TBufferReadSideEffect() or
68+
TBufferWriteSideEffect() or
69+
TBufferMayWriteSideEffect()
6270

6371
class Opcode extends TOpcode {
6472
string toString() {
@@ -92,6 +100,29 @@ abstract class OpcodeWithCondition extends Opcode {}
92100

93101
abstract class BuiltInOpcode extends Opcode {}
94102

103+
abstract class SideEffectOpcode extends Opcode {}
104+
105+
/**
106+
* An opcode that reads from a set of memory locations as a side effect.
107+
*/
108+
abstract class ReadSideEffectOpcode extends SideEffectOpcode {}
109+
110+
/**
111+
* An opcode that writes to a set of memory locations as a side effect.
112+
*/
113+
abstract class WriteSideEffectOpcode extends SideEffectOpcode {}
114+
115+
/**
116+
* An opcode that may overwrite some, all, or none of an existing set of memory locations. Modeled
117+
* as a read of the original contents, plus a "may" write of the new contents.
118+
*/
119+
abstract class MayWriteSideEffectOpcode extends SideEffectOpcode {}
120+
121+
/**
122+
* An opcode that accesses a buffer via an `AddressOperand` and a `BufferSizeOperand`.
123+
*/
124+
abstract class BufferAccessOpcode extends MemoryAccessOpcode {}
125+
95126
module Opcode {
96127
class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } }
97128
class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } }
@@ -153,4 +184,12 @@ module Opcode {
153184
class VarArgsEnd extends BuiltInOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } }
154185
class VarArg extends BuiltInOpcode, TVarArg { override final string toString() { result = "VarArg" } }
155186
class VarArgCopy extends BuiltInOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } }
187+
class CallSideEffect extends MayWriteSideEffectOpcode, TCallSideEffect { override final string toString() { result = "CallSideEffect" } }
188+
class CallReadSideEffect extends ReadSideEffectOpcode, TCallReadSideEffect { override final string toString() { result = "CallReadSideEffect" } }
189+
class IndirectReadSideEffect extends ReadSideEffectOpcode, MemoryAccessOpcode, TIndirectReadSideEffect { override final string toString() { result = "IndirectReadSideEffect" } }
190+
class IndirectWriteSideEffect extends WriteSideEffectOpcode, MemoryAccessOpcode, TIndirectWriteSideEffect { override final string toString() { result = "IndirectWriteSideEffect" } }
191+
class IndirectMayWriteSideEffect extends MayWriteSideEffectOpcode, MemoryAccessOpcode, TIndirectMayWriteSideEffect { override final string toString() { result = "IndirectMayWriteSideEffect" } }
192+
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect { override final string toString() { result = "BufferReadSideEffect" } }
193+
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode, TBufferWriteSideEffect { override final string toString() { result = "BufferWriteSideEffect" } }
194+
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode, TBufferMayWriteSideEffect { override final string toString() { result = "BufferMayWriteSideEffect" } }
156195
}

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

Lines changed: 128 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,16 @@ module InstructionSanity {
3333
) or
3434
opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or
3535
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or
36+
opcode instanceof BufferAccessOpcode and tag instanceof BufferSizeOperand or
3637
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or
3738
opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or
3839
opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or
3940
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or
40-
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
41+
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag or
42+
(
43+
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
44+
tag instanceof SideEffectOperandTag
45+
)
4146
)
4247
)
4348
}
@@ -162,9 +167,9 @@ class Instruction extends Construction::TInstruction {
162167
*/
163168
final string getOperationString() {
164169
if exists(getImmediateString()) then
165-
result = opcode.toString() + "[" + getImmediateString() + "]"
170+
result = getOperationPrefix() + opcode.toString() + "[" + getImmediateString() + "]"
166171
else
167-
result = opcode.toString()
172+
result = getOperationPrefix() + opcode.toString()
168173
}
169174

170175
/**
@@ -174,6 +179,13 @@ class Instruction extends Construction::TInstruction {
174179
none()
175180
}
176181

182+
private string getOperationPrefix() {
183+
if this instanceof SideEffectInstruction then
184+
result = "^"
185+
else
186+
result = ""
187+
}
188+
177189
private string getResultPrefix() {
178190
if resultType instanceof VoidType then
179191
result = "v"
@@ -1084,6 +1096,9 @@ class SwitchInstruction extends Instruction {
10841096
}
10851097
}
10861098

1099+
/**
1100+
* An instruction that calls a function.
1101+
*/
10871102
class CallInstruction extends Instruction {
10881103
CallInstruction() {
10891104
opcode instanceof Opcode::Call
@@ -1094,6 +1109,116 @@ class CallInstruction extends Instruction {
10941109
}
10951110
}
10961111

1112+
/**
1113+
* An instruction representing a side effect of a function call.
1114+
*/
1115+
class SideEffectInstruction extends Instruction {
1116+
SideEffectInstruction() {
1117+
opcode instanceof SideEffectOpcode
1118+
}
1119+
1120+
final Instruction getPrimaryInstruction() {
1121+
result = Construction::getPrimaryInstructionForSideEffect(this)
1122+
}
1123+
}
1124+
1125+
/**
1126+
* An instruction representing the side effect of a function call on any memory that might be
1127+
* accessed by that call.
1128+
*/
1129+
class CallSideEffectInstruction extends SideEffectInstruction {
1130+
CallSideEffectInstruction() {
1131+
opcode instanceof Opcode::CallSideEffect
1132+
}
1133+
1134+
override final MemoryAccessKind getResultMemoryAccess() {
1135+
result instanceof EscapedMemoryAccess
1136+
}
1137+
}
1138+
1139+
/**
1140+
* An instruction representing the side effect of a function call on any memory that might be read
1141+
* by that call.
1142+
*/
1143+
class CallReadSideEffectInstruction extends SideEffectInstruction {
1144+
CallReadSideEffectInstruction() {
1145+
opcode instanceof Opcode::CallReadSideEffect
1146+
}
1147+
}
1148+
1149+
/**
1150+
* An instruction representing the read of an indirect parameter within a function call.
1151+
*/
1152+
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
1153+
IndirectReadSideEffectInstruction() {
1154+
opcode instanceof Opcode::IndirectReadSideEffect
1155+
}
1156+
}
1157+
1158+
/**
1159+
* An instruction representing the read of an indirect buffer parameter within a function call.
1160+
*/
1161+
class BufferReadSideEffectInstruction extends SideEffectInstruction {
1162+
BufferReadSideEffectInstruction() {
1163+
opcode instanceof Opcode::BufferReadSideEffect
1164+
}
1165+
}
1166+
1167+
/**
1168+
* An instruction representing the write of an indirect parameter within a function call.
1169+
*/
1170+
class IndirectWriteSideEffectInstruction extends SideEffectInstruction {
1171+
IndirectWriteSideEffectInstruction() {
1172+
opcode instanceof Opcode::IndirectWriteSideEffect
1173+
}
1174+
1175+
override final MemoryAccessKind getResultMemoryAccess() {
1176+
result instanceof IndirectMemoryAccess
1177+
}
1178+
}
1179+
1180+
/**
1181+
* An instruction representing the write of an indirect buffer parameter within a function call. The
1182+
* entire buffer is overwritten.
1183+
*/
1184+
class BufferWriteSideEffectInstruction extends SideEffectInstruction {
1185+
BufferWriteSideEffectInstruction() {
1186+
opcode instanceof Opcode::BufferWriteSideEffect
1187+
}
1188+
1189+
override final MemoryAccessKind getResultMemoryAccess() {
1190+
result instanceof BufferMemoryAccess
1191+
}
1192+
}
1193+
1194+
/**
1195+
* An instruction representing the potential write of an indirect parameter within a function call.
1196+
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
1197+
* written.
1198+
*/
1199+
class IndirectMayWriteSideEffectInstruction extends SideEffectInstruction {
1200+
IndirectMayWriteSideEffectInstruction() {
1201+
opcode instanceof Opcode::IndirectMayWriteSideEffect
1202+
}
1203+
1204+
override final MemoryAccessKind getResultMemoryAccess() {
1205+
result instanceof IndirectMayMemoryAccess
1206+
}
1207+
}
1208+
1209+
/**
1210+
* An instruction representing the write of an indirect buffer parameter within a function call.
1211+
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
1212+
*/
1213+
class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
1214+
BufferMayWriteSideEffectInstruction() {
1215+
opcode instanceof Opcode::BufferMayWriteSideEffect
1216+
}
1217+
override final MemoryAccessKind getResultMemoryAccess() {
1218+
result instanceof BufferMayMemoryAccess
1219+
}
1220+
}
1221+
10971222
/**
10981223
* An instruction that throws an exception.
10991224
*/

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,38 @@ class PositionalArgumentOperand extends ArgumentOperand {
306306
}
307307
}
308308

309+
class SideEffectOperand extends NonPhiOperand {
310+
SideEffectOperand() {
311+
this = TNonPhiOperand(_, sideEffectOperand(), _)
312+
}
313+
314+
override MemoryAccessKind getMemoryAccess() {
315+
instr instanceof CallSideEffectInstruction and
316+
result instanceof EscapedMemoryAccess
317+
or
318+
instr instanceof CallReadSideEffectInstruction and
319+
result instanceof EscapedMemoryAccess
320+
or
321+
instr instanceof IndirectReadSideEffectInstruction and
322+
result instanceof IndirectMemoryAccess
323+
or
324+
instr instanceof BufferReadSideEffectInstruction and
325+
result instanceof BufferMemoryAccess
326+
or
327+
instr instanceof IndirectWriteSideEffectInstruction and
328+
result instanceof IndirectMemoryAccess
329+
or
330+
instr instanceof BufferWriteSideEffectInstruction and
331+
result instanceof BufferMemoryAccess
332+
or
333+
instr instanceof IndirectMayWriteSideEffectInstruction and
334+
result instanceof IndirectMayMemoryAccess
335+
or
336+
instr instanceof BufferMayWriteSideEffectInstruction and
337+
result instanceof BufferMayMemoryAccess
338+
}
339+
}
340+
309341
/**
310342
* An operand of a `PhiInstruction`.
311343
*/
@@ -350,6 +382,7 @@ class PhiOperand extends Operand, TPhiOperand {
350382
}
351383
}
352384

385+
353386
/**
354387
* An operand that reads a value from memory.
355388
*/

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,13 @@ cached private module Cached {
227227
)
228228
}
229229

230+
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
231+
exists(OldIR::SideEffectInstruction oldInstruction |
232+
oldInstruction = getOldInstruction(instruction) and
233+
result = getNewInstruction(oldInstruction.getPrimaryInstruction())
234+
)
235+
}
236+
230237
private predicate ssa_variableUpdate(Alias::VirtualVariable vvar,
231238
OldIR::Instruction instr, OldIR::IRBlock block, int index) {
232239
block.getInstruction(index) = instr and

0 commit comments

Comments
 (0)