Skip to content

Commit 783560c

Browse files
committed
C++: Add a subclass of PostUpdateNodes and ensure that 'node.asExpr() instanceof ClassAggregateLiteral' holds for this new node subclass.
1 parent 0f21075 commit 783560c

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,41 @@ private module Cached {
264264
e = getConvertedResultExpression(node.asInstruction(), n)
265265
}
266266

267+
/**
268+
* The IR doesn't have an instruction `i` for which this holds:
269+
* ```
270+
* i.getUnconvertedResultExpression() instanceof ClassAggregateLiteral
271+
* ```
272+
* and thus we don't automaticallt get a dataflow node for which:
273+
* ```
274+
* node.asExpr() instanceof ClassAggregateLiteral
275+
* ```
276+
* This is because the IR represents a `ClassAggregateLiteral` as a sequence
277+
* of field writes. To work around this we map `asExpr` on the
278+
* `PostUpdateNode` for the last field write to the class aggregate literal.
279+
*/
280+
private class ClassAggregateInitializerPostUpdateNode extends PostFieldUpdateNode {
281+
ClassAggregateLiteral aggr;
282+
283+
ClassAggregateInitializerPostUpdateNode() {
284+
exists(Node node1, FieldContent fc, int position, StoreInstruction store |
285+
store.getSourceValue().getUnconvertedResultExpression() =
286+
aggr.getFieldExpr(fc.getField(), position) and
287+
node1.asInstruction() = store and
288+
// This is the last field write from the aggregate initialization.
289+
not exists(aggr.getFieldExpr(_, position + 1)) and
290+
storeStep(node1, fc, this)
291+
)
292+
}
293+
294+
ClassAggregateLiteral getClassAggregateLiteral() { result = aggr }
295+
}
296+
297+
private predicate exprNodeShouldBePostUpdateNode(Node node, Expr e, int n) {
298+
node.(ClassAggregateInitializerPostUpdateNode).getClassAggregateLiteral() = e and
299+
n = 0
300+
}
301+
267302
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
268303
private predicate indirectExprNodeShouldBeIndirectInstruction(
269304
IndirectInstruction node, Expr e, int n, int indirectionIndex
@@ -294,7 +329,8 @@ private module Cached {
294329
exprNodeShouldBeInstruction(_, e, n) or
295330
exprNodeShouldBeOperand(_, e, n) or
296331
exprNodeShouldBeIndirectOutNode(_, e, n) or
297-
exprNodeShouldBeIndirectOperand(_, e, n)
332+
exprNodeShouldBeIndirectOperand(_, e, n) or
333+
exprNodeShouldBePostUpdateNode(_, e, n)
298334
}
299335

300336
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
@@ -442,6 +478,12 @@ private module Cached {
442478
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOperand(this, result, n) }
443479
}
444480

481+
private class PostUpdateExprNode extends ExprNodeBase instanceof PostUpdateNode {
482+
PostUpdateExprNode() { exprNodeShouldBePostUpdateNode(this, _, _) }
483+
484+
final override Expr getConvertedExpr(int n) { exprNodeShouldBePostUpdateNode(this, result, n) }
485+
}
486+
445487
/**
446488
* An expression, viewed as a node in a data flow graph.
447489
*/

0 commit comments

Comments
 (0)