Skip to content

Commit 7f69cdf

Browse files
author
Robert Marsh
committed
C++: Dynamic allocations in IR alias analysis
1 parent 05c8610 commit 7f69cdf

File tree

14 files changed

+135
-32
lines changed

14 files changed

+135
-32
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ private newtype TOpcode =
8282
TSizedBufferReadSideEffect() or
8383
TSizedBufferMustWriteSideEffect() or
8484
TSizedBufferMayWriteSideEffect() or
85+
TInitializeDynamicAllocation() or
8586
TChi() or
8687
TInlineAsm() or
8788
TUnreached() or
@@ -695,6 +696,10 @@ module Opcode {
695696
final override string toString() { result = "SizedBufferMayWriteSideEffect" }
696697
}
697698

699+
class InitializeDynamicAllocation extends SideEffectOpcode, EntireAllocationWriteOpcode, TInitializeDynamicAllocation {
700+
final override string toString() { result = "InitializeDynamicAllocation" }
701+
}
702+
698703
class Chi extends Opcode, TChi {
699704
final override string toString() { result = "Chi" }
700705

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,20 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
13401340
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
13411341
}
13421342

1343+
/**
1344+
*
1345+
*/
1346+
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
1347+
InitializeDynamicAllocationInstruction() {
1348+
getOpcode() instanceof Opcode::InitializeDynamicAllocation
1349+
}
1350+
1351+
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
1352+
1353+
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
1354+
1355+
}
1356+
13431357
/**
13441358
* An instruction representing a GNU or MSVC inline assembly statement.
13451359
*/

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ private newtype TAllocation =
77
TVariableAllocation(IRVariable var) or
88
TIndirectParameterAllocation(IRAutomaticUserVariable var) {
99
exists(InitializeIndirectionInstruction instr | instr.getIRVariable() = var)
10+
} or
11+
TDynamicAllocation(CallInstruction call) {
12+
exists(InitializeDynamicAllocationInstruction instr | instr.getPrimaryInstruction() = call)
1013
}
1114

1215
/**
@@ -95,3 +98,31 @@ class IndirectParameterAllocation extends Allocation, TIndirectParameterAllocati
9598

9699
final override predicate alwaysEscapes() { none() }
97100
}
101+
102+
class DynamicAllocation extends Allocation, TDynamicAllocation {
103+
CallInstruction call;
104+
105+
DynamicAllocation() { this = TDynamicAllocation(call) }
106+
107+
final override string toString() {
108+
result = call.toString() + " at " + call.getLocation() // TODO: make this both short and unique
109+
}
110+
111+
final override CallInstruction getABaseInstruction() { result = call }
112+
113+
final override IRFunction getEnclosingIRFunction() { result = call.getEnclosingIRFunction() }
114+
115+
final override Language::Location getLocation() { result = call.getLocation() }
116+
117+
final override string getUniqueId() { result = call.getUniqueId() }
118+
119+
final override IRType getIRType() {
120+
result instanceof IRUnknownType // TODO: look at casts and sizes?
121+
}
122+
123+
final override predicate isReadOnly() { none() }
124+
125+
final override predicate isAlwaysAllocatedOnStack() { none() }
126+
127+
final override predicate alwaysEscapes() { none() }
128+
}

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,12 @@ private newtype TMemoryLocation =
6868
) and
6969
languageType = type.getCanonicalLanguageType()
7070
} or
71-
TEntireAllocationMemoryLocation(IndirectParameterAllocation var, boolean isMayAccess) {
72-
isMayAccess = false or isMayAccess = true
71+
TEntireAllocationMemoryLocation(Allocation var, boolean isMayAccess) {
72+
(
73+
var instanceof IndirectParameterAllocation or
74+
var instanceof DynamicAllocation
75+
) and
76+
(isMayAccess = false or isMayAccess = true)
7377
} or
7478
TUnknownMemoryLocation(IRFunction irFunc, boolean isMayAccess) {
7579
isMayAccess = false or isMayAccess = true

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,20 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
13401340
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
13411341
}
13421342

1343+
/**
1344+
*
1345+
*/
1346+
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
1347+
InitializeDynamicAllocationInstruction() {
1348+
getOpcode() instanceof Opcode::InitializeDynamicAllocation
1349+
}
1350+
1351+
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
1352+
1353+
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
1354+
1355+
}
1356+
13431357
/**
13441358
* An instruction representing a GNU or MSVC inline assembly statement.
13451359
*/

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -341,16 +341,31 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects {
341341
)
342342
}
343343

