Skip to content

Commit 41b283c

Browse files
committed
Swift: add .some enum content to init? calls
Again, this is hacky; we don't distinguish rigorously between an optional value and its content (similar to how it was before enum content flow).
1 parent 03122d7 commit 41b283c

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,13 +590,22 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
590590
c.isSingleton(any(Content::EnumContent ec | ec.getParam() = enum.getElement().getParam(pos)))
591591
)
592592
or
593-
// creation of an optional via implicit conversion
593+
// creation of an optional via implicit conversion,
594+
// i.e. from `f(x)` where `x: T` into `f(.some(x))` where the context `f` expects a `T?`.
594595
exists(InjectIntoOptionalExpr e, OptionalSomeDecl someDecl |
595596
e.convertsFrom(node1.asExpr()) and
596597
node2 = node1 and // HACK: we should ideally have a separate Node case for the (hidden) InjectIntoOptionalExpr
597598
c.isSingleton(any(Content::EnumContent ec | ec.getParam() = someDecl.getParam(0)))
598599
)
599600
or
601+
// creation of an optional by returning from an optional initializer (`init?`)
602+
exists(ConstructorDecl init, OptionalType initRetType, OptionalSomeDecl someDecl |
603+
node1.asExpr().(CallExpr).getStaticTarget() = init and
604+
node2 = node1 and // HACK: again, we should ideally have a separate Node case here, and not reuse the CallExpr
605+
c.isSingleton(any(Content::EnumContent ec | ec.getParam() = someDecl.getParam(0))) and
606+
init.getInterfaceType().(FunctionType).getResult().(FunctionType).getResult() = initRetType
607+
)
608+
or
600609
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
601610
}
602611

0 commit comments

Comments
 (0)