mirror of
https://github.com/github/codeql.git
synced 2026-05-05 05:35:13 +02:00
Swift: CFG for nil coalescing operator
This commit is contained in:
@@ -1179,7 +1179,7 @@ module Exprs {
|
||||
}
|
||||
|
||||
/**
|
||||
* An autoclosure expression that is generated as part of a logical operation.
|
||||
* An autoclosure expression that is generated as part of a logical operation or nil coalescing expression.
|
||||
*
|
||||
* This is needed because the Swift AST for `b1 && b2` is really syntactic sugar a function call:
|
||||
* ```swift
|
||||
@@ -1188,10 +1188,13 @@ module Exprs {
|
||||
* So the `true` edge from `b1` cannot just go to `b2` since this is an implicit autoclosure.
|
||||
* To handle this dig into the autoclosure when it's an operand of a logical operator.
|
||||
*/
|
||||
private class LogicalAutoClosureTree extends AstPreOrderTree {
|
||||
private class ShortCircuitingAutoClosureTree extends AstPreOrderTree {
|
||||
override AutoClosureExpr ast;
|
||||
|
||||
LogicalAutoClosureTree() { ast = any(LogicalOperation op).getAnOperand() }
|
||||
ShortCircuitingAutoClosureTree() {
|
||||
ast = any(LogicalOperation op).getAnOperand() or
|
||||
ast = any(NilCoalescingExpr expr).getAnOperand()
|
||||
}
|
||||
|
||||
override predicate last(ControlFlowElement last, Completion c) {
|
||||
exists(Completion completion | astLast(ast.getReturn(), last, completion) |
|
||||
@@ -1217,7 +1220,7 @@ module Exprs {
|
||||
private class AutoClosureTree extends AstLeafTree {
|
||||
override AutoClosureExpr ast;
|
||||
|
||||
AutoClosureTree() { not this instanceof LogicalAutoClosureTree }
|
||||
AutoClosureTree() { not this instanceof ShortCircuitingAutoClosureTree }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1557,7 +1560,9 @@ module Exprs {
|
||||
// This one is handled in `LogicalNotTree`.
|
||||
not ast instanceof UnaryLogicalOperation and
|
||||
// These are handled in `LogicalOrTree` and `LogicalAndTree`.
|
||||
not ast instanceof BinaryLogicalOperation
|
||||
not ast instanceof BinaryLogicalOperation and
|
||||
// This one is handled in `NilCoalescingTree`
|
||||
not ast instanceof NilCoalescingExpr
|
||||
}
|
||||
|
||||
final override ControlFlowElement getChildElement(int i) {
|
||||
@@ -1581,6 +1586,36 @@ module Exprs {
|
||||
}
|
||||
}
|
||||
|
||||
private class NilCoalescingTree extends AstControlFlowTree {
|
||||
override NilCoalescingExpr ast;
|
||||
|
||||
final override predicate propagatesAbnormal(ControlFlowElement child) {
|
||||
child.asAstNode() = ast.getAnOperand().getFullyConverted()
|
||||
}
|
||||
|
||||
final override predicate first(ControlFlowElement first) {
|
||||
astFirst(ast.getLeftOperand().getFullyConverted(), first)
|
||||
}
|
||||
|
||||
final override predicate last(ControlFlowElement last, Completion c) {
|
||||
last.asAstNode() = ast and
|
||||
exists(EmptinessCompletion ec | ec = c | not ec.isEmpty())
|
||||
or
|
||||
astLast(ast.getRightOperand().getFullyConverted(), last, c) and
|
||||
c instanceof NormalCompletion
|
||||
}
|
||||
|
||||
final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
|
||||
astLast(ast.getLeftOperand().getFullyConverted(), pred, c) and
|
||||
c instanceof NormalCompletion and
|
||||
succ.asAstNode() = ast
|
||||
or
|
||||
pred.asAstNode() = ast and
|
||||
c.(EmptinessCompletion).isEmpty() and
|
||||
astFirst(ast.getRightOperand().getFullyConverted(), succ)
|
||||
}
|
||||
}
|
||||
|
||||
private class LogicalAndTree extends AstPostOrderTree {
|
||||
override LogicalAndExpr ast;
|
||||
|
||||
|
||||
1
swift/ql/lib/codeql/swift/elements.qll
generated
1
swift/ql/lib/codeql/swift/elements.qll
generated
@@ -140,6 +140,7 @@ import codeql.swift.elements.expr.MakeTemporarilyEscapableExpr
|
||||
import codeql.swift.elements.expr.MemberRefExpr
|
||||
import codeql.swift.elements.expr.MetatypeConversionExpr
|
||||
import codeql.swift.elements.expr.MethodLookupExpr
|
||||
import codeql.swift.elements.expr.NilCoalescingExpr
|
||||
import codeql.swift.elements.expr.NilLiteralExpr
|
||||
import codeql.swift.elements.expr.NumberLiteralExpr
|
||||
import codeql.swift.elements.expr.ObjCSelectorExpr
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
private import codeql.swift.elements.expr.Expr
|
||||
private import codeql.swift.elements.expr.BinaryExpr
|
||||
|
||||
class NilCoalescingExpr extends BinaryExpr {
|
||||
NilCoalescingExpr() {
|
||||
this.getStaticTarget().getName() = "??(_:_:)"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user