344-
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { none() }
345-
346-
override Instruction getFirstInstruction() { result = getChild(0).getFirstInstruction() }
344+
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
345+
expr.getTarget() instanceof AllocationFunction and
346+
opcode instanceof Opcode::InitializeDynamicAllocation and
347+
tag = OnlyInstructionTag() and
348+
type = getUnknownType() // TODO: precise type
349+
}
347350

348-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
351+
override Instruction getFirstInstruction() {
352+
if expr.getTarget() instanceof AllocationFunction
353+
then result = getInstruction(OnlyInstructionTag())
354+
else result = getChild(0).getFirstInstruction()
355+
}
349356

350-
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() }
357+
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
358+
tag = OnlyInstructionTag() and
359+
kind = gotoEdge() and
360+
if exists(getChild(0))
361+
then result = getChild(0).getFirstInstruction()
362+
else result = getParent().getChildSuccessor(this)
363+
}
351364

352-
override CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
353-
none()
365+
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
366+
tag = OnlyInstructionTag() and
367+
operandTag = addressOperand() and
368+
result = getPrimaryInstructionForSideEffect(OnlyInstructionTag())
354369
}
355370

356371
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,9 @@ newtype TTranslatedElement =
411411
TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or
412412
// The side effects of a `Call`
413413
TTranslatedSideEffects(Call expr) {
414-
exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or expr instanceof ConstructorCall
414+
exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or
415+
expr instanceof ConstructorCall or
416+
expr.getTarget() instanceof AllocationFunction
415417
} or // A precise side effect of an argument to a `Call`
416418
TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) {
417419
(

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,20 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
13401340
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
13411341
}
13421342

1343+
/**
1344+
*
1345+
*/
1346+
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
1347+
InitializeDynamicAllocationInstruction() {
1348+
getOpcode() instanceof Opcode::InitializeDynamicAllocation
1349+
}
1350+
1351+
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
1352+
1353+
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
1354+
1355+
}
1356+
13431357
/**
13441358
* An instruction representing a GNU or MSVC inline assembly statement.
13451359
*/

cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@
88
| test.cpp:68:28:68:33 | call to getenv | test.cpp:69:10:69:13 | copy | AST only |
99
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:12:70:15 | copy | AST only |
1010
| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy | AST only |
11-
| test.cpp:83:28:83:33 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only |
1211
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only |
1312
| test.cpp:83:28:83:33 | call to getenv | test.cpp:85:8:85:11 | copy | AST only |
1413
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:9:86:12 | copy | AST only |
15-
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:6:88:27 | ! ... | AST only |
16-
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:12 | call to strcmp | AST only |
17-
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... | AST only |
18-
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... | AST only |
19-
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy | AST only |

cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,15 @@
4040
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:15:75:18 | call to atoi | |
4141
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:25 | call to getenv | |
4242
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:45 | (const char *)... | |
43+
| test.cpp:83:28:83:33 | call to getenv | test.cpp:8:24:8:25 | s1 | |
4344
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:36:11:37 | s2 | |
4445
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:17:83:24 | userName | |
4546
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:33 | call to getenv | |
4647
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:46 | (const char *)... | |
4748
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:2:86:7 | call to strcpy | |
4849
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:15:86:22 | userName | |
50+
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:6:88:27 | ! ... | |
51+
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:12 | call to strcmp | |
52+
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... | |
53+
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... | |
54+
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy | |

0 commit comments

Comments
 (0)