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

Skip to content

Commit cd5f3b8

Browse files
committed
C++: Make sure there's a Instruction for each Expr
This change ensures that all `Expr`s (except parentheses) have a `TranslatedExpr` with a `getResult` that's one of its own instructions, not an instruction from one of its operands. This means that when we translate back and forth between `Expr` and `Instruction`, like in `DataFlow::exprNode`, we will not conflate `e` with `&e` or `... = e`.
1 parent 825a3d2 commit cd5f3b8

7 files changed

Lines changed: 2075 additions & 1573 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ newtype TInstructionTag =
4444
ConditionValueResultLoadTag() or
4545
BoolConversionConstantTag() or
4646
BoolConversionCompareTag() or
47+
ResultCopyTag() or
4748
LoadTag() or // Implicit load due to lvalue-to-rvalue conversion
4849
CatchTag() or
4950
ThrowTag() or

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ private import InstructionTag
88
private import TranslatedCondition
99
private import TranslatedFunction
1010
private import TranslatedStmt
11+
private import TranslatedExpr
1112
private import IRConstruction
1213

1314
/**
@@ -235,6 +236,15 @@ newtype TTranslatedElement =
235236
expr.hasLValueToRValueConversion() and
236237
not ignoreLoad(expr)
237238
} or
239+
TTranslatedResultCopy(Expr expr) {
240+
not ignoreExpr(expr) and
241+
exprNeedsCopyIfNotLoaded(expr) and
242+
// Doesn't have a TTranslatedLoad
243+
not (
244+
expr.hasLValueToRValueConversion() and
245+
not ignoreLoad(expr)
246+
)
247+
} or
238248
// An expression most naturally translated as control flow.
239249
TTranslatedNativeCondition(Expr expr) {
240250
not ignoreExpr(expr) and

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

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,14 @@ abstract class TranslatedCoreExpr extends TranslatedExpr {
8585
final override predicate producesExprResult() {
8686
// If there's no load, then this is the only TranslatedExpr for this
8787
// expression.
88-
not expr.hasLValueToRValueConversion()
89-
or
90-
// If we're supposed to ignore the load on this expression, then this
91-
// is the only TranslatedExpr.
92-
ignoreLoad(expr)
88+
not hasLoad() and
89+
// If there's a result copy, then this expression's result is the copy.
90+
not exprNeedsCopyIfNotLoaded(expr)
91+
}
92+
93+
private predicate hasLoad() {
94+
expr.hasLValueToRValueConversion() and
95+
not ignoreLoad(expr)
9396
}
9497

9598
/**
@@ -106,7 +109,7 @@ abstract class TranslatedCoreExpr extends TranslatedExpr {
106109
or
107110
// If this TranslatedExpr doesn't produce the result, then it must represent
108111
// a glvalue that is then loaded by a TranslatedLoad.
109-
not producesExprResult()
112+
hasLoad()
110113
then result = true
111114
else result = false
112115
}
@@ -302,6 +305,51 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad {
302305
private TranslatedCoreExpr getOperand() { result.getExpr() = expr }
303306
}
304307

308+
/**
309+
* IR translation of an implicit lvalue-to-rvalue conversion on the result of
310+
* an expression.
311+
*/
312+
class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy {
313+
TranslatedResultCopy() { this = TTranslatedResultCopy(expr) }
314+
315+
override string toString() { result = "Result of " + expr.toString() }
316+
317+
override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() }
318+
319+
override TranslatedElement getChild(int id) { id = 0 and result = getOperand() }
320+
321+
override predicate hasInstruction(
322+
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
323+
) {
324+
tag = ResultCopyTag() and
325+
opcode instanceof Opcode::CopyValue and
326+
resultType = getOperand().getResultType() and
327+
isGLValue = getOperand().isResultGLValue()
328+
}
329+
330+
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
331+
tag = ResultCopyTag() and
332+
result = getParent().getChildSuccessor(this) and
333+
kind instanceof GotoEdge
334+
}
335+
336+
override Instruction getChildSuccessor(TranslatedElement child) {
337+
child = getOperand() and result = getInstruction(ResultCopyTag())
338+
}
339+
340+
override Instruction getResult() { result = getInstruction(ResultCopyTag()) }
341+
342+
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
343+
tag = ResultCopyTag() and
344+
operandTag instanceof UnaryOperandTag and
345+
result = getOperand().getResult()
346+
}
347+
348+
final override predicate producesExprResult() { any() }
349+
350+
private TranslatedCoreExpr getOperand() { result.getExpr() = expr }
351+
}
352+
305353
class TranslatedCommaExpr extends TranslatedNonConstantExpr {
306354
override CommaExpr expr;
307355

@@ -2485,3 +2533,37 @@ class TranslatedErrorExpr extends TranslatedSingleInstructionExpr {
24852533

24862534
final override Opcode getOpcode() { result instanceof Opcode::Error }
24872535
}
2536+
2537+
/**
2538+
* Holds if the translation of `expr` will not directly generate any
2539+
* `Instruction` for use as result. For such instructions we can synthesize a
2540+
* `CopyValue` instruction to ensure that there is a 1-to-1 mapping between
2541+
* expressions and result-bearing instructions.
2542+
*/
2543+
// This should ideally be a dispatch predicate on TranslatedNonConstantExpr,
2544+
// but it doesn't look monotonic to QL.
2545+
predicate exprNeedsCopyIfNotLoaded(Expr expr) {
2546+
expr instanceof AssignExpr
2547+
or
2548+
expr instanceof AssignOperation and
2549+
not expr.isPRValueCategory() // is C++
2550+
or
2551+
expr instanceof PrefixCrementOperation and
2552+
not expr.isPRValueCategory() // is C++
2553+
or
2554+
expr instanceof PointerDereferenceExpr
2555+
or
2556+
expr instanceof AddressOfExpr
2557+
or
2558+
expr instanceof BuiltInOperationBuiltInAddressOf
2559+
// No case for ParenthesisExpr to avoid getting too many instructions
2560+
or
2561+
expr instanceof ReferenceDereferenceExpr
2562+
or
2563+
expr instanceof ReferenceToExpr
2564+
or
2565+
expr instanceof CommaExpr
2566+
or
2567+
expr instanceof ConditionDeclExpr
2568+
// TODO: simplify TranslatedStmtExpr too
2569+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,105 @@
1+
| escape.cpp:108:5:108:11 | CopyValue | no_+0:0 | no_+0:0 |
2+
| escape.cpp:109:5:109:13 | CopyValue | no_+0:0 | no_+0:0 |
3+
| escape.cpp:110:5:110:19 | CopyValue | no_result+0:0 | no_result+0:0 |
4+
| escape.cpp:111:5:111:21 | CopyValue | no_result+0:0 | no_result+0:0 |
5+
| escape.cpp:111:18:111:21 | CopyValue | no_+0:0 | no_+0:0 |
6+
| escape.cpp:114:5:114:8 | CopyValue | no_+0:0 | no_+0:0 |
7+
| escape.cpp:115:5:115:29 | CopyValue | no_result+0:0 | no_result+0:0 |
18
| escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 |
9+
| escape.cpp:115:20:115:23 | CopyValue | no_+0:0 | no_+0:0 |
10+
| escape.cpp:116:5:116:29 | CopyValue | no_result+0:0 | no_result+0:0 |
211
| escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 |
12+
| escape.cpp:116:20:116:23 | CopyValue | no_+0:0 | no_+0:0 |
13+
| escape.cpp:117:5:117:27 | CopyValue | no_result+0:0 | no_result+0:0 |
314
| escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 |
15+
| escape.cpp:117:23:117:26 | CopyValue | no_+0:0 | no_+0:0 |
16+
| escape.cpp:118:9:118:12 | CopyValue | no_+0:0 | no_+0:0 |
17+
| escape.cpp:120:12:120:15 | CopyValue | no_+0:0 | no_+0:0 |
18+
| escape.cpp:123:14:123:17 | CopyValue | no_+0:0 | no_+0:0 |
19+
| escape.cpp:124:9:124:12 | CopyValue | no_+0:0 | no_+0:0 |
20+
| escape.cpp:124:15:124:18 | CopyValue | no_+0:0 | no_+0:0 |
21+
| escape.cpp:124:21:124:24 | CopyValue | no_+0:0 | no_+0:0 |
22+
| escape.cpp:127:9:127:12 | CopyValue | no_+0:0 | no_+0:0 |
23+
| escape.cpp:129:12:129:15 | CopyValue | no_+0:0 | no_+0:0 |
424
| escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 |
525
| escape.cpp:134:11:134:18 | Convert | no_Array+0:0 | no_Array+0:0 |
626
| escape.cpp:135:5:135:12 | Convert | no_Array+0:0 | no_Array+0:0 |
727
| escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
828
| escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
929
| escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 |
30+
| escape.cpp:137:5:137:27 | CopyValue | no_result+0:0 | no_result+0:0 |
1031
| escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 |
1132
| escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
33+
| escape.cpp:138:5:138:27 | CopyValue | no_result+0:0 | no_result+0:0 |
1234
| escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
1335
| escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 |
1436
| escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 |
1537
| escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
1638
| escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
1739
| escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 |
40+
| escape.cpp:142:5:142:21 | CopyValue | no_Point+4:0 | no_Point+4:0 |
1841
| escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
42+
| escape.cpp:143:19:143:27 | CopyValue | no_Point+0:0 | no_Point+0:0 |
1943
| escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
44+
| escape.cpp:144:5:144:25 | CopyValue | no_Point+4:0 | no_Point+4:0 |
45+
| escape.cpp:144:6:144:14 | CopyValue | no_Point+0:0 | no_Point+0:0 |
2046
| escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
47+
| escape.cpp:145:20:145:30 | CopyValue | no_Point+8:0 | no_Point+8:0 |
2148
| escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
49+
| escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 |
50+
| escape.cpp:146:5:146:25 | CopyValue | no_Point+8:0 | no_Point+8:0 |
51+
| escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 |
2252
| escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
2353
| escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
2454
| escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
55+
| escape.cpp:149:5:149:20 | CopyValue | no_Derived+0:0 | no_Derived+0:0 |
2556
| escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
2657
| escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
2758
| escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
2859
| escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
2960
| escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
61+
| escape.cpp:151:5:151:21 | CopyValue | no_Derived+16:0 | no_Derived+16:0 |
3062
| escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
3163
| escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
3264
| escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
65+
| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |
3366
| escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |
67+
| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 |
3468
| escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 |
3569
| escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 |
70+
| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
3671
| escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
3772
| escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
73+
| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 |
3874
| escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 |
75+
| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0:0 | passByPtr+0:0 |
76+
| escape.cpp:170:21:170:29 | CopyValue | passByRef+0:0 | passByRef+0:0 |
77+
| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 |
78+
| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 |
79+
| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 |
80+
| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 |
81+
| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0:0 | passByPtr2+0:0 |
82+
| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0:0 | passByRef2+0:0 |
3983
| escape.cpp:191:30:191:42 | Call | none | passByPtr3+0:0 |
84+
| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0:0 | passByPtr3+0:0 |
4085
| escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 |
86+
| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0:0 |
87+
| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0:0 | passByRef3+0:0 |
88+
| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 |
89+
| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 |
4190
| escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 |
91+
| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0:0 |
92+
| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0:0 | passByRef6+0:0 |
4293
| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0:0 |
94+
| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0:0 |
95+
| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 |
4396
| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0:0 |
97+
| escape.cpp:217:14:217:16 | CopyValue | c2+0:0 | c2+0:0 |
4498
| escape.cpp:221:8:221:19 | Call | none | c3+0:0 |
4599
| escape.cpp:225:17:225:28 | Call | none | c4+0:0 |
100+
| escape.cpp:247:2:247:27 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 |
46101
| escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 |
102+
| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0:0 | condEscape1+0:0 |
103+
| escape.cpp:249:9:249:34 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 |
47104
| escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 |
105+
| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0:0 | condEscape2+0:0 |

0 commit comments

Comments
 (0)