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

Skip to content

Commit 7e30ce0

Browse files
author
Robert Marsh
committed
C++: add phi node support to escape analysis
1 parent 97c11a5 commit 7e30ce0

5 files changed

Lines changed: 94 additions & 13 deletions

File tree

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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ private predicate operandEscapesDomain(Operand operand) {
7272
not operandIsPropagated(operand, _) and
7373
not isArgumentForParameter(_, operand, _) and
7474
not isOnlyEscapesViaReturnArgument(operand) and
75-
not operand.getUseInstruction() instanceof ReturnValueInstruction
75+
not operand.getUseInstruction() instanceof ReturnValueInstruction and
76+
not operand instanceof PhiOperand
7677
}
7778

7879
/**
@@ -161,7 +162,7 @@ private predicate operandEscapesNonReturn(Operand operand) {
161162
exists(CallInstruction ci, Instruction init |
162163
isArgumentForParameter(ci, operand, init) and
163164
(
164-
resultReturned(init, _) and
165+
resultMayReachReturn(init) and
165166
resultEscapesNonReturn(ci)
166167
or
167168
resultEscapesNonReturn(init)
@@ -170,9 +171,34 @@ private predicate operandEscapesNonReturn(Operand operand) {
170171
or
171172
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUseInstruction())
172173
or
174+
operand instanceof PhiOperand and
175+
resultEscapesNonReturn(operand.getUseInstruction())
176+
or
173177
operandEscapesDomain(operand)
174178
}
175179

180+
181+
private predicate operandMayReachReturn(Operand operand) {
182+
// The address is propagated to the result of the instruction, and that result itself is returned
183+
operandIsPropagated(operand, _) and
184+
resultMayReachReturn(operand.getUseInstruction())
185+
or
186+
// The operand is used in a function call which returns it, and the return value is then returned
187+
exists(CallInstruction ci, Instruction init |
188+
isArgumentForParameter(ci, operand, init) and
189+
resultMayReachReturn(init) and
190+
resultMayReachReturn(ci)
191+
)
192+
or
193+
// The address is returned
194+
operand.getUseInstruction() instanceof ReturnValueInstruction
195+
or
196+
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUseInstruction())
197+
or
198+
operand instanceof PhiOperand and
199+
resultMayReachReturn(operand.getUseInstruction())
200+
}
201+
176202
private predicate operandReturned(Operand operand, IntValue bitOffset) {
177203
// The address is propagated to the result of the instruction, and that result itself is returned
178204
exists(IntValue bitOffset1, IntValue bitOffset2 |
@@ -239,6 +265,10 @@ private predicate resultReturned(Instruction instr, IntValue bitOffset) {
239265
operandReturned(instr.getAUse(), bitOffset)
240266
}
241267

268+
private predicate resultMayReachReturn(Instruction instr) {
269+
operandMayReachReturn(instr.getAUse())
270+
}
271+
242272
/**
243273
* Holds if any address held in the result of instruction `instr` escapes
244274
* outside the domain of the analysis.

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ private predicate operandEscapesDomain(Operand operand) {
7272
not operandIsPropagated(operand, _) and
7373
not isArgumentForParameter(_, operand, _) and
7474
not isOnlyEscapesViaReturnArgument(operand) and
75-
not operand.getUseInstruction() instanceof ReturnValueInstruction
75+
not operand.getUseInstruction() instanceof ReturnValueInstruction and
76+
not operand instanceof PhiOperand
7677
}
7778

7879
/**
@@ -161,7 +162,7 @@ private predicate operandEscapesNonReturn(Operand operand) {
161162
exists(CallInstruction ci, Instruction init |
162163
isArgumentForParameter(ci, operand, init) and
163164
(
164-
resultReturned(init, _) and
165+
resultMayReachReturn(init) and
165166
resultEscapesNonReturn(ci)
166167
or
167168
resultEscapesNonReturn(init)
@@ -170,9 +171,34 @@ private predicate operandEscapesNonReturn(Operand operand) {
170171
or
171172
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUseInstruction())
172173
or
174+
operand instanceof PhiOperand and
175+
resultEscapesNonReturn(operand.getUseInstruction())
176+
or
173177
operandEscapesDomain(operand)
174178
}
175179

180+
181+
private predicate operandMayReachReturn(Operand operand) {
182+
// The address is propagated to the result of the instruction, and that result itself is returned
183+
operandIsPropagated(operand, _) and
184+
resultMayReachReturn(operand.getUseInstruction())
185+
or
186+
// The operand is used in a function call which returns it, and the return value is then returned
187+
exists(CallInstruction ci, Instruction init |
188+
isArgumentForParameter(ci, operand, init) and
189+
resultMayReachReturn(init) and
190+
resultMayReachReturn(ci)
191+
)
192+
or
193+
// The address is returned
194+
operand.getUseInstruction() instanceof ReturnValueInstruction
195+
or
196+
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUseInstruction())
197+
or
198+
operand instanceof PhiOperand and
199+
resultMayReachReturn(operand.getUseInstruction())
200+
}
201+
176202
private predicate operandReturned(Operand operand, IntValue bitOffset) {
177203
// The address is propagated to the result of the instruction, and that result itself is returned
178204
exists(IntValue bitOffset1, IntValue bitOffset2 |
@@ -239,6 +265,10 @@ private predicate resultReturned(Instruction instr, IntValue bitOffset) {
239265
operandReturned(instr.getAUse(), bitOffset)
240266
}
241267

268+
private predicate resultMayReachReturn(Instruction instr) {
269+
operandMayReachReturn(instr.getAUse())
270+
}
271+
242272
/**
243273
* Holds if any address held in the result of instruction `instr` escapes
244274
* outside the domain of the analysis.

cpp/ql/test/library-tests/ir/escape/escape.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,10 @@ void Escape()
193193
int passByRef3;
194194
CallByReferenceParamEscape(ReturnReference(passByRef3));
195195

196-
int passByPtr4;
197-
int passByPtr5;
196+
int no_ssa_passByPtr4;
197+
int no_ssa_passByPtr5;
198198
bool no_b2 = false;
199-
MaybeReturn(&passByPtr4, &passByPtr5, no_b2);
199+
MaybeReturn(&no_ssa_passByPtr4, &no_ssa_passByPtr5, no_b2);
200200

201201
int passByRef6;
202202
EscapeAndReturn(passByRef6);
@@ -239,5 +239,15 @@ void Escape()
239239

240240
OverrideNone on2;
241241
CEscapes(on2.Overridden());
242+
243+
int condEscape1, condEscape2;
244+
245+
int *no_condTemp;
246+
if(GetPointer()) {
247+
no_condTemp = &condEscape1;
248+
} else {
249+
no_condTemp = &condEscape2;
250+
}
251+
CallByPointer(no_condTemp);
242252
}
243253

cpp/ql/test/library-tests/ir/escape/points_to.expected

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@
145145
| escape.cpp:193:9:193:18 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 |
146146
| escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 |
147147
| escape.cpp:194:48:194:57 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 |
148-
| escape.cpp:196:9:196:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 |
149-
| escape.cpp:197:9:197:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 |
148+
| escape.cpp:196:9:196:25 | VariableAddress[no_ssa_passByPtr4] | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 |
149+
| escape.cpp:197:9:197:25 | VariableAddress[no_ssa_passByPtr5] | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 |
150150
| escape.cpp:198:10:198:14 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 |
151-
| escape.cpp:199:18:199:27 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 |
152-
| escape.cpp:199:31:199:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 |
153-
| escape.cpp:199:43:199:47 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 |
151+
| escape.cpp:199:18:199:34 | VariableAddress[no_ssa_passByPtr4] | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 |
152+
| escape.cpp:199:38:199:54 | VariableAddress[no_ssa_passByPtr5] | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 |
153+
| escape.cpp:199:57:199:61 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 |
154154
| escape.cpp:201:9:201:18 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 |
155155
| escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 |
156156
| escape.cpp:202:21:202:30 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 |
@@ -180,3 +180,13 @@
180180
| escape.cpp:238:5:238:7 | VariableAddress[on1] | on1+0:0 | on1+0:0 |
181181
| escape.cpp:240:18:240:20 | VariableAddress[on2] | on2+0:0 | on2+0:0 |
182182
| escape.cpp:241:14:241:16 | VariableAddress[on2] | on2+0:0 | on2+0:0 |
183+
| escape.cpp:243:9:243:19 | VariableAddress[condEscape1] | condEscape1+0:0 | condEscape1+0:0 |
184+
| escape.cpp:243:22:243:32 | VariableAddress[condEscape2] | condEscape2+0:0 | condEscape2+0:0 |
185+
| escape.cpp:245:10:245:20 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 |
186+
| escape.cpp:247:2:247:12 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 |
187+
| escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 |
188+
| escape.cpp:247:17:247:27 | VariableAddress[condEscape1] | condEscape1+0:0 | condEscape1+0:0 |
189+
| escape.cpp:249:9:249:19 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 |
190+
| escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 |
191+
| escape.cpp:249:24:249:34 | VariableAddress[condEscape2] | condEscape2+0:0 | condEscape2+0:0 |
192+
| escape.cpp:251:19:251:29 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 |

cpp/ql/test/library-tests/ir/escape/points_to.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ where
2929
not UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), _) and
3030
unPointsTo = "none"
3131
)
32-
)
32+
) and
33+
rawPointsTo != unPointsTo
3334
select rawInstr.getLocation().toString(), rawInstr.getOperationString(), rawPointsTo, unPointsTo

0 commit comments

Comments
 (0)