Swift: Use shared SuccessorType.

This commit is contained in:
Anders Schack-Mulligen
2025-08-28 10:12:48 +02:00
parent c1662cf05c
commit 1e25b4de4b
6 changed files with 11 additions and 98 deletions

View File

@@ -3,7 +3,6 @@
private import swift
private import ControlFlowGraph
private import internal.ControlFlowGraphImpl as CfgImpl
private import SuccessorTypes
private import CfgImpl::BasicBlocks as BasicBlocksImpl
private import codeql.controlflow.BasicBlock as BB

View File

@@ -2,11 +2,11 @@
private import swift
private import BasicBlocks
private import SuccessorTypes
private import internal.ControlFlowGraphImpl as CfgImpl
private import internal.Completion
private import internal.Scope
private import internal.ControlFlowElements
import codeql.controlflow.SuccessorType
/** An AST node with an associated control-flow graph. */
class CfgScope extends Scope instanceof CfgImpl::CfgScope::Range_ {
@@ -61,72 +61,3 @@ class ControlFlowNode extends CfgImpl::Node {
/** Holds if this node has more than one successor. */
final predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
}
/** The type of a control flow successor. */
class SuccessorType extends CfgImpl::TSuccessorType {
/** Gets a textual representation of successor type. */
string toString() { none() }
}
/** Provides different types of control flow successor types. */
module SuccessorTypes {
/** A normal control flow successor. */
class NormalSuccessor extends SuccessorType, CfgImpl::TSuccessorSuccessor {
final override string toString() { result = "successor" }
}
/** A conditional control flow successor. */
abstract class ConditionalSuccessor extends SuccessorType {
boolean value;
bindingset[value]
ConditionalSuccessor() { any() }
/** Gets the Boolean value of this successor. */
final boolean getValue() { result = value }
override string toString() { result = this.getValue().toString() }
}
/** A Boolean control flow successor. */
class BooleanSuccessor extends ConditionalSuccessor, CfgImpl::TBooleanSuccessor {
BooleanSuccessor() { this = CfgImpl::TBooleanSuccessor(value) }
}
class BreakSuccessor extends SuccessorType, CfgImpl::TBreakSuccessor {
final override string toString() { result = "break" }
}
class ContinueSuccessor extends SuccessorType, CfgImpl::TContinueSuccessor {
final override string toString() { result = "continue" }
}
class ReturnSuccessor extends SuccessorType, CfgImpl::TReturnSuccessor {
final override string toString() { result = "return" }
}
class MatchingSuccessor extends ConditionalSuccessor, CfgImpl::TMatchingSuccessor {
MatchingSuccessor() { this = CfgImpl::TMatchingSuccessor(value) }
/** Holds if this is a match successor. */
predicate isMatch() { value = true }
override string toString() { if this.isMatch() then result = "match" else result = "no-match" }
}
class FallthroughSuccessor extends SuccessorType, CfgImpl::TFallthroughSuccessor {
final override string toString() { result = "fallthrough" }
}
class EmptinessSuccessor extends ConditionalSuccessor, CfgImpl::TEmptinessSuccessor {
EmptinessSuccessor() { this = CfgImpl::TEmptinessSuccessor(value) }
predicate isEmpty() { value = true }
override string toString() { if this.isEmpty() then result = "empty" else result = "non-empty" }
}
class ExceptionSuccessor extends SuccessorType, CfgImpl::TExceptionSuccessor {
override string toString() { result = "exception" }
}
}

View File

@@ -8,7 +8,6 @@ private import swift
private import codeql.swift.controlflow.ControlFlowGraph
private import ControlFlowElements
private import ControlFlowGraphImpl
private import SuccessorTypes
private newtype TCompletion =
TSimpleCompletion() or
@@ -324,7 +323,7 @@ abstract class NormalCompletion extends Completion {
/** A simple (normal) completion. */
class SimpleCompletion extends NormalCompletion, TSimpleCompletion {
override NormalSuccessor getAMatchingSuccessorType() { any() }
override DirectSuccessor getAMatchingSuccessorType() { any() }
override string toString() { result = "simple" }
}
@@ -468,7 +467,7 @@ class FallthroughCompletion extends Completion, TFallthroughCompletion {
FallthroughCompletion() { this = TFallthroughCompletion(dest) }
override FallthroughSuccessor getAMatchingSuccessorType() { any() }
override DirectSuccessor getAMatchingSuccessorType() { any() }
CaseStmt getDestination() { result = dest }

View File

@@ -1976,18 +1976,6 @@ private module Cached {
result = n.(FuncDeclElement).getAst() or
result = n.(KeyPathElement).getAst()
}
cached
newtype TSuccessorType =
TSuccessorSuccessor() or
TBooleanSuccessor(boolean b) { b in [false, true] } or
TBreakSuccessor() or
TContinueSuccessor() or
TReturnSuccessor() or
TMatchingSuccessor(boolean match) { match in [false, true] } or
TFallthroughSuccessor() or
TEmptinessSuccessor(boolean isEmpty) { isEmpty in [false, true] } or
TExceptionSuccessor()
}
import Cached

View File

@@ -57,22 +57,18 @@ module CfgInput implements InputSig<Location> {
* Hold if `c` represents simple (normal) evaluation of a statement or an
* expression.
*/
predicate successorTypeIsSimple(SuccessorType t) {
t instanceof Cfg::SuccessorTypes::NormalSuccessor
}
predicate successorTypeIsSimple(SuccessorType t) { t instanceof Cfg::DirectSuccessor }
/** Holds if `t` is an abnormal exit type out of a CFG scope. */
predicate isAbnormalExitType(SuccessorType t) {
t instanceof Cfg::SuccessorTypes::ExceptionSuccessor
}
predicate isAbnormalExitType(SuccessorType t) { t instanceof Cfg::ExceptionSuccessor }
/** Hold if `t` represents a conditional successor type. */
predicate successorTypeIsCondition(SuccessorType t) {
t instanceof Cfg::SuccessorTypes::BooleanSuccessor or
t instanceof Cfg::SuccessorTypes::BreakSuccessor or
t instanceof Cfg::SuccessorTypes::ContinueSuccessor or
t instanceof Cfg::SuccessorTypes::MatchingSuccessor or
t instanceof Cfg::SuccessorTypes::EmptinessSuccessor
t instanceof Cfg::BooleanSuccessor or
t instanceof Cfg::BreakSuccessor or
t instanceof Cfg::ContinueSuccessor or
t instanceof Cfg::MatchingSuccessor or
t instanceof Cfg::EmptinessSuccessor
}
/** Holds if `first` is first executed when entering `scope`. */

View File

@@ -108,7 +108,7 @@ private class DefaultPathInjectionBarrier extends PathInjectionBarrier {
TaintTracking::localTaint(validated, DataFlow::exprNode(normalize.getQualifier())) and
DataFlow::localExprFlow(normalize, starts.getQualifier()) and
DataFlow::localFlow(validated, this) and
exists(ConditionBlock bb, SuccessorTypes::BooleanSuccessor b |
exists(ConditionBlock bb, BooleanSuccessor b |
bb.getANode().getNode().asAstNode().(IfStmt).getACondition() = getImmediateParent*(starts) and
b.getValue() = true
|