From f81a3ec464ad9e46736c527b1dcecab15cf46327 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Mon, 30 Oct 2023 17:04:53 +0100 Subject: [PATCH 1/6] Swift: add `VarDecl` children to `CaptureListExpr` --- .../extractor/translators/ExprTranslator.cpp | 1 + swift/ql/.generated.list | 6 +- .../codeql/swift/generated/ParentChild.qll | 10 ++- swift/ql/lib/codeql/swift/generated/Raw.qll | 5 ++ .../swift/generated/expr/CaptureListExpr.qll | 21 +++++ swift/ql/lib/swift.dbscheme | 7 ++ .../extractor-tests/declarations/all.expected | 26 ++++++ .../declarations/declarations.swift | 12 ++- .../test/library-tests/ast/PrintAst.expected | 88 ++++++++++++++++++- .../test/library-tests/ast/declarations.swift | 12 ++- .../dataflow/capture/closures.swift | 2 +- .../dataflow/capture/inlinetest.expected | 2 + swift/schema.py | 1 + 13 files changed, 180 insertions(+), 13 deletions(-) diff --git a/swift/extractor/translators/ExprTranslator.cpp b/swift/extractor/translators/ExprTranslator.cpp index 3274c49675e6..b6a1fe6e24eb 100644 --- a/swift/extractor/translators/ExprTranslator.cpp +++ b/swift/extractor/translators/ExprTranslator.cpp @@ -119,6 +119,7 @@ codeql::CaptureListExpr ExprTranslator::translateCaptureListExpr( entry.closure_body = dispatcher.fetchLabel(expr.getClosureBody()); for (const auto& item : const_cast(expr).getCaptureList()) { entry.binding_decls.push_back(dispatcher.fetchLabel(item.PBD)); + entry.variables.push_back(dispatcher.fetchLabel(item.getVar())); } return entry; } diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index 9d8826f7ba05..9e4c60eb4d33 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -376,10 +376,10 @@ lib/codeql/swift/generated/KeyPathComponent.qll c79c7bc04fc1426992ab472eedc1a20a lib/codeql/swift/generated/Locatable.qll be20967d48a34cdba126fe298606e0adc11697831f097acba9c52a0b7ce9983e 8aa01bc376614abbc3209e25785c72f86c9b4e94bb5f471a4a0677fedaec4f61 lib/codeql/swift/generated/Location.qll c5793987e77812059a28254dadee29bfe9b38153c0399fbb1bf6a2f5c237fdab 6e6d8802b021e36bbaad81845657769dd48a798ea33080ada05e9818a20b38f7 lib/codeql/swift/generated/OtherAvailabilitySpec.qll 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 -lib/codeql/swift/generated/ParentChild.qll f2c1bcd5495f9b72cf43f7fe9691e888071e128069c1a4cb43feecec55fd0ab6 95c801caf726159580192fb6f93e2218776014fb0def04ec423dff3f245d53c1 +lib/codeql/swift/generated/ParentChild.qll 680cbaa7cad7b8c33b7cf3b60aba7013facdbc5601b5076a6f38560fd284f2e8 af472eeaca6bd32848cb2de647ff015053f9fb7c54c1eca18f91fcc6ea8ad7b7 lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll f82d9ca416fe8bd59b5531b65b1c74c9f317b3297a6101544a11339a1cffce38 7f5c6d3309e66c134107afe55bae76dfc9a72cb7cdd6d4c3706b6b34cee09fa0 lib/codeql/swift/generated/PureSynthConstructors.qll 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 -lib/codeql/swift/generated/Raw.qll 59a847c009d682dfceb72f33bb54d6cf6da589e59a386450bb5fba310a4170e7 ed02d96d3bfc998a105b8f34e6a92d966e6c3db5c581872a53ac5db6904e5fab +lib/codeql/swift/generated/Raw.qll fc093e8aef6c558b17ba4f7a4d42ce782b0fef3222b983df41b79f921bae37c8 586b13654f152b747f07373edd69b7f478d59ecf5abc7c18a5a221851ce8f73a lib/codeql/swift/generated/Synth.qll 551fdf7e4b53f9ee1314d1bb42c2638cf82f45bfa1f40a635dfa7b6072e4418c 9ab178464700a19951fc5285acacda4913addee81515d8e072b3d7055935a814 lib/codeql/swift/generated/SynthConstructors.qll 2f801bd8b0db829b0253cd459ed3253c1fdfc55dce68ebc53e7fec138ef0aca4 2f801bd8b0db829b0253cd459ed3253c1fdfc55dce68ebc53e7fec138ef0aca4 lib/codeql/swift/generated/UnknownFile.qll 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 @@ -446,7 +446,7 @@ lib/codeql/swift/generated/expr/BridgeFromObjCExpr.qll b9a6520d01613dfb8c7606177 lib/codeql/swift/generated/expr/BridgeToObjCExpr.qll 31ca13762aee9a6a17746f40ec4e1e929811c81fdadb27c48e0e7ce6a3a6222d 31ca13762aee9a6a17746f40ec4e1e929811c81fdadb27c48e0e7ce6a3a6222d lib/codeql/swift/generated/expr/BuiltinLiteralExpr.qll 052f8d0e9109a0d4496da1ae2b461417951614c88dbc9d80220908734b3f70c6 536fa290bb75deae0517d53528237eab74664958bf7fdbf8041283415dda2142 lib/codeql/swift/generated/expr/CallExpr.qll c7dc105fcb6c0956e20d40f736db35bd7f38f41c3d872858972c2ca120110d36 c7dc105fcb6c0956e20d40f736db35bd7f38f41c3d872858972c2ca120110d36 -lib/codeql/swift/generated/expr/CaptureListExpr.qll 300e3e7b60d49c321c9b6209ace7cd4665dc3db1b3f4227af476c3bdaf7da196 3ccc01074fa7cef8df1f2923fb3837af59360f5bd496ccbb5f0f77d02ac9311a +lib/codeql/swift/generated/expr/CaptureListExpr.qll 29271af76039bf16aadc5544ab59f06e5689cb92c944f0ed0cf6d23702fcf449 b467850b683f6415edba260065e15c89fb52d0f3ec07f65d526db9f6965694d1 lib/codeql/swift/generated/expr/CheckedCastExpr.qll 146c24e72cda519676321d3bdb89d1953dfe1810d2710f04cfdc4210ace24c40 91093e0ba88ec3621b538d98454573b5eea6d43075a2ab0a08f80f9b9be336d3 lib/codeql/swift/generated/expr/ClassMetatypeToObjectExpr.qll 076c0f7369af3fffc8860429bd8e290962bf7fc8cf53bbba061de534e99cc8bf 076c0f7369af3fffc8860429bd8e290962bf7fc8cf53bbba061de534e99cc8bf lib/codeql/swift/generated/expr/ClosureExpr.qll f194fc8c5f67fcf0219e8e2de93ee2b820c27a609b2986b68d57a54445f66b61 3cae87f6c6eefb32195f06bc4c95ff6634446ecf346d3a3c94dc05c1539f3de2 diff --git a/swift/ql/lib/codeql/swift/generated/ParentChild.qll b/swift/ql/lib/codeql/swift/generated/ParentChild.qll index 26dfa3c94b3b..0467fa10caf0 100644 --- a/swift/ql/lib/codeql/swift/generated/ParentChild.qll +++ b/swift/ql/lib/codeql/swift/generated/ParentChild.qll @@ -1138,12 +1138,13 @@ private module Impl { private Element getImmediateChildOfCaptureListExpr( CaptureListExpr e, int index, string partialPredicateCall ) { - exists(int b, int bExpr, int n, int nBindingDecl, int nClosureBody | + exists(int b, int bExpr, int n, int nBindingDecl, int nVariable, int nClosureBody | b = 0 and bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and n = bExpr and nBindingDecl = n + 1 + max(int i | i = -1 or exists(e.getBindingDecl(i)) | i) and - nClosureBody = nBindingDecl + 1 and + nVariable = nBindingDecl + 1 + max(int i | i = -1 or exists(e.getVariable(i)) | i) and + nClosureBody = nVariable + 1 and ( none() or @@ -1152,7 +1153,10 @@ private module Impl { result = e.getBindingDecl(index - n) and partialPredicateCall = "BindingDecl(" + (index - n).toString() + ")" or - index = nBindingDecl and + result = e.getVariable(index - nBindingDecl) and + partialPredicateCall = "Variable(" + (index - nBindingDecl).toString() + ")" + or + index = nVariable and result = e.getImmediateClosureBody() and partialPredicateCall = "ClosureBody()" ) diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index 00693018cf1d..4a1a4dcbad4c 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -1103,6 +1103,11 @@ module Raw { capture_list_expr_binding_decls(this, index, result) } + /** + * Gets the `index`th variable of this capture list expression (0-based). + */ + VarDecl getVariable(int index) { capture_list_expr_variables(this, index, result) } + /** * Gets the closure body of this capture list expression. */ diff --git a/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll index 535e477d177c..e2aeb2f9ffde 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll @@ -4,6 +4,7 @@ private import codeql.swift.generated.Raw import codeql.swift.elements.expr.ClosureExpr import codeql.swift.elements.expr.Expr import codeql.swift.elements.decl.PatternBindingDecl +import codeql.swift.elements.decl.VarDecl module Generated { class CaptureListExpr extends Synth::TCaptureListExpr, Expr { @@ -29,6 +30,26 @@ module Generated { */ final int getNumberOfBindingDecls() { result = count(int i | exists(this.getBindingDecl(i))) } + /** + * Gets the `index`th variable of this capture list expression (0-based). + */ + VarDecl getVariable(int index) { + result = + Synth::convertVarDeclFromRaw(Synth::convertCaptureListExprToRaw(this) + .(Raw::CaptureListExpr) + .getVariable(index)) + } + + /** + * Gets any of the variables of this capture list expression. + */ + final VarDecl getAVariable() { result = this.getVariable(_) } + + /** + * Gets the number of variables of this capture list expression. + */ + final int getNumberOfVariables() { result = count(int i | exists(this.getVariable(i))) } + /** * Gets the closure body of this capture list expression. * diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index 7c17e1f4b2d3..afa3da98ec17 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -846,6 +846,13 @@ capture_list_expr_binding_decls( //dir=expr int binding_decl: @pattern_binding_decl_or_none ref ); +#keyset[id, index] +capture_list_expr_variables( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + @closure_expr = @auto_closure_expr | @explicit_closure_expr diff --git a/swift/ql/test/extractor-tests/declarations/all.expected b/swift/ql/test/extractor-tests/declarations/all.expected index 44c5650fad1a..f06a19299a2a 100644 --- a/swift/ql/test/extractor-tests/declarations/all.expected +++ b/swift/ql/test/extractor-tests/declarations/all.expected @@ -274,3 +274,29 @@ | declarations.swift:182:7:182:7 | self | | | declarations.swift:183:1:183:15 | A | getAliasedType:B | | declarations.swift:184:1:184:18 | C | getAliasedType:Int? | +| declarations.swift:186:1:194:1 | S | | +| declarations.swift:186:7:186:7 | S.deinit() | | +| declarations.swift:186:7:186:7 | S.init() | | +| declarations.swift:186:7:186:7 | self | | +| declarations.swift:186:7:186:7 | self | | +| declarations.swift:187:3:187:13 | var ... = ... | | +| declarations.swift:187:7:187:7 | _modify | | +| declarations.swift:187:7:187:7 | bf1 | | +| declarations.swift:187:7:187:7 | get | | +| declarations.swift:187:7:187:7 | self | | +| declarations.swift:187:7:187:7 | self | | +| declarations.swift:187:7:187:7 | self | | +| declarations.swift:187:7:187:7 | set | | +| declarations.swift:187:7:187:7 | value | | +| declarations.swift:188:3:193:3 | captureThis() | | +| declarations.swift:188:8:188:8 | self | | +| declarations.swift:189:5:189:13 | var ... = ... | | +| declarations.swift:189:9:189:9 | x | | +| declarations.swift:190:5:192:5 | var ... = ... | | +| declarations.swift:190:9:190:9 | f | | +| declarations.swift:190:16:190:16 | self | | +| declarations.swift:190:16:190:16 | var ... = ... | | +| declarations.swift:190:22:190:22 | var ... = ... | | +| declarations.swift:190:22:190:22 | x | | +| declarations.swift:191:7:191:7 | self | | +| declarations.swift:191:18:191:18 | x | | diff --git a/swift/ql/test/extractor-tests/declarations/declarations.swift b/swift/ql/test/extractor-tests/declarations/declarations.swift index eb82cb0cce17..6a1503a95e5e 100644 --- a/swift/ql/test/extractor-tests/declarations/declarations.swift +++ b/swift/ql/test/extractor-tests/declarations/declarations.swift @@ -181,4 +181,14 @@ func ifConfig() { class B {} typealias A = B -typealias C = Int? \ No newline at end of file +typealias C = Int? + +class S { + var bf1 = 0 + func captureThis() { + var x = 0 + var f = { [self, x] () in + self.bf1 = x + }; + } +} diff --git a/swift/ql/test/library-tests/ast/PrintAst.expected b/swift/ql/test/library-tests/ast/PrintAst.expected index 918f3d412d42..c8dc0885e531 100644 --- a/swift/ql/test/library-tests/ast/PrintAst.expected +++ b/swift/ql/test/library-tests/ast/PrintAst.expected @@ -2444,15 +2444,15 @@ cfg.swift: # 368| getBindingDecl(1): [PatternBindingDecl] var ... = ... # 368| getInit(0): [StringLiteralExpr] literal # 368| getPattern(0): [NamedPattern] t +# 368| getVariable(0): [ConcreteVarDecl] z +# 368| Type = Int +# 368| getVariable(1): [ConcreteVarDecl] t +# 368| Type = String # 368| getClosureBody(): [ExplicitClosureExpr] { ... } # 368| getBody(): [BraceStmt] { ... } # 369| getElement(0): [ReturnStmt] return ... # 369| getResult(): [DeclRefExpr] z # 369| getCapture(0): [CapturedDecl] z -# 368| [ConcreteVarDecl] z -# 368| Type = Int -# 368| [ConcreteVarDecl] t -# 368| Type = String # 373| [NamedFunction] testTupleElement(t:) # 373| InterfaceType = ((a: Int, Int, c: Int)) -> Int # 373| getParam(0): [ParamDecl] t @@ -4543,6 +4543,86 @@ declarations.swift: # 182| getElement(0): [ReturnStmt] return # 183| [TypeAliasDecl] A # 184| [TypeAliasDecl] C +# 186| [ClassDecl] S +# 187| getMember(0): [PatternBindingDecl] var ... = ... +# 187| getInit(0): [IntegerLiteralExpr] 0 +# 187| getPattern(0): [NamedPattern] bf1 +# 187| getMember(1): [ConcreteVarDecl] bf1 +# 187| Type = Int +# 187| getAccessor(0): [Accessor] get +# 187| InterfaceType = (S) -> () -> Int +# 187| getSelfParam(): [ParamDecl] self +# 187| Type = S +# 187| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [ReturnStmt] return ... +#-----| getResult(): [MemberRefExpr] .bf1 +#-----| getBase(): [DeclRefExpr] self +# 187| getAccessor(1): [Accessor] set +# 187| InterfaceType = (S) -> (Int) -> () +# 187| getSelfParam(): [ParamDecl] self +# 187| Type = S +# 187| getParam(0): [ParamDecl] value +# 187| Type = Int +# 187| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [AssignExpr] ... = ... +#-----| getDest(): [MemberRefExpr] .bf1 +#-----| getBase(): [DeclRefExpr] self +#-----| getSource(): [DeclRefExpr] value +# 187| getAccessor(2): [Accessor] _modify +# 187| InterfaceType = (S) -> () -> () +# 187| getSelfParam(): [ParamDecl] self +# 187| Type = S +# 187| getBody(): [BraceStmt] { ... } +# 187| getElement(0): [YieldStmt] yield ... +#-----| getResult(0): [MemberRefExpr] .bf1 +#-----| getBase(): [DeclRefExpr] self +#-----| getResult(0).getFullyConverted(): [InOutExpr] &... +# 188| getMember(2): [NamedFunction] captureThis() +# 188| InterfaceType = (S) -> () -> () +# 188| getSelfParam(): [ParamDecl] self +# 188| Type = S +# 188| getBody(): [BraceStmt] { ... } +# 189| getVariable(0): [ConcreteVarDecl] x +# 189| Type = Int +# 190| getVariable(1): [ConcreteVarDecl] f +# 190| Type = () -> () +# 189| getElement(0): [PatternBindingDecl] var ... = ... +# 189| getInit(0): [IntegerLiteralExpr] 0 +# 189| getPattern(0): [NamedPattern] x +# 190| getElement(1): [PatternBindingDecl] var ... = ... +# 190| getInit(0): [CaptureListExpr] { ... } +# 190| getBindingDecl(0): [PatternBindingDecl] var ... = ... +# 190| getInit(0): [DeclRefExpr] self +# 190| getPattern(0): [NamedPattern] self +# 190| getBindingDecl(1): [PatternBindingDecl] var ... = ... +# 190| getInit(0): [DeclRefExpr] x +# 190| getInit(0).getFullyConverted(): [LoadExpr] (Int) ... +# 190| getPattern(0): [NamedPattern] x +# 190| getVariable(0): [ConcreteVarDecl] self +# 190| Type = S +# 190| getVariable(1): [ConcreteVarDecl] x +# 190| Type = Int +# 190| getClosureBody(): [ExplicitClosureExpr] { ... } +# 190| getBody(): [BraceStmt] { ... } +# 191| getElement(0): [ReturnStmt] return ... +# 191| getResult(): [AssignExpr] ... = ... +# 191| getDest(): [MemberRefExpr] .bf1 +# 191| getBase(): [DeclRefExpr] self +# 191| getSource(): [DeclRefExpr] x +# 191| getCapture(0): [CapturedDecl] self +# 191| getCapture(1): [CapturedDecl] x +# 190| getPattern(0): [NamedPattern] f +# 186| getMember(3): [Deinitializer] S.deinit() +# 186| InterfaceType = (S) -> () -> () +# 186| getSelfParam(): [ParamDecl] self +# 186| Type = S +# 186| getBody(): [BraceStmt] { ... } +# 186| getMember(4): [Initializer] S.init() +# 186| InterfaceType = (S.Type) -> () -> S +# 186| getSelfParam(): [ParamDecl] self +# 186| Type = S +# 186| getBody(): [BraceStmt] { ... } +# 186| getElement(0): [ReturnStmt] return expressions.swift: # 1| [TopLevelCodeDecl] { ... } # 1| getBody(): [BraceStmt] { ... } diff --git a/swift/ql/test/library-tests/ast/declarations.swift b/swift/ql/test/library-tests/ast/declarations.swift index eb82cb0cce17..6a1503a95e5e 100644 --- a/swift/ql/test/library-tests/ast/declarations.swift +++ b/swift/ql/test/library-tests/ast/declarations.swift @@ -181,4 +181,14 @@ func ifConfig() { class B {} typealias A = B -typealias C = Int? \ No newline at end of file +typealias C = Int? + +class S { + var bf1 = 0 + func captureThis() { + var x = 0 + var f = { [self, x] () in + self.bf1 = x + }; + } +} diff --git a/swift/ql/test/library-tests/dataflow/capture/closures.swift b/swift/ql/test/library-tests/dataflow/capture/closures.swift index 948a46b9b989..e1c0480b044a 100644 --- a/swift/ql/test/library-tests/dataflow/capture/closures.swift +++ b/swift/ql/test/library-tests/dataflow/capture/closures.swift @@ -188,4 +188,4 @@ func multi() { var f = { () in x = y } f() sink(x) // $ hasValueFlow=multi -} \ No newline at end of file +} diff --git a/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected b/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected index 8ec8033d086e..d6a9e48c45d2 100644 --- a/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected +++ b/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected @@ -1,2 +1,4 @@ testFailures +| closures.swift:180:16:181:1 | // $ hasValueFlow=captureThis\n | Missing result:hasValueFlow=captureThis | +| closures.swift:181:21:182:1 | // $ hasValueFlow=captureThis\n | Missing result:hasValueFlow=captureThis | failures diff --git a/swift/schema.py b/swift/schema.py index 95ed1c70caa9..b74103a283aa 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -411,6 +411,7 @@ class CapturedDecl(Decl): class CaptureListExpr(Expr): binding_decls: list[PatternBindingDecl] | child + variables: list[VarDecl] | child closure_body: "ClosureExpr" | child class CollectionExpr(Expr): From 7bae2d9192104d3808848f8e39fe4edcccd0e58c Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 31 Oct 2023 10:10:00 +0100 Subject: [PATCH 2/6] Swift: fix tests --- .../generated/decl/CapturedDecl/PrintAst.expected | 4 ++-- swift/ql/test/extractor-tests/updates/PrintAst.expected | 4 ++-- swift/ql/test/library-tests/dataflow/capture/closures.swift | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/swift/ql/test/extractor-tests/generated/decl/CapturedDecl/PrintAst.expected b/swift/ql/test/extractor-tests/generated/decl/CapturedDecl/PrintAst.expected index 0c17c568ee77..d7f64e2a81a0 100644 --- a/swift/ql/test/extractor-tests/generated/decl/CapturedDecl/PrintAst.expected +++ b/swift/ql/test/extractor-tests/generated/decl/CapturedDecl/PrintAst.expected @@ -18,6 +18,8 @@ closures.swift: # 7| getInit(0): [CallExpr] call to hello() # 7| getFunction(): [DeclRefExpr] hello() # 7| getPattern(0): [NamedPattern] x +# 7| getVariable(0): [ConcreteVarDecl] x +# 7| Type = String # 7| getClosureBody(): [ExplicitClosureExpr] { ... } # 7| getBody(): [BraceStmt] { ... } # 8| getElement(0): [CallExpr] call to print(_:separator:terminator:) @@ -44,8 +46,6 @@ closures.swift: # 9| getExpr(): [DefaultArgumentExpr] default terminator # 8| getCapture(0): [CapturedDecl] x # 9| getCapture(1): [CapturedDecl] y -# 7| [ConcreteVarDecl] x -# 7| Type = String # 12| [TopLevelCodeDecl] { ... } # 12| getBody(): [BraceStmt] { ... } # 12| getElement(0): [PatternBindingDecl] var ... = ... diff --git a/swift/ql/test/extractor-tests/updates/PrintAst.expected b/swift/ql/test/extractor-tests/updates/PrintAst.expected index 664b84da07bd..709074247163 100644 --- a/swift/ql/test/extractor-tests/updates/PrintAst.expected +++ b/swift/ql/test/extractor-tests/updates/PrintAst.expected @@ -214,6 +214,8 @@ v5.8.swift: # 37| getInit(0): [DeclRefExpr] self # 37| getInit(0).getFullyConverted(): [InjectIntoOptionalExpr] (ViewController?) ... # 37| getPattern(0): [NamedPattern] self +# 37| getVariable(0): [ConcreteVarDecl] self +# 37| Type = ViewController? # 37| getClosureBody(): [ExplicitClosureExpr] { ... } # 37| getBody(): [BraceStmt] { ... } # 38| getElement(0): [GuardStmt] guard ... else { ... } @@ -248,8 +250,6 @@ v5.8.swift: # 33| Type = ViewController # 33| getBody(): [BraceStmt] { ... } # 33| getElement(0): [ReturnStmt] return -# 37| [ConcreteVarDecl] self -# 37| Type = ViewController? # 38| [ConcreteVarDecl] self # 38| Type = ViewController # 39| [Comment] // refers to `self.dismiss()` diff --git a/swift/ql/test/library-tests/dataflow/capture/closures.swift b/swift/ql/test/library-tests/dataflow/capture/closures.swift index e1c0480b044a..c3fbdbdc13df 100644 --- a/swift/ql/test/library-tests/dataflow/capture/closures.swift +++ b/swift/ql/test/library-tests/dataflow/capture/closures.swift @@ -177,8 +177,8 @@ class S { f(source("captureThis", 2)); - sink(bf1); // $ MISSING: hasValueFlow - sink(self.bf2); // $ MISSING: hasValueFlow + sink(bf1); // $ hasValueFlow=captureThis + sink(self.bf2); // $ hasValueFlow=captureThis } } From ffff10a7e860e43cb2170e0bf04239188a43609a Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 31 Oct 2023 10:43:14 +0100 Subject: [PATCH 3/6] Swift: synthesize `CaptureListExpr::getVariable` in QL instead of extracting it --- swift/extractor/translators/ExprTranslator.cpp | 1 - swift/ql/.generated.list | 4 ++-- .../lib/codeql/swift/elements/expr/CaptureListExpr.qll | 6 ++++++ swift/ql/lib/codeql/swift/generated/Raw.qll | 5 ----- .../lib/codeql/swift/generated/expr/CaptureListExpr.qll | 9 +++------ swift/ql/lib/swift.dbscheme | 7 ------- swift/schema.py | 4 +++- 7 files changed, 14 insertions(+), 22 deletions(-) diff --git a/swift/extractor/translators/ExprTranslator.cpp b/swift/extractor/translators/ExprTranslator.cpp index b6a1fe6e24eb..3274c49675e6 100644 --- a/swift/extractor/translators/ExprTranslator.cpp +++ b/swift/extractor/translators/ExprTranslator.cpp @@ -119,7 +119,6 @@ codeql::CaptureListExpr ExprTranslator::translateCaptureListExpr( entry.closure_body = dispatcher.fetchLabel(expr.getClosureBody()); for (const auto& item : const_cast(expr).getCaptureList()) { entry.binding_decls.push_back(dispatcher.fetchLabel(item.PBD)); - entry.variables.push_back(dispatcher.fetchLabel(item.getVar())); } return entry; } diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index 9e4c60eb4d33..00d6f0fe319a 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -379,7 +379,7 @@ lib/codeql/swift/generated/OtherAvailabilitySpec.qll 0e26a203b26ff0581b7396b0c6d lib/codeql/swift/generated/ParentChild.qll 680cbaa7cad7b8c33b7cf3b60aba7013facdbc5601b5076a6f38560fd284f2e8 af472eeaca6bd32848cb2de647ff015053f9fb7c54c1eca18f91fcc6ea8ad7b7 lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll f82d9ca416fe8bd59b5531b65b1c74c9f317b3297a6101544a11339a1cffce38 7f5c6d3309e66c134107afe55bae76dfc9a72cb7cdd6d4c3706b6b34cee09fa0 lib/codeql/swift/generated/PureSynthConstructors.qll 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 -lib/codeql/swift/generated/Raw.qll fc093e8aef6c558b17ba4f7a4d42ce782b0fef3222b983df41b79f921bae37c8 586b13654f152b747f07373edd69b7f478d59ecf5abc7c18a5a221851ce8f73a +lib/codeql/swift/generated/Raw.qll 59a847c009d682dfceb72f33bb54d6cf6da589e59a386450bb5fba310a4170e7 ed02d96d3bfc998a105b8f34e6a92d966e6c3db5c581872a53ac5db6904e5fab lib/codeql/swift/generated/Synth.qll 551fdf7e4b53f9ee1314d1bb42c2638cf82f45bfa1f40a635dfa7b6072e4418c 9ab178464700a19951fc5285acacda4913addee81515d8e072b3d7055935a814 lib/codeql/swift/generated/SynthConstructors.qll 2f801bd8b0db829b0253cd459ed3253c1fdfc55dce68ebc53e7fec138ef0aca4 2f801bd8b0db829b0253cd459ed3253c1fdfc55dce68ebc53e7fec138ef0aca4 lib/codeql/swift/generated/UnknownFile.qll 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 @@ -446,7 +446,7 @@ lib/codeql/swift/generated/expr/BridgeFromObjCExpr.qll b9a6520d01613dfb8c7606177 lib/codeql/swift/generated/expr/BridgeToObjCExpr.qll 31ca13762aee9a6a17746f40ec4e1e929811c81fdadb27c48e0e7ce6a3a6222d 31ca13762aee9a6a17746f40ec4e1e929811c81fdadb27c48e0e7ce6a3a6222d lib/codeql/swift/generated/expr/BuiltinLiteralExpr.qll 052f8d0e9109a0d4496da1ae2b461417951614c88dbc9d80220908734b3f70c6 536fa290bb75deae0517d53528237eab74664958bf7fdbf8041283415dda2142 lib/codeql/swift/generated/expr/CallExpr.qll c7dc105fcb6c0956e20d40f736db35bd7f38f41c3d872858972c2ca120110d36 c7dc105fcb6c0956e20d40f736db35bd7f38f41c3d872858972c2ca120110d36 -lib/codeql/swift/generated/expr/CaptureListExpr.qll 29271af76039bf16aadc5544ab59f06e5689cb92c944f0ed0cf6d23702fcf449 b467850b683f6415edba260065e15c89fb52d0f3ec07f65d526db9f6965694d1 +lib/codeql/swift/generated/expr/CaptureListExpr.qll 61a43bb830403a97ebe41729e87666a4ab4a7343f7f61e8cd94875ee7ca9906e 4c04002502de6cce8b67e0afe84114b81749625da0883bb19a48049d6024b72d lib/codeql/swift/generated/expr/CheckedCastExpr.qll 146c24e72cda519676321d3bdb89d1953dfe1810d2710f04cfdc4210ace24c40 91093e0ba88ec3621b538d98454573b5eea6d43075a2ab0a08f80f9b9be336d3 lib/codeql/swift/generated/expr/ClassMetatypeToObjectExpr.qll 076c0f7369af3fffc8860429bd8e290962bf7fc8cf53bbba061de534e99cc8bf 076c0f7369af3fffc8860429bd8e290962bf7fc8cf53bbba061de534e99cc8bf lib/codeql/swift/generated/expr/ClosureExpr.qll f194fc8c5f67fcf0219e8e2de93ee2b820c27a609b2986b68d57a54445f66b61 3cae87f6c6eefb32195f06bc4c95ff6634446ecf346d3a3c94dc05c1539f3de2 diff --git a/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll index 430ba96fd4fa..8bd7248dc898 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll @@ -1,5 +1,11 @@ private import codeql.swift.generated.expr.CaptureListExpr +private import codeql.swift.elements.decl.VarDecl +private import codeql.swift.elements.pattern.NamedPattern class CaptureListExpr extends Generated::CaptureListExpr { override string toString() { result = this.getClosureBody().toString() } + + override VarDecl getVariable(int index) { + result = this.getBindingDecl(index).getPattern(0).(NamedPattern).getVarDecl() + } } diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index 4a1a4dcbad4c..00693018cf1d 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -1103,11 +1103,6 @@ module Raw { capture_list_expr_binding_decls(this, index, result) } - /** - * Gets the `index`th variable of this capture list expression (0-based). - */ - VarDecl getVariable(int index) { capture_list_expr_variables(this, index, result) } - /** * Gets the closure body of this capture list expression. */ diff --git a/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll index e2aeb2f9ffde..828d99637d8a 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll @@ -32,13 +32,10 @@ module Generated { /** * Gets the `index`th variable of this capture list expression (0-based). + * + * These are the variables introduced by this capture in the closure's scope, not the captured ones. */ - VarDecl getVariable(int index) { - result = - Synth::convertVarDeclFromRaw(Synth::convertCaptureListExprToRaw(this) - .(Raw::CaptureListExpr) - .getVariable(index)) - } + VarDecl getVariable(int index) { none() } /** * Gets any of the variables of this capture list expression. diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index afa3da98ec17..7c17e1f4b2d3 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -846,13 +846,6 @@ capture_list_expr_binding_decls( //dir=expr int binding_decl: @pattern_binding_decl_or_none ref ); -#keyset[id, index] -capture_list_expr_variables( //dir=expr - int id: @capture_list_expr ref, - int index: int ref, - int variable: @var_decl_or_none ref -); - @closure_expr = @auto_closure_expr | @explicit_closure_expr diff --git a/swift/schema.py b/swift/schema.py index b74103a283aa..c46a2e4552d2 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -411,7 +411,9 @@ class CapturedDecl(Decl): class CaptureListExpr(Expr): binding_decls: list[PatternBindingDecl] | child - variables: list[VarDecl] | child + variables: list[VarDecl] | child | synth | desc(""" + These are the variables introduced by this capture in the closure's scope, not the captured ones. + """) closure_body: "ClosureExpr" | child class CollectionExpr(Expr): From aac6cf60eec25107a1c5f6f4e3cde0b067c6b866 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 31 Oct 2023 10:46:12 +0100 Subject: [PATCH 4/6] Swift: add explicative comment --- swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll index 8bd7248dc898..3d2ee41465d6 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll @@ -6,6 +6,7 @@ class CaptureListExpr extends Generated::CaptureListExpr { override string toString() { result = this.getClosureBody().toString() } override VarDecl getVariable(int index) { + // all capture binding declarations consist of a single named pattern result = this.getBindingDecl(index).getPattern(0).(NamedPattern).getVarDecl() } } From 5407b5726101f34ad5ba594ddaaea0b496b39e7f Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 31 Oct 2023 10:57:02 +0100 Subject: [PATCH 5/6] Swift: add change note --- .../change-notes/2023-10-31-capture-list-expr-variables.md | 4 ++++ swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 swift/ql/lib/change-notes/2023-10-31-capture-list-expr-variables.md diff --git a/swift/ql/lib/change-notes/2023-10-31-capture-list-expr-variables.md b/swift/ql/lib/change-notes/2023-10-31-capture-list-expr-variables.md new file mode 100644 index 000000000000..5b1dcfe40442 --- /dev/null +++ b/swift/ql/lib/change-notes/2023-10-31-capture-list-expr-variables.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added indexed `getVariable` to `CaptureListExpr`, improving its AST printing and data flow. diff --git a/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll index 3d2ee41465d6..834684d01730 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll @@ -1,5 +1,4 @@ private import codeql.swift.generated.expr.CaptureListExpr -private import codeql.swift.elements.decl.VarDecl private import codeql.swift.elements.pattern.NamedPattern class CaptureListExpr extends Generated::CaptureListExpr { From ea04b500a3b1a03677be5e3d37926502c81cacc9 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 31 Oct 2023 11:39:25 +0100 Subject: [PATCH 6/6] Swift: tweak dataflow test --- swift/ql/test/library-tests/dataflow/capture/closures.swift | 4 ++-- .../test/library-tests/dataflow/capture/inlinetest.expected | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/swift/ql/test/library-tests/dataflow/capture/closures.swift b/swift/ql/test/library-tests/dataflow/capture/closures.swift index c3fbdbdc13df..8b997357bd65 100644 --- a/swift/ql/test/library-tests/dataflow/capture/closures.swift +++ b/swift/ql/test/library-tests/dataflow/capture/closures.swift @@ -177,8 +177,8 @@ class S { f(source("captureThis", 2)); - sink(bf1); // $ hasValueFlow=captureThis - sink(self.bf2); // $ hasValueFlow=captureThis + sink(bf1); // $ MISSING: hasValueFlow=captureThis + sink(self.bf2); // $ MISSING: hasValueFlow=captureThis } } diff --git a/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected b/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected index d6a9e48c45d2..8ec8033d086e 100644 --- a/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected +++ b/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected @@ -1,4 +1,2 @@ testFailures -| closures.swift:180:16:181:1 | // $ hasValueFlow=captureThis\n | Missing result:hasValueFlow=captureThis | -| closures.swift:181:21:182:1 | // $ hasValueFlow=captureThis\n | Missing result:hasValueFlow=captureThis | failures