Skip to content

Commit 7db36b2

Browse files
C++: Skip IR translation for functions with invalid ASTs
An slightly invalid AST can cause IR construction to generate extremely bad IR. This change provides a single place to detect invalid ASTs, and to skip IR construction for the affected functions.
1 parent 03802ed commit 7db36b2

File tree

1 file changed

+64
-11
lines changed

1 file changed

+64
-11
lines changed

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

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import cpp
2+
import cpp
23
import semmle.code.cpp.ir.implementation.raw.IR
4+
private import semmle.code.cpp.ir.IRConfiguration
35
private import semmle.code.cpp.ir.implementation.Opcode
46
private import semmle.code.cpp.ir.internal.OperandTag
57
private import semmle.code.cpp.ir.internal.TempVariableTag
@@ -83,7 +85,8 @@ private predicate ignoreExprOnly(Expr expr) {
8385
// Ignore the allocator call, because we always synthesize it. Don't ignore
8486
// its arguments, though, because we use them as part of the synthesis.
8587
newExpr.getAllocatorCall() = expr
86-
)
88+
) or
89+
not translateFunction(expr.getEnclosingFunction())
8790
}
8891

8992
/**
@@ -94,6 +97,49 @@ private predicate ignoreExpr(Expr expr) {
9497
ignoreExprAndDescendants(getRealParent*(expr))
9598
}
9699

100+
/**
101+
* Holds if `func` contains an AST that cannot be translated into IR. This is mostly used to work
102+
* around extractor bugs. Once the relevant extractor bugs are fixed, this predicate can be removed.
103+
*/
104+
private predicate isInvalidFunction(Function func) {
105+
exists(Literal literal |
106+
// Constructor field inits within a compiler-generated copy constructor have a source expression
107+
// that is a `Literal` with no value.
108+
literal = func.(Constructor).getAnInitializer().(ConstructorFieldInit).getExpr() and
109+
not exists(literal.getValue())
110+
) or
111+
exists(ThisExpr thisExpr |
112+
// An instantiation of a member function template is not treated as a `MemberFunction` if it has
113+
// only non-type template arguments.
114+
thisExpr.getEnclosingFunction() = func and
115+
not func instanceof MemberFunction
116+
) or
117+
exists(Expr expr |
118+
// Expression missing a type.
119+
expr.getEnclosingFunction() = func and
120+
not exists(expr.getType())
121+
)
122+
}
123+
124+
/**
125+
* Holds if `func` should be translated to IR.
126+
*/
127+
private predicate translateFunction(Function func) {
128+
not func.isFromUninstantiatedTemplate(_) and
129+
func.hasEntryPoint() and
130+
not isInvalidFunction(func) and
131+
exists(IRConfiguration config |
132+
config.shouldCreateIRForFunction(func)
133+
)
134+
}
135+
136+
/**
137+
* Holds if `stmt` should be translated to IR.
138+
*/
139+
private predicate translateStmt(Stmt stmt) {
140+
translateFunction(stmt.getEnclosingFunction())
141+
}
142+
97143
/**
98144
* Holds if `expr` is most naturally evaluated as control flow, rather than as
99145
* a value.
@@ -236,7 +282,7 @@ newtype TTranslatedElement =
236282
} or
237283
// The initialization of a field via a member of an initializer list.
238284
TTranslatedExplicitFieldInitialization(Expr ast, Field field,
239-
Expr expr) {
285+
Expr expr) {
240286
exists(ClassAggregateLiteral initList |
241287
not ignoreExpr(initList) and
242288
ast = initList and
@@ -260,14 +306,14 @@ newtype TTranslatedElement =
260306
} or
261307
// The initialization of an array element via a member of an initializer list.
262308
TTranslatedExplicitElementInitialization(
263-
ArrayAggregateLiteral initList, int elementIndex) {
309+
ArrayAggregateLiteral initList, int elementIndex) {
264310
not ignoreExpr(initList) and
265311
exists(initList.getElementExpr(elementIndex))
266312
} or
267313
// The value initialization of a range of array elements that were omitted
268314
// from an initializer list.
269315
TTranslatedElementValueInitialization(ArrayAggregateLiteral initList,
270-
int elementIndex, int elementCount) {
316+
int elementIndex, int elementCount) {
271317
not ignoreExpr(initList) and
272318
isFirstValueInitializedElementInRange(initList, elementIndex) and
273319
elementCount =
@@ -287,28 +333,35 @@ newtype TTranslatedElement =
287333
not ignoreExpr(destruction)
288334
} or
289335
// A statement
290-
TTranslatedStmt(Stmt stmt) or
336+
TTranslatedStmt(Stmt stmt) {
337+
translateStmt(stmt)
338+
} or
291339
// A function
292340
TTranslatedFunction(Function func) {
293-
func.hasEntryPoint() and
294-
not func.isFromUninstantiatedTemplate(_)
341+
translateFunction(func)
295342
} or
296343
// A constructor init list
297344
TTranslatedConstructorInitList(Function func) {
298-
func.hasEntryPoint()
345+
translateFunction(func)
299346
} or
300347
// A destructor destruction list
301348
TTranslatedDestructorDestructionList(Function func) {
302-
func.hasEntryPoint()
349+
translateFunction(func)
303350
} or
304351
// A function parameter
305352
TTranslatedParameter(Parameter param) {
306-
param.getFunction().hasEntryPoint() or
307-
exists(param.getCatchBlock())
353+
exists(Function func |
354+
(
355+
func = param.getFunction() or
356+
func = param.getCatchBlock().getEnclosingFunction()
357+
) and
358+
translateFunction(func)
359+
)
308360
} or
309361
// A local declaration
310362
TTranslatedDeclarationEntry(DeclarationEntry entry) {
311363
exists(DeclStmt declStmt |
364+
translateStmt(declStmt) and
312365
declStmt.getADeclarationEntry() = entry
313366
)
314367
} or

0 commit comments

Comments
 (0)