From e86ccf8498e7ff40e610da1dfe33c33e4676a985 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Aug 2023 17:06:15 +0100 Subject: [PATCH 001/325] Swift: Test flow through various conversions. --- .../dataflow/taint/core/LocalTaint.expected | 79 ++++++++++++++ .../dataflow/taint/core/Taint.expected | 37 +++++++ .../dataflow/taint/core/conversions.swift | 101 ++++++++++++++++++ 3 files changed, 217 insertions(+) create mode 100644 swift/ql/test/library-tests/dataflow/taint/core/conversions.swift diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected index b7408d1f57e..65fe7171c3f 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected @@ -1,3 +1,82 @@ +| conversions.swift:9:7:9:7 | SSA def(self) | conversions.swift:9:7:9:7 | self[return] | +| conversions.swift:9:7:9:7 | SSA def(self) | conversions.swift:9:7:9:7 | self[return] | +| conversions.swift:9:7:9:7 | self | conversions.swift:9:7:9:7 | SSA def(self) | +| conversions.swift:9:7:9:7 | self | conversions.swift:9:7:9:7 | SSA def(self) | +| conversions.swift:12:7:12:7 | SSA def(self) | conversions.swift:12:7:12:7 | self[return] | +| conversions.swift:12:7:12:7 | self | conversions.swift:12:7:12:7 | SSA def(self) | +| conversions.swift:12:36:12:36 | SSA def(self) | conversions.swift:12:36:12:36 | self[return] | +| conversions.swift:12:36:12:36 | self | conversions.swift:12:36:12:36 | SSA def(self) | +| conversions.swift:15:7:15:7 | SSA def(self) | conversions.swift:15:7:15:7 | self[return] | +| conversions.swift:15:7:15:7 | self | conversions.swift:15:7:15:7 | SSA def(self) | +| conversions.swift:16:11:16:11 | SSA def(self) | conversions.swift:16:11:16:42 | self[return] | +| conversions.swift:16:11:16:11 | self | conversions.swift:16:11:16:11 | SSA def(self) | +| conversions.swift:18:28:18:28 | SSA def(self) | conversions.swift:18:28:18:44 | self[return] | +| conversions.swift:18:28:18:28 | self | conversions.swift:18:28:18:28 | SSA def(self) | +| conversions.swift:19:33:19:33 | SSA def(self) | conversions.swift:19:33:19:49 | self[return] | +| conversions.swift:19:33:19:33 | self | conversions.swift:19:33:19:33 | SSA def(self) | +| conversions.swift:20:22:20:22 | SSA def(self) | conversions.swift:20:22:20:38 | self[return] | +| conversions.swift:20:22:20:22 | self | conversions.swift:20:22:20:22 | SSA def(self) | +| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | +| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 | +| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) | +| conversions.swift:30:20:30:33 | call to sourceString() | conversions.swift:30:20:30:35 | .utf8 | +| conversions.swift:32:9:32:9 | SSA def(v) | conversions.swift:33:13:33:13 | v | +| conversions.swift:32:9:32:9 | v | conversions.swift:32:9:32:9 | SSA def(v) | +| conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:32:5:32:9 | let ...? | +| conversions.swift:36:6:36:6 | SSA def(v2) | conversions.swift:37:12:37:12 | v2 | +| conversions.swift:36:6:36:6 | v2 | conversions.swift:36:6:36:6 | SSA def(v2) | +| conversions.swift:36:6:36:10 | ... as ... | conversions.swift:36:6:36:6 | v2 | +| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:36:6:36:10 | ... as ... | +| conversions.swift:39:6:39:6 | SSA def(v4) | conversions.swift:40:12:40:12 | v4 | +| conversions.swift:39:6:39:6 | v4 | conversions.swift:39:6:39:6 | SSA def(v4) | +| conversions.swift:39:6:39:10 | ... as ... | conversions.swift:39:6:39:6 | v4 | +| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:39:6:39:10 | ... as ... | +| conversions.swift:42:6:42:6 | SSA def(v5) | conversions.swift:43:12:43:12 | v5 | +| conversions.swift:42:6:42:6 | v5 | conversions.swift:42:6:42:6 | SSA def(v5) | +| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:42:6:42:6 | v5 | +| conversions.swift:45:6:45:6 | SSA def(v6) | conversions.swift:46:12:46:12 | v6 | +| conversions.swift:45:6:45:6 | v6 | conversions.swift:45:6:45:6 | SSA def(v6) | +| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:45:6:45:6 | v6 | +| conversions.swift:48:12:48:36 | call to Self.init(exactly:) | conversions.swift:48:12:48:37 | ...! | +| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! | +| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | +| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 | +| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) | +| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | +| conversions.swift:80:6:80:6 | SSA def(ms1) | conversions.swift:81:12:81:12 | ms1 | +| conversions.swift:80:6:80:6 | ms1 | conversions.swift:80:6:80:6 | SSA def(ms1) | +| conversions.swift:80:12:80:26 | call to MyString.init(_:) | conversions.swift:80:12:80:27 | ...! | +| conversions.swift:80:12:80:27 | ...! | conversions.swift:80:6:80:6 | ms1 | +| conversions.swift:81:12:81:12 | [post] ms1 | conversions.swift:82:12:82:12 | ms1 | +| conversions.swift:81:12:81:12 | ms1 | conversions.swift:82:12:82:12 | ms1 | +| conversions.swift:82:12:82:12 | [post] ms1 | conversions.swift:83:12:83:12 | ms1 | +| conversions.swift:82:12:82:12 | ms1 | conversions.swift:83:12:83:12 | ms1 | +| conversions.swift:83:12:83:12 | [post] ms1 | conversions.swift:84:12:84:12 | ms1 | +| conversions.swift:83:12:83:12 | ms1 | conversions.swift:84:12:84:12 | ms1 | +| conversions.swift:86:6:86:6 | SSA def(ms2) | conversions.swift:87:12:87:12 | ms2 | +| conversions.swift:86:6:86:6 | ms2 | conversions.swift:86:6:86:6 | SSA def(ms2) | +| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:36 | ...! | +| conversions.swift:86:12:86:36 | ...! | conversions.swift:86:6:86:6 | ms2 | +| conversions.swift:87:12:87:12 | [post] ms2 | conversions.swift:88:12:88:12 | ms2 | +| conversions.swift:87:12:87:12 | ms2 | conversions.swift:88:12:88:12 | ms2 | +| conversions.swift:88:12:88:12 | [post] ms2 | conversions.swift:89:12:89:12 | ms2 | +| conversions.swift:88:12:88:12 | ms2 | conversions.swift:89:12:89:12 | ms2 | +| conversions.swift:89:12:89:12 | [post] ms2 | conversions.swift:90:12:90:12 | ms2 | +| conversions.swift:89:12:89:12 | ms2 | conversions.swift:90:12:90:12 | ms2 | +| conversions.swift:94:6:94:6 | SSA def(parent) | conversions.swift:95:12:95:12 | parent | +| conversions.swift:94:6:94:6 | parent | conversions.swift:94:6:94:6 | SSA def(parent) | +| conversions.swift:94:6:94:15 | ... as ... | conversions.swift:94:6:94:6 | parent | +| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:94:6:94:15 | ... as ... | +| conversions.swift:95:12:95:12 | [post] parent | conversions.swift:96:12:96:12 | parent | +| conversions.swift:95:12:95:12 | parent | conversions.swift:96:12:96:12 | parent | +| conversions.swift:96:12:96:12 | [post] parent | conversions.swift:98:40:98:40 | parent | +| conversions.swift:96:12:96:12 | parent | conversions.swift:98:40:98:40 | parent | +| conversions.swift:98:6:98:6 | SSA def(v3) | conversions.swift:99:12:99:12 | v3 | +| conversions.swift:98:6:98:6 | v3 | conversions.swift:98:6:98:6 | SSA def(v3) | +| conversions.swift:98:6:98:10 | ... as ... | conversions.swift:98:6:98:6 | v3 | +| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:98:6:98:10 | ... as ... | +| conversions.swift:99:12:99:12 | [post] v3 | conversions.swift:100:12:100:12 | v3 | +| conversions.swift:99:12:99:12 | v3 | conversions.swift:100:12:100:12 | v3 | | simple.swift:12:13:12:13 | 1 | simple.swift:12:13:12:24 | ... .+(_:_:) ... | | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected index 3438ed3afeb..6923c1e8ec1 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected @@ -1,4 +1,13 @@ edges +| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | +| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 | +| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) | +| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | +| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 | +| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) | +| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | +| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | +| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | | file://:0:0:0:0 | self [first] | file://:0:0:0:0 | .first | | file://:0:0:0:0 | self [second] | file://:0:0:0:0 | .second | | file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [first] | @@ -77,6 +86,24 @@ edges | try.swift:18:18:18:25 | call to source() | try.swift:18:18:18:25 | call to source() [some:0] | | try.swift:18:18:18:25 | call to source() [some:0] | try.swift:18:13:18:25 | try? ... [some:0] | nodes +| conversions.swift:24:12:24:22 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:28:12:28:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:28:19:28:29 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:29:12:29:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:29:12:29:32 | .utf8 | semmle.label | .utf8 | +| conversions.swift:29:19:29:29 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:60:12:60:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:63:12:63:32 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:63:19:63:31 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:64:12:64:32 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:64:12:64:34 | .utf8 | semmle.label | .utf8 | +| conversions.swift:64:19:64:31 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:77:12:77:25 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:78:12:78:33 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:78:19:78:32 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:94:31:94:44 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:95:12:95:12 | parent | semmle.label | parent | +| conversions.swift:96:12:96:12 | parent | semmle.label | parent | | file://:0:0:0:0 | .first | semmle.label | .first | | file://:0:0:0:0 | .second | semmle.label | .second | | file://:0:0:0:0 | [post] self [first] | semmle.label | [post] self [first] | @@ -200,6 +227,16 @@ subpaths | stringinterpolation.swift:28:14:28:21 | call to source() | stringinterpolation.swift:7:6:7:6 | value | file://:0:0:0:0 | [post] self [second] | stringinterpolation.swift:28:2:28:2 | [post] p2 [second] | | stringinterpolation.swift:31:21:31:21 | p2 [second] | stringinterpolation.swift:7:6:7:6 | self [second] | file://:0:0:0:0 | .second | stringinterpolation.swift:31:21:31:24 | .second | #select +| conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | result | +| conversions.swift:28:12:28:30 | call to String.init(_:) | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | result | +| conversions.swift:29:12:29:32 | .utf8 | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:32 | .utf8 | result | +| conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | result | +| conversions.swift:63:12:63:32 | call to String.init(_:) | conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | result | +| conversions.swift:64:12:64:34 | .utf8 | conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:34 | .utf8 | result | +| conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | result | +| conversions.swift:78:12:78:33 | call to String.init(_:) | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | result | +| conversions.swift:95:12:95:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | result | +| conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result | | simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result | | simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result | | simple.swift:14:13:14:24 | ... .-(_:_:) ... | simple.swift:14:17:14:24 | call to source() | simple.swift:14:13:14:24 | ... .-(_:_:) ... | result | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift new file mode 100644 index 00000000000..4789486ad45 --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift @@ -0,0 +1,101 @@ + +func sourceInt() -> Int { 0 } +func sourceFloat() -> Float { 0.0 } +func sourceString() -> String { "" } +func sink(arg: Any) { } + +// --- + +class MyParentClass { +} + +class MyChildClass : MyParentClass { +} + +class MyString : LosslessStringConvertible, CustomStringConvertible, CustomDebugStringConvertible { + required init?(_ description: String) { } + + var description: String { get { return "" } } + var debugDescription: String { get { return "" } } + var clean: String { get { return "" } } +} + +func testConversions() { + sink(arg: sourceInt()) // $ tainted=24 + sink(arg: Int(sourceInt())) // $ MISSING: tainted= + sink(arg: UInt8(sourceInt())) // $ MISSING: tainted= + sink(arg: Float(sourceInt())) // $ MISSING: tainted= + sink(arg: String(sourceInt())) // $ tainted=28 + sink(arg: String(sourceInt()).utf8) // $ tainted=29 + sink(arg: [UInt8](sourceString().utf8)) // $ MISSING: tainted= + + if let v = sourceInt() as? UInt { + sink(arg: v) // $ MISSING: tainted= + } + + let v2: UInt8 = numericCast(sourceInt()) + sink(arg: v2) // $ MISSING: tainted= + + let v4: UInt = unsafeBitCast(sourceInt(), to: UInt.self) + sink(arg: v4) // $ MISSING: tainted= + + let v5 = UInt(truncatingIfNeeded: sourceInt()) + sink(arg: v5) // $ MISSING: tainted= + + let v6 = UInt(bitPattern: sourceInt()) + sink(arg: v6) // $ MISSING: tainted= + + sink(arg: Int(exactly: sourceInt())!) // $ MISSING: tainted= + sink(arg: Int(clamping: sourceInt())) // $ MISSING: tainted= + sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ MISSING: tainted= + sink(arg: Int(sourceString(), radix: 10)!) // $ MISSING: tainted= + + sink(arg: Int(littleEndian: sourceInt())) // $ MISSING: tainted= + sink(arg: Int(bigEndian: sourceInt())) // $ MISSING: tainted= + sink(arg: sourceInt().littleEndian) // $ MISSING: tainted= + sink(arg: sourceInt().bigEndian) // $ MISSING: tainted= + + // --- + + sink(arg: sourceFloat()) // $ tainted=60 + sink(arg: Float(sourceFloat())) // $ MISSING: tainted= + sink(arg: UInt8(sourceFloat())) // $ MISSING: tainted= + sink(arg: String(sourceFloat())) // $ tainted=63 + sink(arg: String(sourceFloat()).utf8) // $ tainted=64 + + sink(arg: Float(sourceFloat())) // MISSING: tainted= + sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // MISSING: tainted= + sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // MISSING: tainted= + sink(arg: Float(signOf: sourceFloat(), magnitudeOf: 0.0)) // (good) + sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // MISSING: tainted= + + sink(arg: sourceFloat().exponent) // $ MISSING: tainted= + sink(arg: sourceFloat().significand) // $ MISSING: tainted= + + // --- + + sink(arg: sourceString()) // $ tainted=77 + sink(arg: String(sourceString())) // $ tainted=78 + + let ms1 = MyString("abc")! + sink(arg: ms1) + sink(arg: ms1.description) + sink(arg: ms1.debugDescription) + sink(arg: ms1.clean) + + let ms2 = MyString(sourceString())! + sink(arg: ms2) // $ MISSING: tainted= + sink(arg: ms2.description) // $ MISSING: tainted= + sink(arg: ms2.debugDescription) // $ MISSING: tainted= + sink(arg: ms2.clean) + + // --- + + let parent : MyParentClass = sourceString() as! MyChildClass + sink(arg: parent) // $ tainted=94 + sink(arg: parent as! MyChildClass) // $ tainted=94 + + let v3: MyChildClass = unsafeDowncast(parent, to: MyChildClass.self) + sink(arg: v3) // $ MISSING: tainted= + sink(arg: v3 as! MyParentClass) // $ MISSING: tainted= +} From aa2e79b6da4c1d53efe12c2970703104d9cd99b1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Aug 2023 20:57:43 +0100 Subject: [PATCH 002/325] Swift: Model numeric conversions. --- .../frameworks/StandardLibrary/Numeric.qll | 51 ++++++++ .../StandardLibrary/StandardLibrary.qll | 1 + .../dataflow/taint/core/LocalTaint.expected | 26 ++++ .../dataflow/taint/core/Taint.expected | 114 ++++++++++++++++++ .../dataflow/taint/core/conversions.swift | 50 ++++---- 5 files changed, 217 insertions(+), 25 deletions(-) create mode 100644 swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Numeric.qll diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Numeric.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Numeric.qll new file mode 100644 index 00000000000..a985bb7f0ed --- /dev/null +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Numeric.qll @@ -0,0 +1,51 @@ +/** + * Provides models for `Numeric` and related Swift classes (such as `Int` and `Float`). + */ + +import swift +private import codeql.swift.dataflow.DataFlow +private import codeql.swift.dataflow.ExternalFlow +private import codeql.swift.dataflow.FlowSteps + +/** + * A model for `Numeric` and related class members and functions that permit taint flow. + */ +private class NumericSummaries extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + ";;false;numericCast(_:);;;Argument[0];ReturnValue;taint", + ";;false;unsafeDowncast(_:to:);;;Argument[0];ReturnValue;taint", + ";;false;unsafeBitCast(_:to:);;;Argument[0];ReturnValue;taint", + ";Numeric;true;init(exactly:);;;Argument[0];ReturnValue.OptionalSome;value", + ";Numeric;true;init(bitPattern:);;;Argument[0];ReturnValue;taint", + ";BinaryInteger;true;init(_:);;;Argument[0];ReturnValue;taint", + ";BinaryInteger;true;init(clamping:);;;Argument[0];ReturnValue;taint", + ";BinaryInteger;true;init(truncatingIfNeeded:);;;Argument[0];ReturnValue;taint", + ";BinaryInteger;true;init(_:format:lenient:);;;Argument[0];ReturnValue;taint", + ";BinaryInteger;true;init(_:strategy:);;;Argument[0];ReturnValue;taint", + ";BinaryInteger;true;formatted();;;Argument[-1];ReturnValue;taint", + ";BinaryInteger;true;formatted(_:);;;Argument[-1];ReturnValue;taint", + ";FixedWidthInteger;true;init(_:radix:);;;Argument[0];ReturnValue;taint", + ";FixedWidthInteger;true;init(littleEndian:);;;Argument[0];ReturnValue;taint", + ";FixedWidthInteger;true;init(bigEndian:);;;Argument[0];ReturnValue;taint", + ";FloatingPoint;true;init(_:);;;Argument[0];ReturnValue;taint", + ";FloatingPoint;true;init(sign:exponent:significand:);;;Argument[1..2];ReturnValue;taint", + ";FloatingPoint;true;init(signOf:magnitudeOf:);;;Argument[1];ReturnValue;taint", + ] + } +} + +/** + * A content implying that, if a `Numeric` is tainted, then some of its fields are + * tainted. + */ +private class NumericFieldsInheritTaint extends TaintInheritingContent, + DataFlow::Content::FieldContent +{ + NumericFieldsInheritTaint() { + this.getField().hasQualifiedName("FixedWidthInteger", ["littleEndian", "bigEndian"]) + or + this.getField().hasQualifiedName(["Double", "Float", "Float80", "FloatingPoint"], ["exponent", "significand"]) + } +} diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll index 93d60dba092..775c6afcea0 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll @@ -14,6 +14,7 @@ private import NsData private import NsObject private import NsString private import NsUrl +private import Numeric private import Sequence private import Set private import String diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected index 65fe7171c3f..1ff797add87 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected @@ -16,6 +16,9 @@ | conversions.swift:19:33:19:33 | self | conversions.swift:19:33:19:33 | SSA def(self) | | conversions.swift:20:22:20:22 | SSA def(self) | conversions.swift:20:22:20:38 | self[return] | | conversions.swift:20:22:20:22 | self | conversions.swift:20:22:20:22 | SSA def(self) | +| conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) | +| conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) | +| conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | | conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 | | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) | @@ -27,21 +30,43 @@ | conversions.swift:36:6:36:6 | v2 | conversions.swift:36:6:36:6 | SSA def(v2) | | conversions.swift:36:6:36:10 | ... as ... | conversions.swift:36:6:36:6 | v2 | | conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:36:6:36:10 | ... as ... | +| conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) | | conversions.swift:39:6:39:6 | SSA def(v4) | conversions.swift:40:12:40:12 | v4 | | conversions.swift:39:6:39:6 | v4 | conversions.swift:39:6:39:6 | SSA def(v4) | | conversions.swift:39:6:39:10 | ... as ... | conversions.swift:39:6:39:6 | v4 | | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:39:6:39:10 | ... as ... | +| conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | | conversions.swift:42:6:42:6 | SSA def(v5) | conversions.swift:43:12:43:12 | v5 | | conversions.swift:42:6:42:6 | v5 | conversions.swift:42:6:42:6 | SSA def(v5) | | conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:42:6:42:6 | v5 | +| conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | | conversions.swift:45:6:45:6 | SSA def(v6) | conversions.swift:46:12:46:12 | v6 | | conversions.swift:45:6:45:6 | v6 | conversions.swift:45:6:45:6 | SSA def(v6) | | conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:45:6:45:6 | v6 | +| conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | | conversions.swift:48:12:48:36 | call to Self.init(exactly:) | conversions.swift:48:12:48:37 | ...! | +| conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) | +| conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | | conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! | +| conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | +| conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | +| conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | +| conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian | +| conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian | +| conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) | +| conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) | | conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | | conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 | | conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) | +| conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) | +| conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:67:67:67:67 | 0.0 | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:68:41:68:41 | 0 | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:69:54:69:54 | 0.0 | conversions.swift:69:12:69:57 | call to Float.init(signOf:magnitudeOf:) | +| conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | +| conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent | +| conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | | conversions.swift:80:6:80:6 | SSA def(ms1) | conversions.swift:81:12:81:12 | ms1 | | conversions.swift:80:6:80:6 | ms1 | conversions.swift:80:6:80:6 | SSA def(ms1) | @@ -75,6 +100,7 @@ | conversions.swift:98:6:98:6 | v3 | conversions.swift:98:6:98:6 | SSA def(v3) | | conversions.swift:98:6:98:10 | ... as ... | conversions.swift:98:6:98:6 | v3 | | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:98:6:98:10 | ... as ... | +| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | | conversions.swift:99:12:99:12 | [post] v3 | conversions.swift:100:12:100:12 | v3 | | conversions.swift:99:12:99:12 | v3 | conversions.swift:100:12:100:12 | v3 | | simple.swift:12:13:12:13 | 1 | simple.swift:12:13:12:24 | ... .+(_:_:) ... | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected index 6923c1e8ec1..48ef4ada925 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected @@ -1,13 +1,46 @@ edges +| conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) | +| conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) | +| conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | | conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 | | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) | +| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:37:12:37:12 | v2 | +| conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) | +| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:40:12:40:12 | v4 | +| conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | +| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:43:12:43:12 | v5 | +| conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:46:12:46:12 | v6 | +| conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | +| conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | conversions.swift:48:12:48:37 | ...! | +| conversions.swift:48:25:48:35 | call to sourceInt() | conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | +| conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) | +| conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! | +| conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | +| conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | +| conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | +| conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian | +| conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian | +| conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) | +| conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) | | conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | | conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 | | conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) | +| conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) | +| conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | +| conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent | +| conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | +| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:98:40:98:40 | parent | +| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:99:12:99:12 | v3 | +| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:100:12:100:12 | v3 | +| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | | file://:0:0:0:0 | self [first] | file://:0:0:0:0 | .first | | file://:0:0:0:0 | self [second] | file://:0:0:0:0 | .second | | file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [first] | @@ -87,23 +120,79 @@ edges | try.swift:18:18:18:25 | call to source() [some:0] | try.swift:18:13:18:25 | try? ... [some:0] | nodes | conversions.swift:24:12:24:22 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:25:12:25:27 | call to Self.init(_:) | semmle.label | call to Self.init(_:) | +| conversions.swift:25:16:25:26 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:26:12:26:29 | call to Self.init(_:) | semmle.label | call to Self.init(_:) | +| conversions.swift:26:18:26:28 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:27:12:27:29 | call to Float.init(_:) | semmle.label | call to Float.init(_:) | +| conversions.swift:27:18:27:28 | call to sourceInt() | semmle.label | call to sourceInt() | | conversions.swift:28:12:28:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | | conversions.swift:28:19:28:29 | call to sourceInt() | semmle.label | call to sourceInt() | | conversions.swift:29:12:29:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | | conversions.swift:29:12:29:32 | .utf8 | semmle.label | .utf8 | | conversions.swift:29:19:29:29 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:36:18:36:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) | +| conversions.swift:36:30:36:40 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:37:12:37:12 | v2 | semmle.label | v2 | +| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | semmle.label | call to unsafeBitCast(_:to:) | +| conversions.swift:39:31:39:41 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:40:12:40:12 | v4 | semmle.label | v4 | +| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:42:36:42:46 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:43:12:43:12 | v5 | semmle.label | v5 | +| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | semmle.label | call to UInt.init(bitPattern:) | +| conversions.swift:45:28:45:38 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:46:12:46:12 | v6 | semmle.label | v6 | +| conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | semmle.label | call to Self.init(exactly:) [some:0] | +| conversions.swift:48:12:48:37 | ...! | semmle.label | ...! | +| conversions.swift:48:25:48:35 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:49:12:49:37 | call to Self.init(clamping:) | semmle.label | call to Self.init(clamping:) | +| conversions.swift:49:26:49:36 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:50:36:50:46 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | semmle.label | call to Self.init(_:radix:) | +| conversions.swift:51:12:51:42 | ...! | semmle.label | ...! | +| conversions.swift:51:16:51:29 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | semmle.label | call to Self.init(littleEndian:) | +| conversions.swift:53:30:53:40 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | semmle.label | call to Self.init(bigEndian:) | +| conversions.swift:54:27:54:37 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:55:12:55:22 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:55:12:55:24 | .littleEndian | semmle.label | .littleEndian | +| conversions.swift:56:12:56:22 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:56:12:56:24 | .bigEndian | semmle.label | .bigEndian | | conversions.swift:60:12:60:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:61:12:61:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) | +| conversions.swift:61:18:61:30 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:62:12:62:31 | call to UInt8.init(_:) | semmle.label | call to UInt8.init(_:) | +| conversions.swift:62:18:62:30 | call to sourceFloat() | semmle.label | call to sourceFloat() | | conversions.swift:63:12:63:32 | call to String.init(_:) | semmle.label | call to String.init(_:) | | conversions.swift:63:19:63:31 | call to sourceFloat() | semmle.label | call to sourceFloat() | | conversions.swift:64:12:64:32 | call to String.init(_:) | semmle.label | call to String.init(_:) | | conversions.swift:64:12:64:34 | .utf8 | semmle.label | .utf8 | | conversions.swift:64:19:64:31 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:66:12:66:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) | +| conversions.swift:66:18:66:30 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) | +| conversions.swift:67:41:67:51 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) | +| conversions.swift:68:57:68:69 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | semmle.label | call to Float.init(signOf:magnitudeOf:) | +| conversions.swift:70:44:70:56 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:72:12:72:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:72:12:72:26 | .exponent | semmle.label | .exponent | +| conversions.swift:73:12:73:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:73:12:73:26 | .significand | semmle.label | .significand | | conversions.swift:77:12:77:25 | call to sourceString() | semmle.label | call to sourceString() | | conversions.swift:78:12:78:33 | call to String.init(_:) | semmle.label | call to String.init(_:) | | conversions.swift:78:19:78:32 | call to sourceString() | semmle.label | call to sourceString() | | conversions.swift:94:31:94:44 | call to sourceString() | semmle.label | call to sourceString() | | conversions.swift:95:12:95:12 | parent | semmle.label | parent | | conversions.swift:96:12:96:12 | parent | semmle.label | parent | +| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | semmle.label | call to unsafeDowncast(_:to:) | +| conversions.swift:98:40:98:40 | parent | semmle.label | parent | +| conversions.swift:99:12:99:12 | v3 | semmle.label | v3 | +| conversions.swift:100:12:100:12 | v3 | semmle.label | v3 | | file://:0:0:0:0 | .first | semmle.label | .first | | file://:0:0:0:0 | .second | semmle.label | .second | | file://:0:0:0:0 | [post] self [first] | semmle.label | [post] self [first] | @@ -228,15 +317,40 @@ subpaths | stringinterpolation.swift:31:21:31:21 | p2 [second] | stringinterpolation.swift:7:6:7:6 | self [second] | file://:0:0:0:0 | .second | stringinterpolation.swift:31:21:31:24 | .second | #select | conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | result | +| conversions.swift:25:12:25:27 | call to Self.init(_:) | conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) | result | +| conversions.swift:26:12:26:29 | call to Self.init(_:) | conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) | result | +| conversions.swift:27:12:27:29 | call to Float.init(_:) | conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | result | | conversions.swift:28:12:28:30 | call to String.init(_:) | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | result | | conversions.swift:29:12:29:32 | .utf8 | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:32 | .utf8 | result | +| conversions.swift:37:12:37:12 | v2 | conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:37:12:37:12 | v2 | result | +| conversions.swift:40:12:40:12 | v4 | conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:40:12:40:12 | v4 | result | +| conversions.swift:43:12:43:12 | v5 | conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:43:12:43:12 | v5 | result | +| conversions.swift:46:12:46:12 | v6 | conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:46:12:46:12 | v6 | result | +| conversions.swift:48:12:48:37 | ...! | conversions.swift:48:25:48:35 | call to sourceInt() | conversions.swift:48:12:48:37 | ...! | result | +| conversions.swift:49:12:49:37 | call to Self.init(clamping:) | conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) | result | +| conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | result | +| conversions.swift:51:12:51:42 | ...! | conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:42 | ...! | result | +| conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | result | +| conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | result | +| conversions.swift:55:12:55:24 | .littleEndian | conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian | result | +| conversions.swift:56:12:56:24 | .bigEndian | conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian | result | | conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | result | +| conversions.swift:61:12:61:31 | call to Float.init(_:) | conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) | result | +| conversions.swift:62:12:62:31 | call to UInt8.init(_:) | conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) | result | | conversions.swift:63:12:63:32 | call to String.init(_:) | conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | result | | conversions.swift:64:12:64:34 | .utf8 | conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:34 | .utf8 | result | +| conversions.swift:66:12:66:31 | call to Float.init(_:) | conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) | result | +| conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | result | +| conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | result | +| conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | result | +| conversions.swift:72:12:72:26 | .exponent | conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent | result | +| conversions.swift:73:12:73:26 | .significand | conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | result | | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | result | | conversions.swift:78:12:78:33 | call to String.init(_:) | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | result | | conversions.swift:95:12:95:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | result | | conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result | +| conversions.swift:99:12:99:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:99:12:99:12 | v3 | result | +| conversions.swift:100:12:100:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:100:12:100:12 | v3 | result | | simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result | | simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result | | simple.swift:14:13:14:24 | ... .-(_:_:) ... | simple.swift:14:17:14:24 | call to source() | simple.swift:14:13:14:24 | ... .-(_:_:) ... | result | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift index 4789486ad45..a4d8956dff1 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift +++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift @@ -22,9 +22,9 @@ class MyString : LosslessStringConvertible, CustomStringConvertible, CustomDebug func testConversions() { sink(arg: sourceInt()) // $ tainted=24 - sink(arg: Int(sourceInt())) // $ MISSING: tainted= - sink(arg: UInt8(sourceInt())) // $ MISSING: tainted= - sink(arg: Float(sourceInt())) // $ MISSING: tainted= + sink(arg: Int(sourceInt())) // $ tainted=25 + sink(arg: UInt8(sourceInt())) // $ tainted=26 + sink(arg: Float(sourceInt())) // $ tainted=27 sink(arg: String(sourceInt())) // $ tainted=28 sink(arg: String(sourceInt()).utf8) // $ tainted=29 sink(arg: [UInt8](sourceString().utf8)) // $ MISSING: tainted= @@ -34,43 +34,43 @@ func testConversions() { } let v2: UInt8 = numericCast(sourceInt()) - sink(arg: v2) // $ MISSING: tainted= + sink(arg: v2) // $ tainted=36 let v4: UInt = unsafeBitCast(sourceInt(), to: UInt.self) - sink(arg: v4) // $ MISSING: tainted= + sink(arg: v4) // $ tainted=39 let v5 = UInt(truncatingIfNeeded: sourceInt()) - sink(arg: v5) // $ MISSING: tainted= + sink(arg: v5) // $ tainted=42 let v6 = UInt(bitPattern: sourceInt()) - sink(arg: v6) // $ MISSING: tainted= + sink(arg: v6) // $ tainted=45 - sink(arg: Int(exactly: sourceInt())!) // $ MISSING: tainted= - sink(arg: Int(clamping: sourceInt())) // $ MISSING: tainted= - sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ MISSING: tainted= - sink(arg: Int(sourceString(), radix: 10)!) // $ MISSING: tainted= + sink(arg: Int(exactly: sourceInt())!) // $ tainted=48 + sink(arg: Int(clamping: sourceInt())) // $ tainted=49 + sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ tainted=50 + sink(arg: Int(sourceString(), radix: 10)!) // $ tainted=51 - sink(arg: Int(littleEndian: sourceInt())) // $ MISSING: tainted= - sink(arg: Int(bigEndian: sourceInt())) // $ MISSING: tainted= - sink(arg: sourceInt().littleEndian) // $ MISSING: tainted= - sink(arg: sourceInt().bigEndian) // $ MISSING: tainted= + sink(arg: Int(littleEndian: sourceInt())) // $ tainted=53 + sink(arg: Int(bigEndian: sourceInt())) // $ tainted=54 + sink(arg: sourceInt().littleEndian) // $ tainted=55 + sink(arg: sourceInt().bigEndian) // $ tainted=56 // --- sink(arg: sourceFloat()) // $ tainted=60 - sink(arg: Float(sourceFloat())) // $ MISSING: tainted= - sink(arg: UInt8(sourceFloat())) // $ MISSING: tainted= + sink(arg: Float(sourceFloat())) // $ tainted=61 + sink(arg: UInt8(sourceFloat())) // $ tainted=62 sink(arg: String(sourceFloat())) // $ tainted=63 sink(arg: String(sourceFloat()).utf8) // $ tainted=64 - sink(arg: Float(sourceFloat())) // MISSING: tainted= - sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // MISSING: tainted= - sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // MISSING: tainted= + sink(arg: Float(sourceFloat())) // $ tainted=66 + sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // $ tainted=67 + sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // $ tainted=68 sink(arg: Float(signOf: sourceFloat(), magnitudeOf: 0.0)) // (good) - sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // MISSING: tainted= + sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // $ tainted=70 - sink(arg: sourceFloat().exponent) // $ MISSING: tainted= - sink(arg: sourceFloat().significand) // $ MISSING: tainted= + sink(arg: sourceFloat().exponent) // $ tainted=72 + sink(arg: sourceFloat().significand) // $ tainted=73 // --- @@ -96,6 +96,6 @@ func testConversions() { sink(arg: parent as! MyChildClass) // $ tainted=94 let v3: MyChildClass = unsafeDowncast(parent, to: MyChildClass.self) - sink(arg: v3) // $ MISSING: tainted= - sink(arg: v3 as! MyParentClass) // $ MISSING: tainted= + sink(arg: v3) // $ tainted=94 + sink(arg: v3 as! MyParentClass) // $ tainted=94 } From effe3762b8cf0cbcd326d742bd885655d0197538 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Aug 2023 17:25:56 +0100 Subject: [PATCH 003/325] Swift: More robust OptionalSomePattern flow. --- .../lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll | 5 +++++ .../library-tests/dataflow/taint/core/LocalTaint.expected | 1 + .../ql/test/library-tests/dataflow/taint/core/Taint.expected | 4 ++++ .../test/library-tests/dataflow/taint/core/conversions.swift | 2 +- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index 145ac20573b..0ddd5728e52 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -182,6 +182,11 @@ private module Cached { // retaining this case increases robustness of flow). nodeFrom.asExpr() = nodeTo.asExpr().(ForceValueExpr).getSubExpr() or + // read of an optional .some member via `let x: T = y: T?` pattern matching + // note: similar to `ForceValueExpr` this is ideally a content `readStep` but + // in practice we sometimes have taint on the optional itself. + nodeTo.asPattern() = nodeFrom.asPattern().(OptionalSomePattern).getSubPattern() + or // flow through `?` and `?.` nodeFrom.asExpr() = nodeTo.asExpr().(BindOptionalExpr).getSubExpr() or diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected index 1ff797add87..40862be951d 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected @@ -23,6 +23,7 @@ | conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 | | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) | | conversions.swift:30:20:30:33 | call to sourceString() | conversions.swift:30:20:30:35 | .utf8 | +| conversions.swift:32:5:32:9 | let ...? | conversions.swift:32:9:32:9 | v | | conversions.swift:32:9:32:9 | SSA def(v) | conversions.swift:33:13:33:13 | v | | conversions.swift:32:9:32:9 | v | conversions.swift:32:9:32:9 | SSA def(v) | | conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:32:5:32:9 | let ...? | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected index 48ef4ada925..e2c7100da5c 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected @@ -5,6 +5,7 @@ edges | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | | conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 | | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) | +| conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:33:13:33:13 | v | | conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:37:12:37:12 | v2 | | conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) | | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:40:12:40:12 | v4 | @@ -131,6 +132,8 @@ nodes | conversions.swift:29:12:29:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | | conversions.swift:29:12:29:32 | .utf8 | semmle.label | .utf8 | | conversions.swift:29:19:29:29 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:32:13:32:23 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:33:13:33:13 | v | semmle.label | v | | conversions.swift:36:18:36:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) | | conversions.swift:36:30:36:40 | call to sourceInt() | semmle.label | call to sourceInt() | | conversions.swift:37:12:37:12 | v2 | semmle.label | v2 | @@ -322,6 +325,7 @@ subpaths | conversions.swift:27:12:27:29 | call to Float.init(_:) | conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | result | | conversions.swift:28:12:28:30 | call to String.init(_:) | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | result | | conversions.swift:29:12:29:32 | .utf8 | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:32 | .utf8 | result | +| conversions.swift:33:13:33:13 | v | conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:33:13:33:13 | v | result | | conversions.swift:37:12:37:12 | v2 | conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:37:12:37:12 | v2 | result | | conversions.swift:40:12:40:12 | v4 | conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:40:12:40:12 | v4 | result | | conversions.swift:43:12:43:12 | v5 | conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:43:12:43:12 | v5 | result | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift index a4d8956dff1..b9a7ad6ad5c 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift +++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift @@ -30,7 +30,7 @@ func testConversions() { sink(arg: [UInt8](sourceString().utf8)) // $ MISSING: tainted= if let v = sourceInt() as? UInt { - sink(arg: v) // $ MISSING: tainted= + sink(arg: v) // $ tainted=32 } let v2: UInt8 = numericCast(sourceInt()) From 376479325de840bb4665994256ccb936fcd3f9ba Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 10 Aug 2023 09:27:05 +0100 Subject: [PATCH 004/325] Swift: Model LosslessStringConvertible. --- .../swift/frameworks/StandardLibrary/String.qll | 5 +++-- .../dataflow/taint/core/LocalTaint.expected | 3 +++ .../library-tests/dataflow/taint/core/Taint.expected | 11 +++++++++++ .../dataflow/taint/core/conversions.swift | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll index 4768521322f..65b1f23ad94 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll @@ -27,7 +27,7 @@ private class StringSource extends SourceModelCsv { } /** - * A model for `String` and `StringProtocol` members that permit taint flow. + * A model for members of `String`, `StringProtocol` and similar classes that permit taint flow. */ private class StringSummaries extends SummaryModelCsv { override predicate row(string row) { @@ -111,7 +111,8 @@ private class StringSummaries extends SummaryModelCsv { ";String;true;randomElement();;;Argument[-1];ReturnValue;taint", ";String;true;randomElement(using:);;;Argument[-1];ReturnValue;taint", ";String;true;enumerated();;;Argument[-1];ReturnValue;taint", - ";String;true;encode(to:);;;Argument[-1];Argument[0];taint" + ";String;true;encode(to:);;;Argument[-1];Argument[0];taint", + ";LosslessStringConvertible;true;init(_:);;;Argument[0];ReturnValue;taint", ] } } diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected index 40862be951d..6fd724f31ad 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected @@ -10,6 +10,7 @@ | conversions.swift:15:7:15:7 | self | conversions.swift:15:7:15:7 | SSA def(self) | | conversions.swift:16:11:16:11 | SSA def(self) | conversions.swift:16:11:16:42 | self[return] | | conversions.swift:16:11:16:11 | self | conversions.swift:16:11:16:11 | SSA def(self) | +| conversions.swift:16:11:16:42 | [summary param] 0 in MyString.init(_:) | conversions.swift:16:11:16:42 | [summary] to write: ReturnValue in MyString.init(_:) | | conversions.swift:18:28:18:28 | SSA def(self) | conversions.swift:18:28:18:44 | self[return] | | conversions.swift:18:28:18:28 | self | conversions.swift:18:28:18:28 | SSA def(self) | | conversions.swift:19:33:19:33 | SSA def(self) | conversions.swift:19:33:19:49 | self[return] | @@ -73,6 +74,7 @@ | conversions.swift:80:6:80:6 | ms1 | conversions.swift:80:6:80:6 | SSA def(ms1) | | conversions.swift:80:12:80:26 | call to MyString.init(_:) | conversions.swift:80:12:80:27 | ...! | | conversions.swift:80:12:80:27 | ...! | conversions.swift:80:6:80:6 | ms1 | +| conversions.swift:80:21:80:21 | abc | conversions.swift:80:12:80:26 | call to MyString.init(_:) | | conversions.swift:81:12:81:12 | [post] ms1 | conversions.swift:82:12:82:12 | ms1 | | conversions.swift:81:12:81:12 | ms1 | conversions.swift:82:12:82:12 | ms1 | | conversions.swift:82:12:82:12 | [post] ms1 | conversions.swift:83:12:83:12 | ms1 | @@ -83,6 +85,7 @@ | conversions.swift:86:6:86:6 | ms2 | conversions.swift:86:6:86:6 | SSA def(ms2) | | conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:36 | ...! | | conversions.swift:86:12:86:36 | ...! | conversions.swift:86:6:86:6 | ms2 | +| conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:86:12:86:35 | call to MyString.init(_:) | | conversions.swift:87:12:87:12 | [post] ms2 | conversions.swift:88:12:88:12 | ms2 | | conversions.swift:87:12:87:12 | ms2 | conversions.swift:88:12:88:12 | ms2 | | conversions.swift:88:12:88:12 | [post] ms2 | conversions.swift:89:12:89:12 | ms2 | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected index e2c7100da5c..25b8d79aa68 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected @@ -36,6 +36,11 @@ edges | conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent | | conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | +| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | +| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:87:12:87:12 | ms2 | +| conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | conversions.swift:86:12:86:36 | ...! | +| conversions.swift:86:12:86:36 | ...! | conversions.swift:87:12:87:12 | ms2 | +| conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:86:12:86:35 | call to MyString.init(_:) | | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:98:40:98:40 | parent | @@ -189,6 +194,11 @@ nodes | conversions.swift:77:12:77:25 | call to sourceString() | semmle.label | call to sourceString() | | conversions.swift:78:12:78:33 | call to String.init(_:) | semmle.label | call to String.init(_:) | | conversions.swift:78:19:78:32 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:86:12:86:35 | call to MyString.init(_:) | semmle.label | call to MyString.init(_:) | +| conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | semmle.label | call to MyString.init(_:) [some:0] | +| conversions.swift:86:12:86:36 | ...! | semmle.label | ...! | +| conversions.swift:86:21:86:34 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:87:12:87:12 | ms2 | semmle.label | ms2 | | conversions.swift:94:31:94:44 | call to sourceString() | semmle.label | call to sourceString() | | conversions.swift:95:12:95:12 | parent | semmle.label | parent | | conversions.swift:96:12:96:12 | parent | semmle.label | parent | @@ -351,6 +361,7 @@ subpaths | conversions.swift:73:12:73:26 | .significand | conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | result | | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | result | | conversions.swift:78:12:78:33 | call to String.init(_:) | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | result | +| conversions.swift:87:12:87:12 | ms2 | conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:87:12:87:12 | ms2 | result | | conversions.swift:95:12:95:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | result | | conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result | | conversions.swift:99:12:99:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:99:12:99:12 | v3 | result | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift index b9a7ad6ad5c..499ec8dcfe2 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift +++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift @@ -84,7 +84,7 @@ func testConversions() { sink(arg: ms1.clean) let ms2 = MyString(sourceString())! - sink(arg: ms2) // $ MISSING: tainted= + sink(arg: ms2) // $ tainted=86 sink(arg: ms2.description) // $ MISSING: tainted= sink(arg: ms2.debugDescription) // $ MISSING: tainted= sink(arg: ms2.clean) From 936b1ced4d9bbc3c4404e6bbfe0b28d8f9de3102 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 10 Aug 2023 19:24:30 +0100 Subject: [PATCH 005/325] Swift: Add one last test case (and address a .expected change elsewhere). --- .../library-tests/dataflow/taint/core/conversions.swift | 8 ++++++++ .../library-tests/dataflow/taint/libraries/string.swift | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift index 499ec8dcfe2..321c555e0ab 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift +++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift @@ -99,3 +99,11 @@ func testConversions() { sink(arg: v3) // $ tainted=94 sink(arg: v3 as! MyParentClass) // $ tainted=94 } + +var myCEnumConst : Int = 0 +typealias MyCEnumType = UInt32 + +func testCEnum() { + sink(arg: MyCEnumType(myCEnumConst)) + sink(arg: MyCEnumType(sourceInt())) // $ tainted=108 +} diff --git a/swift/ql/test/library-tests/dataflow/taint/libraries/string.swift b/swift/ql/test/library-tests/dataflow/taint/libraries/string.swift index 9f684139fd3..919a07b6675 100644 --- a/swift/ql/test/library-tests/dataflow/taint/libraries/string.swift +++ b/swift/ql/test/library-tests/dataflow/taint/libraries/string.swift @@ -589,7 +589,7 @@ func taintedThroughConversion() { sink(arg: String(describing: source())) // $ tainted=589 sink(arg: Int("123")!) - sink(arg: Int(source2())!) // $ MISSING: tainted=592 + sink(arg: Int(source2())!) // $ tainted=592 } func untaintedFields() { From 4f5d7e1b6f33ca95a2a0a69bbca84a7ac275ccd9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 10 Aug 2023 19:49:27 +0100 Subject: [PATCH 006/325] Swift: Accept test changes. --- .../dataflow/dataflow/DataFlow.expected | 31 +++++++++++++++++++ .../dataflow/dataflow/LocalFlow.expected | 11 +++++++ .../dataflow/taint/core/LocalTaint.expected | 2 ++ .../dataflow/taint/core/Taint.expected | 4 +++ 4 files changed, 48 insertions(+) diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected index b0404de37ec..77530c3af28 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected @@ -6,9 +6,11 @@ edges | file://:0:0:0:0 | self [v3] | file://:0:0:0:0 | .v3 | | file://:0:0:0:0 | self [x, some:0] | file://:0:0:0:0 | .x [some:0] | | file://:0:0:0:0 | self [x] | file://:0:0:0:0 | .x | +| file://:0:0:0:0 | self [x] | file://:0:0:0:0 | .x | | file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v2] | | file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v3] | | file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [x] | +| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [x] | | file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [v2, some:0] | | file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [x, some:0] | | test.swift:6:19:6:26 | call to source() | test.swift:7:15:7:15 | t1 | @@ -109,6 +111,8 @@ edges | test.swift:225:14:225:21 | call to source() | test.swift:238:13:238:15 | .source_value | | test.swift:259:12:259:19 | call to source() | test.swift:259:12:259:19 | call to source() [some:0] | | test.swift:259:12:259:19 | call to source() | test.swift:263:13:263:28 | call to optionalSource() | +| test.swift:259:12:259:19 | call to source() | test.swift:517:13:517:28 | call to optionalSource() | +| test.swift:259:12:259:19 | call to source() | test.swift:544:13:544:28 | call to optionalSource() | | test.swift:259:12:259:19 | call to source() [some:0] | test.swift:263:13:263:28 | call to optionalSource() [some:0] | | test.swift:259:12:259:19 | call to source() [some:0] | test.swift:517:13:517:28 | call to optionalSource() [some:0] | | test.swift:259:12:259:19 | call to source() [some:0] | test.swift:544:13:544:28 | call to optionalSource() [some:0] | @@ -119,7 +123,9 @@ edges | test.swift:263:13:263:28 | call to optionalSource() | test.swift:275:15:275:27 | ... ??(_:_:) ... | | test.swift:263:13:263:28 | call to optionalSource() | test.swift:279:15:279:31 | ... ? ... : ... | | test.swift:263:13:263:28 | call to optionalSource() | test.swift:280:15:280:38 | ... ? ... : ... | +| test.swift:263:13:263:28 | call to optionalSource() | test.swift:285:19:285:19 | z | | test.swift:263:13:263:28 | call to optionalSource() | test.swift:291:16:291:17 | ...? | +| test.swift:263:13:263:28 | call to optionalSource() | test.swift:300:15:300:15 | z1 | | test.swift:263:13:263:28 | call to optionalSource() | test.swift:303:15:303:16 | ...! | | test.swift:263:13:263:28 | call to optionalSource() [some:0] | test.swift:267:15:267:15 | x [some:0] | | test.swift:263:13:263:28 | call to optionalSource() [some:0] | test.swift:279:26:279:26 | x [some:0] | @@ -147,6 +153,7 @@ edges | test.swift:291:16:291:17 | ...? | test.swift:291:16:291:26 | call to signum() | | test.swift:291:16:291:17 | ...? [some:0] | test.swift:291:16:291:26 | call to signum() [some:0] | | test.swift:291:16:291:26 | call to signum() | test.swift:291:16:291:26 | call to signum() [some:0] | +| test.swift:291:16:291:26 | call to signum() | test.swift:292:19:292:19 | z | | test.swift:291:16:291:26 | call to signum() [some:0] | test.swift:291:8:291:12 | let ...? [some:0] | | test.swift:298:11:298:15 | let ...? [some:0] | test.swift:298:15:298:15 | z1 | | test.swift:298:15:298:15 | z1 | test.swift:300:15:300:15 | z1 | @@ -246,6 +253,7 @@ edges | test.swift:507:15:507:15 | e2 [some:0] | test.swift:507:15:507:17 | ...! | | test.swift:509:15:509:15 | e4 [some:0] | test.swift:509:15:509:17 | ...! | | test.swift:511:15:511:15 | e6 [some:0] | test.swift:511:15:511:17 | ...! | +| test.swift:517:13:517:28 | call to optionalSource() | test.swift:520:19:520:19 | a | | test.swift:517:13:517:28 | call to optionalSource() [some:0] | test.swift:519:8:519:12 | let ...? [some:0] | | test.swift:517:13:517:28 | call to optionalSource() [some:0] | test.swift:524:19:524:19 | x [some:0] | | test.swift:519:8:519:12 | let ...? [some:0] | test.swift:519:12:519:12 | a | @@ -256,15 +264,24 @@ edges | test.swift:526:11:526:22 | .some(...) [some:0] | test.swift:526:21:526:21 | a | | test.swift:526:21:526:21 | a | test.swift:527:19:527:19 | a | | test.swift:540:9:540:9 | self [x, some:0] | file://:0:0:0:0 | self [x, some:0] | +| test.swift:540:9:540:9 | self [x] | file://:0:0:0:0 | self [x] | +| test.swift:540:9:540:9 | value | file://:0:0:0:0 | value | | test.swift:540:9:540:9 | value [some:0] | file://:0:0:0:0 | value [some:0] | +| test.swift:544:13:544:28 | call to optionalSource() | test.swift:546:12:546:12 | x | | test.swift:544:13:544:28 | call to optionalSource() [some:0] | test.swift:546:12:546:12 | x [some:0] | | test.swift:546:5:546:5 | [post] cx [x, some:0] | test.swift:550:20:550:20 | cx [x, some:0] | +| test.swift:546:5:546:5 | [post] cx [x] | test.swift:550:20:550:20 | cx [x] | +| test.swift:546:12:546:12 | x | test.swift:540:9:540:9 | value | +| test.swift:546:12:546:12 | x | test.swift:546:5:546:5 | [post] cx [x] | | test.swift:546:12:546:12 | x [some:0] | test.swift:540:9:540:9 | value [some:0] | | test.swift:546:12:546:12 | x [some:0] | test.swift:546:5:546:5 | [post] cx [x, some:0] | | test.swift:550:11:550:15 | let ...? [some:0] | test.swift:550:15:550:15 | z1 | | test.swift:550:15:550:15 | z1 | test.swift:551:15:551:15 | z1 | | test.swift:550:20:550:20 | cx [x, some:0] | test.swift:540:9:540:9 | self [x, some:0] | | test.swift:550:20:550:20 | cx [x, some:0] | test.swift:550:20:550:23 | .x [some:0] | +| test.swift:550:20:550:20 | cx [x] | test.swift:540:9:540:9 | self [x] | +| test.swift:550:20:550:20 | cx [x] | test.swift:550:20:550:23 | .x | +| test.swift:550:20:550:23 | .x | test.swift:551:15:551:15 | z1 | | test.swift:550:20:550:23 | .x [some:0] | test.swift:550:11:550:15 | let ...? [some:0] | | test.swift:557:14:557:21 | call to source() | test.swift:557:13:557:21 | call to +(_:) | | test.swift:566:9:566:9 | self [str] | file://:0:0:0:0 | self [str] | @@ -396,12 +413,14 @@ nodes | file://:0:0:0:0 | .v2 [some:0] | semmle.label | .v2 [some:0] | | file://:0:0:0:0 | .v3 | semmle.label | .v3 | | file://:0:0:0:0 | .x | semmle.label | .x | +| file://:0:0:0:0 | .x | semmle.label | .x | | file://:0:0:0:0 | .x [some:0] | semmle.label | .x [some:0] | | file://:0:0:0:0 | [post] self [v2, some:0] | semmle.label | [post] self [v2, some:0] | | file://:0:0:0:0 | [post] self [v2] | semmle.label | [post] self [v2] | | file://:0:0:0:0 | [post] self [v3] | semmle.label | [post] self [v3] | | file://:0:0:0:0 | [post] self [x, some:0] | semmle.label | [post] self [x, some:0] | | file://:0:0:0:0 | [post] self [x] | semmle.label | [post] self [x] | +| file://:0:0:0:0 | [post] self [x] | semmle.label | [post] self [x] | | file://:0:0:0:0 | self [a, x] | semmle.label | self [a, x] | | file://:0:0:0:0 | self [str] | semmle.label | self [str] | | file://:0:0:0:0 | self [v2, some:0] | semmle.label | self [v2, some:0] | @@ -409,6 +428,8 @@ nodes | file://:0:0:0:0 | self [v3] | semmle.label | self [v3] | | file://:0:0:0:0 | self [x, some:0] | semmle.label | self [x, some:0] | | file://:0:0:0:0 | self [x] | semmle.label | self [x] | +| file://:0:0:0:0 | self [x] | semmle.label | self [x] | +| file://:0:0:0:0 | value | semmle.label | value | | file://:0:0:0:0 | value | semmle.label | value | | file://:0:0:0:0 | value | semmle.label | value | | file://:0:0:0:0 | value | semmle.label | value | @@ -665,6 +686,7 @@ nodes | test.swift:509:15:509:17 | ...! | semmle.label | ...! | | test.swift:511:15:511:15 | e6 [some:0] | semmle.label | e6 [some:0] | | test.swift:511:15:511:17 | ...! | semmle.label | ...! | +| test.swift:517:13:517:28 | call to optionalSource() | semmle.label | call to optionalSource() | | test.swift:517:13:517:28 | call to optionalSource() [some:0] | semmle.label | call to optionalSource() [some:0] | | test.swift:519:8:519:12 | let ...? [some:0] | semmle.label | let ...? [some:0] | | test.swift:519:12:519:12 | a | semmle.label | a | @@ -676,13 +698,20 @@ nodes | test.swift:526:21:526:21 | a | semmle.label | a | | test.swift:527:19:527:19 | a | semmle.label | a | | test.swift:540:9:540:9 | self [x, some:0] | semmle.label | self [x, some:0] | +| test.swift:540:9:540:9 | self [x] | semmle.label | self [x] | +| test.swift:540:9:540:9 | value | semmle.label | value | | test.swift:540:9:540:9 | value [some:0] | semmle.label | value [some:0] | +| test.swift:544:13:544:28 | call to optionalSource() | semmle.label | call to optionalSource() | | test.swift:544:13:544:28 | call to optionalSource() [some:0] | semmle.label | call to optionalSource() [some:0] | | test.swift:546:5:546:5 | [post] cx [x, some:0] | semmle.label | [post] cx [x, some:0] | +| test.swift:546:5:546:5 | [post] cx [x] | semmle.label | [post] cx [x] | +| test.swift:546:12:546:12 | x | semmle.label | x | | test.swift:546:12:546:12 | x [some:0] | semmle.label | x [some:0] | | test.swift:550:11:550:15 | let ...? [some:0] | semmle.label | let ...? [some:0] | | test.swift:550:15:550:15 | z1 | semmle.label | z1 | | test.swift:550:20:550:20 | cx [x, some:0] | semmle.label | cx [x, some:0] | +| test.swift:550:20:550:20 | cx [x] | semmle.label | cx [x] | +| test.swift:550:20:550:23 | .x | semmle.label | .x | | test.swift:550:20:550:23 | .x [some:0] | semmle.label | .x [some:0] | | test.swift:551:15:551:15 | z1 | semmle.label | z1 | | test.swift:557:13:557:21 | call to +(_:) | semmle.label | call to +(_:) | @@ -846,8 +875,10 @@ subpaths | test.swift:219:13:219:15 | .a [x] | test.swift:163:7:163:7 | self [x] | file://:0:0:0:0 | .x | test.swift:219:13:219:17 | .x | | test.swift:490:24:490:31 | call to source() | test.swift:375:16:375:21 | v | test.swift:375:45:375:62 | call to ... [mySingle:0] | test.swift:490:14:490:32 | call to mkMyEnum1(_:) [mySingle:0] | | test.swift:503:26:503:33 | call to source() | test.swift:377:18:377:23 | v | test.swift:377:45:377:60 | call to ... [some:0] | test.swift:503:14:503:34 | call to mkOptional1(_:) [some:0] | +| test.swift:546:12:546:12 | x | test.swift:540:9:540:9 | value | file://:0:0:0:0 | [post] self [x] | test.swift:546:5:546:5 | [post] cx [x] | | test.swift:546:12:546:12 | x [some:0] | test.swift:540:9:540:9 | value [some:0] | file://:0:0:0:0 | [post] self [x, some:0] | test.swift:546:5:546:5 | [post] cx [x, some:0] | | test.swift:550:20:550:20 | cx [x, some:0] | test.swift:540:9:540:9 | self [x, some:0] | file://:0:0:0:0 | .x [some:0] | test.swift:550:20:550:23 | .x [some:0] | +| test.swift:550:20:550:20 | cx [x] | test.swift:540:9:540:9 | self [x] | file://:0:0:0:0 | .x | test.swift:550:20:550:23 | .x | | test.swift:574:20:574:28 | call to source3() | test.swift:567:10:567:13 | s | test.swift:568:7:568:7 | [post] self [str] | test.swift:574:7:574:7 | [post] self [str] | | test.swift:580:13:580:33 | call to MyClass.init(s:) [str] | test.swift:566:9:566:9 | self [str] | file://:0:0:0:0 | .str | test.swift:580:13:580:35 | .str | | test.swift:580:24:580:32 | call to source3() | test.swift:567:10:567:13 | s | test.swift:567:5:569:5 | self[return] [str] | test.swift:580:13:580:33 | call to MyClass.init(s:) [str] | diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected index 6058e6e645b..b583c64cdca 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected @@ -281,30 +281,36 @@ | test.swift:282:26:282:26 | y | test.swift:287:16:287:16 | y | | test.swift:282:26:282:27 | ...! | test.swift:282:15:282:38 | ... ? ... : ... | | test.swift:282:31:282:38 | call to source() | test.swift:282:15:282:38 | ... ? ... : ... | +| test.swift:284:8:284:12 | let ...? | test.swift:284:12:284:12 | z | | test.swift:284:12:284:12 | SSA def(z) | test.swift:285:19:285:19 | z | | test.swift:284:12:284:12 | z | test.swift:284:12:284:12 | SSA def(z) | | test.swift:284:16:284:16 | x | test.swift:284:8:284:12 | let ...? | | test.swift:284:16:284:16 | x | test.swift:291:16:291:16 | x | +| test.swift:287:8:287:12 | let ...? | test.swift:287:12:287:12 | z | | test.swift:287:12:287:12 | SSA def(z) | test.swift:288:19:288:19 | z | | test.swift:287:12:287:12 | z | test.swift:287:12:287:12 | SSA def(z) | | test.swift:287:16:287:16 | y | test.swift:287:8:287:12 | let ...? | | test.swift:287:16:287:16 | y | test.swift:294:16:294:16 | y | +| test.swift:291:8:291:12 | let ...? | test.swift:291:12:291:12 | z | | test.swift:291:12:291:12 | SSA def(z) | test.swift:292:19:292:19 | z | | test.swift:291:12:291:12 | z | test.swift:291:12:291:12 | SSA def(z) | | test.swift:291:16:291:16 | x | test.swift:291:16:291:17 | ...? | | test.swift:291:16:291:16 | x | test.swift:298:20:298:20 | x | | test.swift:291:16:291:26 | OptionalEvaluationExpr | test.swift:291:8:291:12 | let ...? | | test.swift:291:16:291:26 | call to signum() | test.swift:291:16:291:26 | OptionalEvaluationExpr | +| test.swift:294:8:294:12 | let ...? | test.swift:294:12:294:12 | z | | test.swift:294:12:294:12 | SSA def(z) | test.swift:295:19:295:19 | z | | test.swift:294:12:294:12 | z | test.swift:294:12:294:12 | SSA def(z) | | test.swift:294:16:294:16 | y | test.swift:294:16:294:17 | ...? | | test.swift:294:16:294:16 | y | test.swift:299:20:299:20 | y | | test.swift:294:16:294:26 | OptionalEvaluationExpr | test.swift:294:8:294:12 | let ...? | | test.swift:294:16:294:26 | call to signum() | test.swift:294:16:294:26 | OptionalEvaluationExpr | +| test.swift:298:11:298:15 | let ...? | test.swift:298:15:298:15 | z1 | | test.swift:298:15:298:15 | SSA def(z1) | test.swift:300:15:300:15 | z1 | | test.swift:298:15:298:15 | z1 | test.swift:298:15:298:15 | SSA def(z1) | | test.swift:298:20:298:20 | x | test.swift:298:11:298:15 | let ...? | | test.swift:298:20:298:20 | x | test.swift:303:15:303:15 | x | +| test.swift:299:11:299:15 | let ...? | test.swift:299:15:299:15 | z2 | | test.swift:299:15:299:15 | SSA def(z2) | test.swift:301:15:301:15 | z2 | | test.swift:299:15:299:15 | z2 | test.swift:299:15:299:15 | SSA def(z2) | | test.swift:299:20:299:20 | y | test.swift:299:11:299:15 | let ...? | @@ -582,10 +588,12 @@ | test.swift:517:9:517:9 | SSA def(x) | test.swift:519:16:519:16 | x | | test.swift:517:9:517:9 | x | test.swift:517:9:517:9 | SSA def(x) | | test.swift:517:13:517:28 | call to optionalSource() | test.swift:517:9:517:9 | x | +| test.swift:519:8:519:12 | let ...? | test.swift:519:12:519:12 | a | | test.swift:519:12:519:12 | SSA def(a) | test.swift:519:27:519:27 | SSA phi(a) | | test.swift:519:12:519:12 | a | test.swift:519:12:519:12 | SSA def(a) | | test.swift:519:16:519:16 | x | test.swift:519:8:519:12 | let ...? | | test.swift:519:16:519:16 | x | test.swift:524:19:524:19 | x | +| test.swift:519:19:519:23 | let ...? | test.swift:519:23:519:23 | b | | test.swift:519:23:519:23 | SSA def(b) | test.swift:521:19:521:19 | b | | test.swift:519:23:519:23 | b | test.swift:519:23:519:23 | SSA def(b) | | test.swift:519:27:519:27 | SSA phi(a) | test.swift:520:19:520:19 | a | @@ -600,6 +608,7 @@ | test.swift:526:21:526:21 | a | test.swift:526:21:526:21 | SSA def(a) | | test.swift:526:35:526:35 | SSA def(b) | test.swift:528:19:528:19 | b | | test.swift:526:35:526:35 | b | test.swift:526:35:526:35 | SSA def(b) | +| test.swift:533:8:533:17 | let ...? | test.swift:533:12:533:17 | (...) | | test.swift:533:13:533:13 | SSA def(x) | test.swift:534:19:534:19 | x | | test.swift:533:13:533:13 | x | test.swift:533:13:533:13 | SSA def(x) | | test.swift:533:16:533:16 | SSA def(y) | test.swift:535:19:535:19 | y | @@ -628,9 +637,11 @@ | test.swift:547:14:547:16 | call to C.init() | test.swift:547:9:547:9 | cy | | test.swift:548:5:548:5 | [post] cy | test.swift:552:20:552:20 | cy | | test.swift:548:5:548:5 | cy | test.swift:552:20:552:20 | cy | +| test.swift:550:11:550:15 | let ...? | test.swift:550:15:550:15 | z1 | | test.swift:550:15:550:15 | SSA def(z1) | test.swift:551:15:551:15 | z1 | | test.swift:550:15:550:15 | z1 | test.swift:550:15:550:15 | SSA def(z1) | | test.swift:550:20:550:23 | .x | test.swift:550:11:550:15 | let ...? | +| test.swift:552:11:552:15 | let ...? | test.swift:552:15:552:15 | z2 | | test.swift:552:15:552:15 | SSA def(z2) | test.swift:553:15:553:15 | z2 | | test.swift:552:15:552:15 | z2 | test.swift:552:15:552:15 | SSA def(z2) | | test.swift:552:20:552:23 | .x | test.swift:552:11:552:15 | let ...? | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected index 6fd724f31ad..cb5fc364e9f 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected @@ -107,6 +107,8 @@ | conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | | conversions.swift:99:12:99:12 | [post] v3 | conversions.swift:100:12:100:12 | v3 | | conversions.swift:99:12:99:12 | v3 | conversions.swift:100:12:100:12 | v3 | +| conversions.swift:107:24:107:24 | myCEnumConst | conversions.swift:107:12:107:36 | call to Self.init(_:) | +| conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) | | simple.swift:12:13:12:13 | 1 | simple.swift:12:13:12:24 | ... .+(_:_:) ... | | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected index 25b8d79aa68..427040adc40 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected @@ -47,6 +47,7 @@ edges | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:99:12:99:12 | v3 | | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:100:12:100:12 | v3 | | conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | +| conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) | | file://:0:0:0:0 | self [first] | file://:0:0:0:0 | .first | | file://:0:0:0:0 | self [second] | file://:0:0:0:0 | .second | | file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [first] | @@ -206,6 +207,8 @@ nodes | conversions.swift:98:40:98:40 | parent | semmle.label | parent | | conversions.swift:99:12:99:12 | v3 | semmle.label | v3 | | conversions.swift:100:12:100:12 | v3 | semmle.label | v3 | +| conversions.swift:108:12:108:35 | call to Self.init(_:) | semmle.label | call to Self.init(_:) | +| conversions.swift:108:24:108:34 | call to sourceInt() | semmle.label | call to sourceInt() | | file://:0:0:0:0 | .first | semmle.label | .first | | file://:0:0:0:0 | .second | semmle.label | .second | | file://:0:0:0:0 | [post] self [first] | semmle.label | [post] self [first] | @@ -366,6 +369,7 @@ subpaths | conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result | | conversions.swift:99:12:99:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:99:12:99:12 | v3 | result | | conversions.swift:100:12:100:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:100:12:100:12 | v3 | result | +| conversions.swift:108:12:108:35 | call to Self.init(_:) | conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) | result | | simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result | | simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result | | simple.swift:14:13:14:24 | ... .-(_:_:) ... | simple.swift:14:17:14:24 | call to source() | simple.swift:14:13:14:24 | ... .-(_:_:) ... | result | From 0a2e4def8e925b5a3c62b429443124982a3c95eb Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 10 Aug 2023 19:53:24 +0100 Subject: [PATCH 007/325] Swift: Change note. --- swift/ql/lib/change-notes/2023-08-10-numeric-models.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 swift/ql/lib/change-notes/2023-08-10-numeric-models.md diff --git a/swift/ql/lib/change-notes/2023-08-10-numeric-models.md b/swift/ql/lib/change-notes/2023-08-10-numeric-models.md new file mode 100644 index 00000000000..85812d99c10 --- /dev/null +++ b/swift/ql/lib/change-notes/2023-08-10-numeric-models.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- + +* Added taint models for `Numeric` conversions. From 9a4410d4b764e58e82ee048adc3f6ef0227d4b7f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 16 Aug 2023 11:53:05 +0100 Subject: [PATCH 008/325] Swift: Additional test cases for array conversions. --- .../dataflow/taint/core/LocalTaint.expected | 195 +++++----- .../dataflow/taint/core/Taint.expected | 348 +++++++++--------- .../dataflow/taint/core/conversions.swift | 87 +++-- 3 files changed, 329 insertions(+), 301 deletions(-) diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected index cb5fc364e9f..5953d76c22d 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected @@ -17,98 +17,109 @@ | conversions.swift:19:33:19:33 | self | conversions.swift:19:33:19:33 | SSA def(self) | | conversions.swift:20:22:20:22 | SSA def(self) | conversions.swift:20:22:20:38 | self[return] | | conversions.swift:20:22:20:22 | self | conversions.swift:20:22:20:22 | SSA def(self) | -| conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) | -| conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) | -| conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | -| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | -| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 | -| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) | -| conversions.swift:30:20:30:33 | call to sourceString() | conversions.swift:30:20:30:35 | .utf8 | -| conversions.swift:32:5:32:9 | let ...? | conversions.swift:32:9:32:9 | v | -| conversions.swift:32:9:32:9 | SSA def(v) | conversions.swift:33:13:33:13 | v | -| conversions.swift:32:9:32:9 | v | conversions.swift:32:9:32:9 | SSA def(v) | -| conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:32:5:32:9 | let ...? | -| conversions.swift:36:6:36:6 | SSA def(v2) | conversions.swift:37:12:37:12 | v2 | -| conversions.swift:36:6:36:6 | v2 | conversions.swift:36:6:36:6 | SSA def(v2) | -| conversions.swift:36:6:36:10 | ... as ... | conversions.swift:36:6:36:6 | v2 | -| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:36:6:36:10 | ... as ... | -| conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) | -| conversions.swift:39:6:39:6 | SSA def(v4) | conversions.swift:40:12:40:12 | v4 | -| conversions.swift:39:6:39:6 | v4 | conversions.swift:39:6:39:6 | SSA def(v4) | -| conversions.swift:39:6:39:10 | ... as ... | conversions.swift:39:6:39:6 | v4 | -| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:39:6:39:10 | ... as ... | -| conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | -| conversions.swift:42:6:42:6 | SSA def(v5) | conversions.swift:43:12:43:12 | v5 | -| conversions.swift:42:6:42:6 | v5 | conversions.swift:42:6:42:6 | SSA def(v5) | -| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:42:6:42:6 | v5 | -| conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | -| conversions.swift:45:6:45:6 | SSA def(v6) | conversions.swift:46:12:46:12 | v6 | -| conversions.swift:45:6:45:6 | v6 | conversions.swift:45:6:45:6 | SSA def(v6) | -| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:45:6:45:6 | v6 | -| conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | -| conversions.swift:48:12:48:36 | call to Self.init(exactly:) | conversions.swift:48:12:48:37 | ...! | -| conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) | -| conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | -| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! | -| conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | -| conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | -| conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | -| conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian | -| conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian | -| conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) | -| conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) | -| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | -| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 | -| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) | -| conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) | -| conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | -| conversions.swift:67:67:67:67 | 0.0 | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | -| conversions.swift:68:41:68:41 | 0 | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | -| conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | -| conversions.swift:69:54:69:54 | 0.0 | conversions.swift:69:12:69:57 | call to Float.init(signOf:magnitudeOf:) | -| conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | -| conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent | -| conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | -| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | -| conversions.swift:80:6:80:6 | SSA def(ms1) | conversions.swift:81:12:81:12 | ms1 | -| conversions.swift:80:6:80:6 | ms1 | conversions.swift:80:6:80:6 | SSA def(ms1) | -| conversions.swift:80:12:80:26 | call to MyString.init(_:) | conversions.swift:80:12:80:27 | ...! | -| conversions.swift:80:12:80:27 | ...! | conversions.swift:80:6:80:6 | ms1 | -| conversions.swift:80:21:80:21 | abc | conversions.swift:80:12:80:26 | call to MyString.init(_:) | -| conversions.swift:81:12:81:12 | [post] ms1 | conversions.swift:82:12:82:12 | ms1 | -| conversions.swift:81:12:81:12 | ms1 | conversions.swift:82:12:82:12 | ms1 | -| conversions.swift:82:12:82:12 | [post] ms1 | conversions.swift:83:12:83:12 | ms1 | -| conversions.swift:82:12:82:12 | ms1 | conversions.swift:83:12:83:12 | ms1 | -| conversions.swift:83:12:83:12 | [post] ms1 | conversions.swift:84:12:84:12 | ms1 | -| conversions.swift:83:12:83:12 | ms1 | conversions.swift:84:12:84:12 | ms1 | -| conversions.swift:86:6:86:6 | SSA def(ms2) | conversions.swift:87:12:87:12 | ms2 | -| conversions.swift:86:6:86:6 | ms2 | conversions.swift:86:6:86:6 | SSA def(ms2) | -| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:36 | ...! | -| conversions.swift:86:12:86:36 | ...! | conversions.swift:86:6:86:6 | ms2 | -| conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:86:12:86:35 | call to MyString.init(_:) | -| conversions.swift:87:12:87:12 | [post] ms2 | conversions.swift:88:12:88:12 | ms2 | -| conversions.swift:87:12:87:12 | ms2 | conversions.swift:88:12:88:12 | ms2 | -| conversions.swift:88:12:88:12 | [post] ms2 | conversions.swift:89:12:89:12 | ms2 | -| conversions.swift:88:12:88:12 | ms2 | conversions.swift:89:12:89:12 | ms2 | -| conversions.swift:89:12:89:12 | [post] ms2 | conversions.swift:90:12:90:12 | ms2 | -| conversions.swift:89:12:89:12 | ms2 | conversions.swift:90:12:90:12 | ms2 | -| conversions.swift:94:6:94:6 | SSA def(parent) | conversions.swift:95:12:95:12 | parent | -| conversions.swift:94:6:94:6 | parent | conversions.swift:94:6:94:6 | SSA def(parent) | -| conversions.swift:94:6:94:15 | ... as ... | conversions.swift:94:6:94:6 | parent | -| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:94:6:94:15 | ... as ... | -| conversions.swift:95:12:95:12 | [post] parent | conversions.swift:96:12:96:12 | parent | -| conversions.swift:95:12:95:12 | parent | conversions.swift:96:12:96:12 | parent | -| conversions.swift:96:12:96:12 | [post] parent | conversions.swift:98:40:98:40 | parent | -| conversions.swift:96:12:96:12 | parent | conversions.swift:98:40:98:40 | parent | -| conversions.swift:98:6:98:6 | SSA def(v3) | conversions.swift:99:12:99:12 | v3 | -| conversions.swift:98:6:98:6 | v3 | conversions.swift:98:6:98:6 | SSA def(v3) | -| conversions.swift:98:6:98:10 | ... as ... | conversions.swift:98:6:98:6 | v3 | -| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:98:6:98:10 | ... as ... | -| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | -| conversions.swift:99:12:99:12 | [post] v3 | conversions.swift:100:12:100:12 | v3 | -| conversions.swift:99:12:99:12 | v3 | conversions.swift:100:12:100:12 | v3 | -| conversions.swift:107:24:107:24 | myCEnumConst | conversions.swift:107:12:107:36 | call to Self.init(_:) | -| conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) | +| conversions.swift:27:16:27:26 | call to sourceInt() | conversions.swift:27:12:27:27 | call to Self.init(_:) | +| conversions.swift:28:18:28:28 | call to sourceInt() | conversions.swift:28:12:28:29 | call to Self.init(_:) | +| conversions.swift:29:18:29:28 | call to sourceInt() | conversions.swift:29:12:29:29 | call to Float.init(_:) | +| conversions.swift:30:19:30:29 | call to sourceInt() | conversions.swift:30:12:30:30 | call to String.init(_:) | +| conversions.swift:31:12:31:30 | call to String.init(_:) | conversions.swift:31:12:31:32 | .utf8 | +| conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:30 | call to String.init(_:) | +| conversions.swift:33:6:33:6 | SSA def(arr) | conversions.swift:34:12:34:12 | arr | +| conversions.swift:33:6:33:6 | arr | conversions.swift:33:6:33:6 | SSA def(arr) | +| conversions.swift:33:12:33:30 | [...] | conversions.swift:33:6:33:6 | arr | +| conversions.swift:34:12:34:12 | arr | conversions.swift:35:12:35:12 | arr | +| conversions.swift:35:12:35:12 | [post] arr | conversions.swift:36:20:36:20 | arr | +| conversions.swift:35:12:35:12 | arr | conversions.swift:35:12:35:17 | ...[...] | +| conversions.swift:35:12:35:12 | arr | conversions.swift:36:20:36:20 | arr | +| conversions.swift:36:20:36:20 | arr | conversions.swift:37:20:37:20 | arr | +| conversions.swift:37:12:37:23 | call to Array.init(_:) | conversions.swift:37:12:37:26 | ...[...] | +| conversions.swift:38:20:38:33 | call to sourceString() | conversions.swift:38:20:38:35 | .utf8 | +| conversions.swift:39:12:39:39 | call to Array.init(_:) | conversions.swift:39:12:39:42 | ...[...] | +| conversions.swift:39:20:39:33 | call to sourceString() | conversions.swift:39:20:39:35 | .utf8 | +| conversions.swift:41:5:41:9 | let ...? | conversions.swift:41:9:41:9 | v | +| conversions.swift:41:9:41:9 | SSA def(v) | conversions.swift:42:13:42:13 | v | +| conversions.swift:41:9:41:9 | v | conversions.swift:41:9:41:9 | SSA def(v) | +| conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:41:5:41:9 | let ...? | +| conversions.swift:45:6:45:6 | SSA def(v2) | conversions.swift:46:12:46:12 | v2 | +| conversions.swift:45:6:45:6 | v2 | conversions.swift:45:6:45:6 | SSA def(v2) | +| conversions.swift:45:6:45:10 | ... as ... | conversions.swift:45:6:45:6 | v2 | +| conversions.swift:45:18:45:41 | call to numericCast(_:) | conversions.swift:45:6:45:10 | ... as ... | +| conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:45:18:45:41 | call to numericCast(_:) | +| conversions.swift:48:6:48:6 | SSA def(v4) | conversions.swift:49:12:49:12 | v4 | +| conversions.swift:48:6:48:6 | v4 | conversions.swift:48:6:48:6 | SSA def(v4) | +| conversions.swift:48:6:48:10 | ... as ... | conversions.swift:48:6:48:6 | v4 | +| conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) | conversions.swift:48:6:48:10 | ... as ... | +| conversions.swift:48:31:48:41 | call to sourceInt() | conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) | +| conversions.swift:51:6:51:6 | SSA def(v5) | conversions.swift:52:12:52:12 | v5 | +| conversions.swift:51:6:51:6 | v5 | conversions.swift:51:6:51:6 | SSA def(v5) | +| conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:51:6:51:6 | v5 | +| conversions.swift:51:36:51:46 | call to sourceInt() | conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:54:6:54:6 | SSA def(v6) | conversions.swift:55:12:55:12 | v6 | +| conversions.swift:54:6:54:6 | v6 | conversions.swift:54:6:54:6 | SSA def(v6) | +| conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) | conversions.swift:54:6:54:6 | v6 | +| conversions.swift:54:28:54:38 | call to sourceInt() | conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) | +| conversions.swift:57:12:57:36 | call to Self.init(exactly:) | conversions.swift:57:12:57:37 | ...! | +| conversions.swift:58:26:58:36 | call to sourceInt() | conversions.swift:58:12:58:37 | call to Self.init(clamping:) | +| conversions.swift:59:36:59:46 | call to sourceInt() | conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:60:12:60:41 | call to Self.init(_:radix:) | conversions.swift:60:12:60:42 | ...! | +| conversions.swift:60:16:60:29 | call to sourceString() | conversions.swift:60:12:60:41 | call to Self.init(_:radix:) | +| conversions.swift:62:30:62:40 | call to sourceInt() | conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) | +| conversions.swift:63:27:63:37 | call to sourceInt() | conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) | +| conversions.swift:64:12:64:22 | call to sourceInt() | conversions.swift:64:12:64:24 | .littleEndian | +| conversions.swift:65:12:65:22 | call to sourceInt() | conversions.swift:65:12:65:24 | .bigEndian | +| conversions.swift:70:18:70:30 | call to sourceFloat() | conversions.swift:70:12:70:31 | call to Float.init(_:) | +| conversions.swift:71:18:71:30 | call to sourceFloat() | conversions.swift:71:12:71:31 | call to UInt8.init(_:) | +| conversions.swift:72:19:72:31 | call to sourceFloat() | conversions.swift:72:12:72:32 | call to String.init(_:) | +| conversions.swift:73:12:73:32 | call to String.init(_:) | conversions.swift:73:12:73:34 | .utf8 | +| conversions.swift:73:19:73:31 | call to sourceFloat() | conversions.swift:73:12:73:32 | call to String.init(_:) | +| conversions.swift:75:18:75:30 | call to sourceFloat() | conversions.swift:75:12:75:31 | call to Float.init(_:) | +| conversions.swift:76:41:76:51 | call to sourceInt() | conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:76:67:76:67 | 0.0 | conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:77:41:77:41 | 0 | conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:77:57:77:69 | call to sourceFloat() | conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:78:54:78:54 | 0.0 | conversions.swift:78:12:78:57 | call to Float.init(signOf:magnitudeOf:) | +| conversions.swift:79:44:79:56 | call to sourceFloat() | conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) | +| conversions.swift:81:12:81:24 | call to sourceFloat() | conversions.swift:81:12:81:26 | .exponent | +| conversions.swift:82:12:82:24 | call to sourceFloat() | conversions.swift:82:12:82:26 | .significand | +| conversions.swift:87:19:87:32 | call to sourceString() | conversions.swift:87:12:87:33 | call to String.init(_:) | +| conversions.swift:89:6:89:6 | SSA def(ms1) | conversions.swift:90:12:90:12 | ms1 | +| conversions.swift:89:6:89:6 | ms1 | conversions.swift:89:6:89:6 | SSA def(ms1) | +| conversions.swift:89:12:89:26 | call to MyString.init(_:) | conversions.swift:89:12:89:27 | ...! | +| conversions.swift:89:12:89:27 | ...! | conversions.swift:89:6:89:6 | ms1 | +| conversions.swift:89:21:89:21 | abc | conversions.swift:89:12:89:26 | call to MyString.init(_:) | +| conversions.swift:90:12:90:12 | [post] ms1 | conversions.swift:91:12:91:12 | ms1 | +| conversions.swift:90:12:90:12 | ms1 | conversions.swift:91:12:91:12 | ms1 | +| conversions.swift:91:12:91:12 | [post] ms1 | conversions.swift:92:12:92:12 | ms1 | +| conversions.swift:91:12:91:12 | ms1 | conversions.swift:92:12:92:12 | ms1 | +| conversions.swift:92:12:92:12 | [post] ms1 | conversions.swift:93:12:93:12 | ms1 | +| conversions.swift:92:12:92:12 | ms1 | conversions.swift:93:12:93:12 | ms1 | +| conversions.swift:95:6:95:6 | SSA def(ms2) | conversions.swift:96:12:96:12 | ms2 | +| conversions.swift:95:6:95:6 | ms2 | conversions.swift:95:6:95:6 | SSA def(ms2) | +| conversions.swift:95:12:95:35 | call to MyString.init(_:) | conversions.swift:95:12:95:36 | ...! | +| conversions.swift:95:12:95:36 | ...! | conversions.swift:95:6:95:6 | ms2 | +| conversions.swift:95:21:95:34 | call to sourceString() | conversions.swift:95:12:95:35 | call to MyString.init(_:) | +| conversions.swift:96:12:96:12 | [post] ms2 | conversions.swift:97:12:97:12 | ms2 | +| conversions.swift:96:12:96:12 | ms2 | conversions.swift:97:12:97:12 | ms2 | +| conversions.swift:97:12:97:12 | [post] ms2 | conversions.swift:98:12:98:12 | ms2 | +| conversions.swift:97:12:97:12 | ms2 | conversions.swift:98:12:98:12 | ms2 | +| conversions.swift:98:12:98:12 | [post] ms2 | conversions.swift:99:12:99:12 | ms2 | +| conversions.swift:98:12:98:12 | ms2 | conversions.swift:99:12:99:12 | ms2 | +| conversions.swift:103:6:103:6 | SSA def(parent) | conversions.swift:104:12:104:12 | parent | +| conversions.swift:103:6:103:6 | parent | conversions.swift:103:6:103:6 | SSA def(parent) | +| conversions.swift:103:6:103:15 | ... as ... | conversions.swift:103:6:103:6 | parent | +| conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:103:6:103:15 | ... as ... | +| conversions.swift:104:12:104:12 | [post] parent | conversions.swift:105:12:105:12 | parent | +| conversions.swift:104:12:104:12 | parent | conversions.swift:105:12:105:12 | parent | +| conversions.swift:105:12:105:12 | [post] parent | conversions.swift:107:40:107:40 | parent | +| conversions.swift:105:12:105:12 | parent | conversions.swift:107:40:107:40 | parent | +| conversions.swift:107:6:107:6 | SSA def(v3) | conversions.swift:108:12:108:12 | v3 | +| conversions.swift:107:6:107:6 | v3 | conversions.swift:107:6:107:6 | SSA def(v3) | +| conversions.swift:107:6:107:10 | ... as ... | conversions.swift:107:6:107:6 | v3 | +| conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | conversions.swift:107:6:107:10 | ... as ... | +| conversions.swift:107:40:107:40 | parent | conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | +| conversions.swift:108:12:108:12 | [post] v3 | conversions.swift:109:12:109:12 | v3 | +| conversions.swift:108:12:108:12 | v3 | conversions.swift:109:12:109:12 | v3 | +| conversions.swift:116:24:116:24 | myCEnumConst | conversions.swift:116:12:116:36 | call to Self.init(_:) | +| conversions.swift:117:24:117:34 | call to sourceInt() | conversions.swift:117:12:117:35 | call to Self.init(_:) | | simple.swift:12:13:12:13 | 1 | simple.swift:12:13:12:24 | ... .+(_:_:) ... | | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected index 427040adc40..4f10e907be3 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected @@ -1,53 +1,56 @@ edges -| conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) | -| conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) | -| conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | -| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | -| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 | -| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) | -| conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:33:13:33:13 | v | -| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:37:12:37:12 | v2 | -| conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) | -| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:40:12:40:12 | v4 | -| conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | -| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:43:12:43:12 | v5 | -| conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | -| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:46:12:46:12 | v6 | -| conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | -| conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | conversions.swift:48:12:48:37 | ...! | -| conversions.swift:48:25:48:35 | call to sourceInt() | conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | -| conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) | -| conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | -| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! | -| conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | -| conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | -| conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | -| conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian | -| conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian | -| conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) | -| conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) | -| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | -| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 | -| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) | -| conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) | -| conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | -| conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | -| conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | -| conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent | -| conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | -| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | -| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | -| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:87:12:87:12 | ms2 | -| conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | conversions.swift:86:12:86:36 | ...! | -| conversions.swift:86:12:86:36 | ...! | conversions.swift:87:12:87:12 | ms2 | -| conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:86:12:86:35 | call to MyString.init(_:) | -| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | -| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | -| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:98:40:98:40 | parent | -| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:99:12:99:12 | v3 | -| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:100:12:100:12 | v3 | -| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | -| conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) | +| conversions.swift:27:16:27:26 | call to sourceInt() | conversions.swift:27:12:27:27 | call to Self.init(_:) | +| conversions.swift:28:18:28:28 | call to sourceInt() | conversions.swift:28:12:28:29 | call to Self.init(_:) | +| conversions.swift:29:18:29:28 | call to sourceInt() | conversions.swift:29:12:29:29 | call to Float.init(_:) | +| conversions.swift:30:19:30:29 | call to sourceInt() | conversions.swift:30:12:30:30 | call to String.init(_:) | +| conversions.swift:31:12:31:30 | call to String.init(_:) | conversions.swift:31:12:31:32 | .utf8 | +| conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:30 | call to String.init(_:) | +| conversions.swift:33:12:33:30 | [...] [Array element] | conversions.swift:35:12:35:12 | arr [Array element] | +| conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:33:12:33:30 | [...] [Array element] | +| conversions.swift:35:12:35:12 | arr [Array element] | conversions.swift:35:12:35:17 | ...[...] | +| conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:42:13:42:13 | v | +| conversions.swift:45:18:45:41 | call to numericCast(_:) | conversions.swift:46:12:46:12 | v2 | +| conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:45:18:45:41 | call to numericCast(_:) | +| conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) | conversions.swift:49:12:49:12 | v4 | +| conversions.swift:48:31:48:41 | call to sourceInt() | conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) | +| conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:52:12:52:12 | v5 | +| conversions.swift:51:36:51:46 | call to sourceInt() | conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) | conversions.swift:55:12:55:12 | v6 | +| conversions.swift:54:28:54:38 | call to sourceInt() | conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) | +| conversions.swift:57:12:57:36 | call to Self.init(exactly:) [some:0] | conversions.swift:57:12:57:37 | ...! | +| conversions.swift:57:25:57:35 | call to sourceInt() | conversions.swift:57:12:57:36 | call to Self.init(exactly:) [some:0] | +| conversions.swift:58:26:58:36 | call to sourceInt() | conversions.swift:58:12:58:37 | call to Self.init(clamping:) | +| conversions.swift:59:36:59:46 | call to sourceInt() | conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:60:12:60:41 | call to Self.init(_:radix:) | conversions.swift:60:12:60:42 | ...! | +| conversions.swift:60:16:60:29 | call to sourceString() | conversions.swift:60:12:60:41 | call to Self.init(_:radix:) | +| conversions.swift:62:30:62:40 | call to sourceInt() | conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) | +| conversions.swift:63:27:63:37 | call to sourceInt() | conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) | +| conversions.swift:64:12:64:22 | call to sourceInt() | conversions.swift:64:12:64:24 | .littleEndian | +| conversions.swift:65:12:65:22 | call to sourceInt() | conversions.swift:65:12:65:24 | .bigEndian | +| conversions.swift:70:18:70:30 | call to sourceFloat() | conversions.swift:70:12:70:31 | call to Float.init(_:) | +| conversions.swift:71:18:71:30 | call to sourceFloat() | conversions.swift:71:12:71:31 | call to UInt8.init(_:) | +| conversions.swift:72:19:72:31 | call to sourceFloat() | conversions.swift:72:12:72:32 | call to String.init(_:) | +| conversions.swift:73:12:73:32 | call to String.init(_:) | conversions.swift:73:12:73:34 | .utf8 | +| conversions.swift:73:19:73:31 | call to sourceFloat() | conversions.swift:73:12:73:32 | call to String.init(_:) | +| conversions.swift:75:18:75:30 | call to sourceFloat() | conversions.swift:75:12:75:31 | call to Float.init(_:) | +| conversions.swift:76:41:76:51 | call to sourceInt() | conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:77:57:77:69 | call to sourceFloat() | conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) | +| conversions.swift:79:44:79:56 | call to sourceFloat() | conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) | +| conversions.swift:81:12:81:24 | call to sourceFloat() | conversions.swift:81:12:81:26 | .exponent | +| conversions.swift:82:12:82:24 | call to sourceFloat() | conversions.swift:82:12:82:26 | .significand | +| conversions.swift:87:19:87:32 | call to sourceString() | conversions.swift:87:12:87:33 | call to String.init(_:) | +| conversions.swift:95:12:95:35 | call to MyString.init(_:) | conversions.swift:95:12:95:35 | call to MyString.init(_:) [some:0] | +| conversions.swift:95:12:95:35 | call to MyString.init(_:) | conversions.swift:96:12:96:12 | ms2 | +| conversions.swift:95:12:95:35 | call to MyString.init(_:) [some:0] | conversions.swift:95:12:95:36 | ...! | +| conversions.swift:95:12:95:36 | ...! | conversions.swift:96:12:96:12 | ms2 | +| conversions.swift:95:21:95:34 | call to sourceString() | conversions.swift:95:12:95:35 | call to MyString.init(_:) | +| conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:104:12:104:12 | parent | +| conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:105:12:105:12 | parent | +| conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:107:40:107:40 | parent | +| conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | conversions.swift:108:12:108:12 | v3 | +| conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | conversions.swift:109:12:109:12 | v3 | +| conversions.swift:107:40:107:40 | parent | conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | +| conversions.swift:117:24:117:34 | call to sourceInt() | conversions.swift:117:12:117:35 | call to Self.init(_:) | | file://:0:0:0:0 | self [first] | file://:0:0:0:0 | .first | | file://:0:0:0:0 | self [second] | file://:0:0:0:0 | .second | | file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [first] | @@ -126,89 +129,93 @@ edges | try.swift:18:18:18:25 | call to source() | try.swift:18:18:18:25 | call to source() [some:0] | | try.swift:18:18:18:25 | call to source() [some:0] | try.swift:18:13:18:25 | try? ... [some:0] | nodes -| conversions.swift:24:12:24:22 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:25:12:25:27 | call to Self.init(_:) | semmle.label | call to Self.init(_:) | -| conversions.swift:25:16:25:26 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:26:12:26:29 | call to Self.init(_:) | semmle.label | call to Self.init(_:) | -| conversions.swift:26:18:26:28 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:27:12:27:29 | call to Float.init(_:) | semmle.label | call to Float.init(_:) | -| conversions.swift:27:18:27:28 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:28:12:28:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| conversions.swift:28:19:28:29 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:29:12:29:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| conversions.swift:29:12:29:32 | .utf8 | semmle.label | .utf8 | -| conversions.swift:29:19:29:29 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:32:13:32:23 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:33:13:33:13 | v | semmle.label | v | -| conversions.swift:36:18:36:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) | -| conversions.swift:36:30:36:40 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:37:12:37:12 | v2 | semmle.label | v2 | -| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | semmle.label | call to unsafeBitCast(_:to:) | -| conversions.swift:39:31:39:41 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:40:12:40:12 | v4 | semmle.label | v4 | -| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) | -| conversions.swift:42:36:42:46 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:43:12:43:12 | v5 | semmle.label | v5 | -| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | semmle.label | call to UInt.init(bitPattern:) | -| conversions.swift:45:28:45:38 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:46:12:46:12 | v6 | semmle.label | v6 | -| conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | semmle.label | call to Self.init(exactly:) [some:0] | -| conversions.swift:48:12:48:37 | ...! | semmle.label | ...! | -| conversions.swift:48:25:48:35 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:49:12:49:37 | call to Self.init(clamping:) | semmle.label | call to Self.init(clamping:) | -| conversions.swift:49:26:49:36 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) | -| conversions.swift:50:36:50:46 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | semmle.label | call to Self.init(_:radix:) | -| conversions.swift:51:12:51:42 | ...! | semmle.label | ...! | -| conversions.swift:51:16:51:29 | call to sourceString() | semmle.label | call to sourceString() | -| conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | semmle.label | call to Self.init(littleEndian:) | -| conversions.swift:53:30:53:40 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | semmle.label | call to Self.init(bigEndian:) | -| conversions.swift:54:27:54:37 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:55:12:55:22 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:55:12:55:24 | .littleEndian | semmle.label | .littleEndian | -| conversions.swift:56:12:56:22 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:56:12:56:24 | .bigEndian | semmle.label | .bigEndian | -| conversions.swift:60:12:60:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:61:12:61:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) | -| conversions.swift:61:18:61:30 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:62:12:62:31 | call to UInt8.init(_:) | semmle.label | call to UInt8.init(_:) | -| conversions.swift:62:18:62:30 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:63:12:63:32 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| conversions.swift:63:19:63:31 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:64:12:64:32 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| conversions.swift:64:12:64:34 | .utf8 | semmle.label | .utf8 | -| conversions.swift:64:19:64:31 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:66:12:66:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) | -| conversions.swift:66:18:66:30 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) | -| conversions.swift:67:41:67:51 | call to sourceInt() | semmle.label | call to sourceInt() | -| conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) | -| conversions.swift:68:57:68:69 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | semmle.label | call to Float.init(signOf:magnitudeOf:) | -| conversions.swift:70:44:70:56 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:72:12:72:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:72:12:72:26 | .exponent | semmle.label | .exponent | -| conversions.swift:73:12:73:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | -| conversions.swift:73:12:73:26 | .significand | semmle.label | .significand | -| conversions.swift:77:12:77:25 | call to sourceString() | semmle.label | call to sourceString() | -| conversions.swift:78:12:78:33 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| conversions.swift:78:19:78:32 | call to sourceString() | semmle.label | call to sourceString() | -| conversions.swift:86:12:86:35 | call to MyString.init(_:) | semmle.label | call to MyString.init(_:) | -| conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | semmle.label | call to MyString.init(_:) [some:0] | -| conversions.swift:86:12:86:36 | ...! | semmle.label | ...! | -| conversions.swift:86:21:86:34 | call to sourceString() | semmle.label | call to sourceString() | -| conversions.swift:87:12:87:12 | ms2 | semmle.label | ms2 | -| conversions.swift:94:31:94:44 | call to sourceString() | semmle.label | call to sourceString() | -| conversions.swift:95:12:95:12 | parent | semmle.label | parent | -| conversions.swift:96:12:96:12 | parent | semmle.label | parent | -| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | semmle.label | call to unsafeDowncast(_:to:) | -| conversions.swift:98:40:98:40 | parent | semmle.label | parent | -| conversions.swift:99:12:99:12 | v3 | semmle.label | v3 | -| conversions.swift:100:12:100:12 | v3 | semmle.label | v3 | -| conversions.swift:108:12:108:35 | call to Self.init(_:) | semmle.label | call to Self.init(_:) | -| conversions.swift:108:24:108:34 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:26:12:26:22 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:27:12:27:27 | call to Self.init(_:) | semmle.label | call to Self.init(_:) | +| conversions.swift:27:16:27:26 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:28:12:28:29 | call to Self.init(_:) | semmle.label | call to Self.init(_:) | +| conversions.swift:28:18:28:28 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:29:12:29:29 | call to Float.init(_:) | semmle.label | call to Float.init(_:) | +| conversions.swift:29:18:29:28 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:30:12:30:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:30:19:30:29 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:31:12:31:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:31:12:31:32 | .utf8 | semmle.label | .utf8 | +| conversions.swift:31:19:31:29 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:33:12:33:30 | [...] [Array element] | semmle.label | [...] [Array element] | +| conversions.swift:33:19:33:29 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:35:12:35:12 | arr [Array element] | semmle.label | arr [Array element] | +| conversions.swift:35:12:35:17 | ...[...] | semmle.label | ...[...] | +| conversions.swift:41:13:41:23 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:42:13:42:13 | v | semmle.label | v | +| conversions.swift:45:18:45:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) | +| conversions.swift:45:30:45:40 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:46:12:46:12 | v2 | semmle.label | v2 | +| conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) | semmle.label | call to unsafeBitCast(_:to:) | +| conversions.swift:48:31:48:41 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:49:12:49:12 | v4 | semmle.label | v4 | +| conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:51:36:51:46 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:52:12:52:12 | v5 | semmle.label | v5 | +| conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) | semmle.label | call to UInt.init(bitPattern:) | +| conversions.swift:54:28:54:38 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:55:12:55:12 | v6 | semmle.label | v6 | +| conversions.swift:57:12:57:36 | call to Self.init(exactly:) [some:0] | semmle.label | call to Self.init(exactly:) [some:0] | +| conversions.swift:57:12:57:37 | ...! | semmle.label | ...! | +| conversions.swift:57:25:57:35 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:58:12:58:37 | call to Self.init(clamping:) | semmle.label | call to Self.init(clamping:) | +| conversions.swift:58:26:58:36 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) | +| conversions.swift:59:36:59:46 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:60:12:60:41 | call to Self.init(_:radix:) | semmle.label | call to Self.init(_:radix:) | +| conversions.swift:60:12:60:42 | ...! | semmle.label | ...! | +| conversions.swift:60:16:60:29 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) | semmle.label | call to Self.init(littleEndian:) | +| conversions.swift:62:30:62:40 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) | semmle.label | call to Self.init(bigEndian:) | +| conversions.swift:63:27:63:37 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:64:12:64:22 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:64:12:64:24 | .littleEndian | semmle.label | .littleEndian | +| conversions.swift:65:12:65:22 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:65:12:65:24 | .bigEndian | semmle.label | .bigEndian | +| conversions.swift:69:12:69:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:70:12:70:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) | +| conversions.swift:70:18:70:30 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:71:12:71:31 | call to UInt8.init(_:) | semmle.label | call to UInt8.init(_:) | +| conversions.swift:71:18:71:30 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:72:12:72:32 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:72:19:72:31 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:73:12:73:32 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:73:12:73:34 | .utf8 | semmle.label | .utf8 | +| conversions.swift:73:19:73:31 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:75:12:75:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) | +| conversions.swift:75:18:75:30 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) | +| conversions.swift:76:41:76:51 | call to sourceInt() | semmle.label | call to sourceInt() | +| conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) | +| conversions.swift:77:57:77:69 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) | semmle.label | call to Float.init(signOf:magnitudeOf:) | +| conversions.swift:79:44:79:56 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:81:12:81:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:81:12:81:26 | .exponent | semmle.label | .exponent | +| conversions.swift:82:12:82:24 | call to sourceFloat() | semmle.label | call to sourceFloat() | +| conversions.swift:82:12:82:26 | .significand | semmle.label | .significand | +| conversions.swift:86:12:86:25 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:87:12:87:33 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| conversions.swift:87:19:87:32 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:95:12:95:35 | call to MyString.init(_:) | semmle.label | call to MyString.init(_:) | +| conversions.swift:95:12:95:35 | call to MyString.init(_:) [some:0] | semmle.label | call to MyString.init(_:) [some:0] | +| conversions.swift:95:12:95:36 | ...! | semmle.label | ...! | +| conversions.swift:95:21:95:34 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:96:12:96:12 | ms2 | semmle.label | ms2 | +| conversions.swift:103:31:103:44 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:104:12:104:12 | parent | semmle.label | parent | +| conversions.swift:105:12:105:12 | parent | semmle.label | parent | +| conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | semmle.label | call to unsafeDowncast(_:to:) | +| conversions.swift:107:40:107:40 | parent | semmle.label | parent | +| conversions.swift:108:12:108:12 | v3 | semmle.label | v3 | +| conversions.swift:109:12:109:12 | v3 | semmle.label | v3 | +| conversions.swift:117:12:117:35 | call to Self.init(_:) | semmle.label | call to Self.init(_:) | +| conversions.swift:117:24:117:34 | call to sourceInt() | semmle.label | call to sourceInt() | | file://:0:0:0:0 | .first | semmle.label | .first | | file://:0:0:0:0 | .second | semmle.label | .second | | file://:0:0:0:0 | [post] self [first] | semmle.label | [post] self [first] | @@ -332,44 +339,45 @@ subpaths | stringinterpolation.swift:28:14:28:21 | call to source() | stringinterpolation.swift:7:6:7:6 | value | file://:0:0:0:0 | [post] self [second] | stringinterpolation.swift:28:2:28:2 | [post] p2 [second] | | stringinterpolation.swift:31:21:31:21 | p2 [second] | stringinterpolation.swift:7:6:7:6 | self [second] | file://:0:0:0:0 | .second | stringinterpolation.swift:31:21:31:24 | .second | #select -| conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | result | -| conversions.swift:25:12:25:27 | call to Self.init(_:) | conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) | result | -| conversions.swift:26:12:26:29 | call to Self.init(_:) | conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) | result | -| conversions.swift:27:12:27:29 | call to Float.init(_:) | conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | result | -| conversions.swift:28:12:28:30 | call to String.init(_:) | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | result | -| conversions.swift:29:12:29:32 | .utf8 | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:32 | .utf8 | result | -| conversions.swift:33:13:33:13 | v | conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:33:13:33:13 | v | result | -| conversions.swift:37:12:37:12 | v2 | conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:37:12:37:12 | v2 | result | -| conversions.swift:40:12:40:12 | v4 | conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:40:12:40:12 | v4 | result | -| conversions.swift:43:12:43:12 | v5 | conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:43:12:43:12 | v5 | result | -| conversions.swift:46:12:46:12 | v6 | conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:46:12:46:12 | v6 | result | -| conversions.swift:48:12:48:37 | ...! | conversions.swift:48:25:48:35 | call to sourceInt() | conversions.swift:48:12:48:37 | ...! | result | -| conversions.swift:49:12:49:37 | call to Self.init(clamping:) | conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) | result | -| conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | result | -| conversions.swift:51:12:51:42 | ...! | conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:42 | ...! | result | -| conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | result | -| conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | result | -| conversions.swift:55:12:55:24 | .littleEndian | conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian | result | -| conversions.swift:56:12:56:24 | .bigEndian | conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian | result | -| conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | result | -| conversions.swift:61:12:61:31 | call to Float.init(_:) | conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) | result | -| conversions.swift:62:12:62:31 | call to UInt8.init(_:) | conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) | result | -| conversions.swift:63:12:63:32 | call to String.init(_:) | conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | result | -| conversions.swift:64:12:64:34 | .utf8 | conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:34 | .utf8 | result | -| conversions.swift:66:12:66:31 | call to Float.init(_:) | conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) | result | -| conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | result | -| conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | result | -| conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | result | -| conversions.swift:72:12:72:26 | .exponent | conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent | result | -| conversions.swift:73:12:73:26 | .significand | conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | result | -| conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | result | -| conversions.swift:78:12:78:33 | call to String.init(_:) | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | result | -| conversions.swift:87:12:87:12 | ms2 | conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:87:12:87:12 | ms2 | result | -| conversions.swift:95:12:95:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | result | -| conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result | -| conversions.swift:99:12:99:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:99:12:99:12 | v3 | result | -| conversions.swift:100:12:100:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:100:12:100:12 | v3 | result | -| conversions.swift:108:12:108:35 | call to Self.init(_:) | conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) | result | +| conversions.swift:26:12:26:22 | call to sourceInt() | conversions.swift:26:12:26:22 | call to sourceInt() | conversions.swift:26:12:26:22 | call to sourceInt() | result | +| conversions.swift:27:12:27:27 | call to Self.init(_:) | conversions.swift:27:16:27:26 | call to sourceInt() | conversions.swift:27:12:27:27 | call to Self.init(_:) | result | +| conversions.swift:28:12:28:29 | call to Self.init(_:) | conversions.swift:28:18:28:28 | call to sourceInt() | conversions.swift:28:12:28:29 | call to Self.init(_:) | result | +| conversions.swift:29:12:29:29 | call to Float.init(_:) | conversions.swift:29:18:29:28 | call to sourceInt() | conversions.swift:29:12:29:29 | call to Float.init(_:) | result | +| conversions.swift:30:12:30:30 | call to String.init(_:) | conversions.swift:30:19:30:29 | call to sourceInt() | conversions.swift:30:12:30:30 | call to String.init(_:) | result | +| conversions.swift:31:12:31:32 | .utf8 | conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:32 | .utf8 | result | +| conversions.swift:35:12:35:17 | ...[...] | conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:35:12:35:17 | ...[...] | result | +| conversions.swift:42:13:42:13 | v | conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:42:13:42:13 | v | result | +| conversions.swift:46:12:46:12 | v2 | conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:46:12:46:12 | v2 | result | +| conversions.swift:49:12:49:12 | v4 | conversions.swift:48:31:48:41 | call to sourceInt() | conversions.swift:49:12:49:12 | v4 | result | +| conversions.swift:52:12:52:12 | v5 | conversions.swift:51:36:51:46 | call to sourceInt() | conversions.swift:52:12:52:12 | v5 | result | +| conversions.swift:55:12:55:12 | v6 | conversions.swift:54:28:54:38 | call to sourceInt() | conversions.swift:55:12:55:12 | v6 | result | +| conversions.swift:57:12:57:37 | ...! | conversions.swift:57:25:57:35 | call to sourceInt() | conversions.swift:57:12:57:37 | ...! | result | +| conversions.swift:58:12:58:37 | call to Self.init(clamping:) | conversions.swift:58:26:58:36 | call to sourceInt() | conversions.swift:58:12:58:37 | call to Self.init(clamping:) | result | +| conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:59:36:59:46 | call to sourceInt() | conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) | result | +| conversions.swift:60:12:60:42 | ...! | conversions.swift:60:16:60:29 | call to sourceString() | conversions.swift:60:12:60:42 | ...! | result | +| conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) | conversions.swift:62:30:62:40 | call to sourceInt() | conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) | result | +| conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) | conversions.swift:63:27:63:37 | call to sourceInt() | conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) | result | +| conversions.swift:64:12:64:24 | .littleEndian | conversions.swift:64:12:64:22 | call to sourceInt() | conversions.swift:64:12:64:24 | .littleEndian | result | +| conversions.swift:65:12:65:24 | .bigEndian | conversions.swift:65:12:65:22 | call to sourceInt() | conversions.swift:65:12:65:24 | .bigEndian | result | +| conversions.swift:69:12:69:24 | call to sourceFloat() | conversions.swift:69:12:69:24 | call to sourceFloat() | conversions.swift:69:12:69:24 | call to sourceFloat() | result | +| conversions.swift:70:12:70:31 | call to Float.init(_:) | conversions.swift:70:18:70:30 | call to sourceFloat() | conversions.swift:70:12:70:31 | call to Float.init(_:) | result | +| conversions.swift:71:12:71:31 | call to UInt8.init(_:) | conversions.swift:71:18:71:30 | call to sourceFloat() | conversions.swift:71:12:71:31 | call to UInt8.init(_:) | result | +| conversions.swift:72:12:72:32 | call to String.init(_:) | conversions.swift:72:19:72:31 | call to sourceFloat() | conversions.swift:72:12:72:32 | call to String.init(_:) | result | +| conversions.swift:73:12:73:34 | .utf8 | conversions.swift:73:19:73:31 | call to sourceFloat() | conversions.swift:73:12:73:34 | .utf8 | result | +| conversions.swift:75:12:75:31 | call to Float.init(_:) | conversions.swift:75:18:75:30 | call to sourceFloat() | conversions.swift:75:12:75:31 | call to Float.init(_:) | result | +| conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:76:41:76:51 | call to sourceInt() | conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) | result | +| conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:77:57:77:69 | call to sourceFloat() | conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) | result | +| conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) | conversions.swift:79:44:79:56 | call to sourceFloat() | conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) | result | +| conversions.swift:81:12:81:26 | .exponent | conversions.swift:81:12:81:24 | call to sourceFloat() | conversions.swift:81:12:81:26 | .exponent | result | +| conversions.swift:82:12:82:26 | .significand | conversions.swift:82:12:82:24 | call to sourceFloat() | conversions.swift:82:12:82:26 | .significand | result | +| conversions.swift:86:12:86:25 | call to sourceString() | conversions.swift:86:12:86:25 | call to sourceString() | conversions.swift:86:12:86:25 | call to sourceString() | result | +| conversions.swift:87:12:87:33 | call to String.init(_:) | conversions.swift:87:19:87:32 | call to sourceString() | conversions.swift:87:12:87:33 | call to String.init(_:) | result | +| conversions.swift:96:12:96:12 | ms2 | conversions.swift:95:21:95:34 | call to sourceString() | conversions.swift:96:12:96:12 | ms2 | result | +| conversions.swift:104:12:104:12 | parent | conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:104:12:104:12 | parent | result | +| conversions.swift:105:12:105:12 | parent | conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:105:12:105:12 | parent | result | +| conversions.swift:108:12:108:12 | v3 | conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:108:12:108:12 | v3 | result | +| conversions.swift:109:12:109:12 | v3 | conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:109:12:109:12 | v3 | result | +| conversions.swift:117:12:117:35 | call to Self.init(_:) | conversions.swift:117:24:117:34 | call to sourceInt() | conversions.swift:117:12:117:35 | call to Self.init(_:) | result | | simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result | | simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result | | simple.swift:14:13:14:24 | ... .-(_:_:) ... | simple.swift:14:17:14:24 | call to source() | simple.swift:14:13:14:24 | ... .-(_:_:) ... | result | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift index 321c555e0ab..efb0bba4ed2 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift +++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift @@ -20,62 +20,71 @@ class MyString : LosslessStringConvertible, CustomStringConvertible, CustomDebug var clean: String { get { return "" } } } +typealias MyInt = Int + func testConversions() { - sink(arg: sourceInt()) // $ tainted=24 - sink(arg: Int(sourceInt())) // $ tainted=25 - sink(arg: UInt8(sourceInt())) // $ tainted=26 - sink(arg: Float(sourceInt())) // $ tainted=27 - sink(arg: String(sourceInt())) // $ tainted=28 - sink(arg: String(sourceInt()).utf8) // $ tainted=29 - sink(arg: [UInt8](sourceString().utf8)) // $ MISSING: tainted= + sink(arg: sourceInt()) // $ tainted=26 + sink(arg: Int(sourceInt())) // $ tainted=27 + sink(arg: UInt8(sourceInt())) // $ tainted=28 + sink(arg: Float(sourceInt())) // $ tainted=29 + sink(arg: String(sourceInt())) // $ tainted=30 + sink(arg: String(sourceInt()).utf8) // $ tainted=31 + + let arr = [1, 2, sourceInt()] + sink(arg: arr) + sink(arg: arr[0]) // $ tainted=33 + sink(arg: [MyInt](arr)) + sink(arg: [MyInt](arr)[0]) // $ MISSING: tainted=33 + sink(arg: [UInt8](sourceString().utf8)) + sink(arg: [UInt8](sourceString().utf8)[0]) // $ MISSING: tainted=33 if let v = sourceInt() as? UInt { - sink(arg: v) // $ tainted=32 + sink(arg: v) // $ tainted=41 } let v2: UInt8 = numericCast(sourceInt()) - sink(arg: v2) // $ tainted=36 + sink(arg: v2) // $ tainted=45 let v4: UInt = unsafeBitCast(sourceInt(), to: UInt.self) - sink(arg: v4) // $ tainted=39 + sink(arg: v4) // $ tainted=48 let v5 = UInt(truncatingIfNeeded: sourceInt()) - sink(arg: v5) // $ tainted=42 + sink(arg: v5) // $ tainted=51 let v6 = UInt(bitPattern: sourceInt()) - sink(arg: v6) // $ tainted=45 + sink(arg: v6) // $ tainted=54 - sink(arg: Int(exactly: sourceInt())!) // $ tainted=48 - sink(arg: Int(clamping: sourceInt())) // $ tainted=49 - sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ tainted=50 - sink(arg: Int(sourceString(), radix: 10)!) // $ tainted=51 + sink(arg: Int(exactly: sourceInt())!) // $ tainted=57 + sink(arg: Int(clamping: sourceInt())) // $ tainted=58 + sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ tainted=59 + sink(arg: Int(sourceString(), radix: 10)!) // $ tainted=60 - sink(arg: Int(littleEndian: sourceInt())) // $ tainted=53 - sink(arg: Int(bigEndian: sourceInt())) // $ tainted=54 - sink(arg: sourceInt().littleEndian) // $ tainted=55 - sink(arg: sourceInt().bigEndian) // $ tainted=56 + sink(arg: Int(littleEndian: sourceInt())) // $ tainted=62 + sink(arg: Int(bigEndian: sourceInt())) // $ tainted=63 + sink(arg: sourceInt().littleEndian) // $ tainted=64 + sink(arg: sourceInt().bigEndian) // $ tainted=65 // --- - sink(arg: sourceFloat()) // $ tainted=60 - sink(arg: Float(sourceFloat())) // $ tainted=61 - sink(arg: UInt8(sourceFloat())) // $ tainted=62 - sink(arg: String(sourceFloat())) // $ tainted=63 - sink(arg: String(sourceFloat()).utf8) // $ tainted=64 + sink(arg: sourceFloat()) // $ tainted=69 + sink(arg: Float(sourceFloat())) // $ tainted=70 + sink(arg: UInt8(sourceFloat())) // $ tainted=71 + sink(arg: String(sourceFloat())) // $ tainted=72 + sink(arg: String(sourceFloat()).utf8) // $ tainted=73 - sink(arg: Float(sourceFloat())) // $ tainted=66 - sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // $ tainted=67 - sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // $ tainted=68 + sink(arg: Float(sourceFloat())) // $ tainted=75 + sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // $ tainted=76 + sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // $ tainted=77 sink(arg: Float(signOf: sourceFloat(), magnitudeOf: 0.0)) // (good) - sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // $ tainted=70 + sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // $ tainted=79 - sink(arg: sourceFloat().exponent) // $ tainted=72 - sink(arg: sourceFloat().significand) // $ tainted=73 + sink(arg: sourceFloat().exponent) // $ tainted=81 + sink(arg: sourceFloat().significand) // $ tainted=82 // --- - sink(arg: sourceString()) // $ tainted=77 - sink(arg: String(sourceString())) // $ tainted=78 + sink(arg: sourceString()) // $ tainted=86 + sink(arg: String(sourceString())) // $ tainted=87 let ms1 = MyString("abc")! sink(arg: ms1) @@ -84,7 +93,7 @@ func testConversions() { sink(arg: ms1.clean) let ms2 = MyString(sourceString())! - sink(arg: ms2) // $ tainted=86 + sink(arg: ms2) // $ tainted=95 sink(arg: ms2.description) // $ MISSING: tainted= sink(arg: ms2.debugDescription) // $ MISSING: tainted= sink(arg: ms2.clean) @@ -92,12 +101,12 @@ func testConversions() { // --- let parent : MyParentClass = sourceString() as! MyChildClass - sink(arg: parent) // $ tainted=94 - sink(arg: parent as! MyChildClass) // $ tainted=94 + sink(arg: parent) // $ tainted=103 + sink(arg: parent as! MyChildClass) // $ tainted=103 let v3: MyChildClass = unsafeDowncast(parent, to: MyChildClass.self) - sink(arg: v3) // $ tainted=94 - sink(arg: v3 as! MyParentClass) // $ tainted=94 + sink(arg: v3) // $ tainted=103 + sink(arg: v3 as! MyParentClass) // $ tainted=103 } var myCEnumConst : Int = 0 @@ -105,5 +114,5 @@ typealias MyCEnumType = UInt32 func testCEnum() { sink(arg: MyCEnumType(myCEnumConst)) - sink(arg: MyCEnumType(sourceInt())) // $ tainted=108 + sink(arg: MyCEnumType(sourceInt())) // $ tainted=117 } From 4b66bada3d188fc891950b1171ae9b3abb572323 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 16 Aug 2023 12:01:53 +0100 Subject: [PATCH 009/325] Swift: Model array initializers. --- .../swift/frameworks/StandardLibrary/Array.qll | 5 +++++ .../dataflow/taint/core/Taint.expected | 15 +++++++++++++++ .../dataflow/taint/core/conversions.swift | 4 ++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll index 207d120e82e..30d753ae967 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll @@ -19,6 +19,11 @@ private class ArraySummaries extends SummaryModelCsv { override predicate row(string row) { row = [ + ";Array;true;init(_:);;;Argument[0];ReturnValue.ArrayElement;value", + ";Array;true;init(_:);;;Argument[0].ArrayElement;ReturnValue.ArrayElement;value", + ";Array;true;init(_:);;;Argument[0].CollectionElement;ReturnValue.ArrayElement;value", + ";Array;true;init(repeating:count:);;;Argument[0];ReturnValue.ArrayElement;value", + ";Array;true;init(arrayLiteral:);;;Argument[0].ArrayElement;ReturnValue.ArrayElement;value", ";Array;true;insert(_:at:);;;Argument[0];Argument[-1].ArrayElement;value", ";Array;true;insert(_:at:);;;Argument[1];Argument[-1];taint" ] diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected index 4f10e907be3..440a286dfb9 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected @@ -6,8 +6,14 @@ edges | conversions.swift:31:12:31:30 | call to String.init(_:) | conversions.swift:31:12:31:32 | .utf8 | | conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:30 | call to String.init(_:) | | conversions.swift:33:12:33:30 | [...] [Array element] | conversions.swift:35:12:35:12 | arr [Array element] | +| conversions.swift:33:12:33:30 | [...] [Array element] | conversions.swift:37:20:37:20 | arr [Array element] | | conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:33:12:33:30 | [...] [Array element] | | conversions.swift:35:12:35:12 | arr [Array element] | conversions.swift:35:12:35:17 | ...[...] | +| conversions.swift:37:12:37:23 | call to Array.init(_:) [Array element] | conversions.swift:37:12:37:26 | ...[...] | +| conversions.swift:37:20:37:20 | arr [Array element] | conversions.swift:37:12:37:23 | call to Array.init(_:) [Array element] | +| conversions.swift:39:12:39:39 | call to Array.init(_:) [Array element] | conversions.swift:39:12:39:42 | ...[...] | +| conversions.swift:39:20:39:33 | call to sourceString() | conversions.swift:39:20:39:35 | .utf8 | +| conversions.swift:39:20:39:35 | .utf8 | conversions.swift:39:12:39:39 | call to Array.init(_:) [Array element] | | conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:42:13:42:13 | v | | conversions.swift:45:18:45:41 | call to numericCast(_:) | conversions.swift:46:12:46:12 | v2 | | conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:45:18:45:41 | call to numericCast(_:) | @@ -145,6 +151,13 @@ nodes | conversions.swift:33:19:33:29 | call to sourceInt() | semmle.label | call to sourceInt() | | conversions.swift:35:12:35:12 | arr [Array element] | semmle.label | arr [Array element] | | conversions.swift:35:12:35:17 | ...[...] | semmle.label | ...[...] | +| conversions.swift:37:12:37:23 | call to Array.init(_:) [Array element] | semmle.label | call to Array.init(_:) [Array element] | +| conversions.swift:37:12:37:26 | ...[...] | semmle.label | ...[...] | +| conversions.swift:37:20:37:20 | arr [Array element] | semmle.label | arr [Array element] | +| conversions.swift:39:12:39:39 | call to Array.init(_:) [Array element] | semmle.label | call to Array.init(_:) [Array element] | +| conversions.swift:39:12:39:42 | ...[...] | semmle.label | ...[...] | +| conversions.swift:39:20:39:33 | call to sourceString() | semmle.label | call to sourceString() | +| conversions.swift:39:20:39:35 | .utf8 | semmle.label | .utf8 | | conversions.swift:41:13:41:23 | call to sourceInt() | semmle.label | call to sourceInt() | | conversions.swift:42:13:42:13 | v | semmle.label | v | | conversions.swift:45:18:45:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) | @@ -346,6 +359,8 @@ subpaths | conversions.swift:30:12:30:30 | call to String.init(_:) | conversions.swift:30:19:30:29 | call to sourceInt() | conversions.swift:30:12:30:30 | call to String.init(_:) | result | | conversions.swift:31:12:31:32 | .utf8 | conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:32 | .utf8 | result | | conversions.swift:35:12:35:17 | ...[...] | conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:35:12:35:17 | ...[...] | result | +| conversions.swift:37:12:37:26 | ...[...] | conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:37:12:37:26 | ...[...] | result | +| conversions.swift:39:12:39:42 | ...[...] | conversions.swift:39:20:39:33 | call to sourceString() | conversions.swift:39:12:39:42 | ...[...] | result | | conversions.swift:42:13:42:13 | v | conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:42:13:42:13 | v | result | | conversions.swift:46:12:46:12 | v2 | conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:46:12:46:12 | v2 | result | | conversions.swift:49:12:49:12 | v4 | conversions.swift:48:31:48:41 | call to sourceInt() | conversions.swift:49:12:49:12 | v4 | result | diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift index efb0bba4ed2..e24c8347251 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift +++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift @@ -34,9 +34,9 @@ func testConversions() { sink(arg: arr) sink(arg: arr[0]) // $ tainted=33 sink(arg: [MyInt](arr)) - sink(arg: [MyInt](arr)[0]) // $ MISSING: tainted=33 + sink(arg: [MyInt](arr)[0]) // $ tainted=33 sink(arg: [UInt8](sourceString().utf8)) - sink(arg: [UInt8](sourceString().utf8)[0]) // $ MISSING: tainted=33 + sink(arg: [UInt8](sourceString().utf8)[0]) // $ tainted=39 if let v = sourceInt() as? UInt { sink(arg: v) // $ tainted=41 From 60dc1afbc06358070edf1c28a875917d97194c38 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 15 Aug 2023 10:01:20 +0200 Subject: [PATCH 010/325] Python: prepare to promote NoSqlInjection Mostly move files, preserving authourship. This will not compile. --- python/ql/lib/semmle/python/Frameworks.qll | 1 + .../{src/experimental => lib}/semmle/python/frameworks/NoSQL.qll | 0 .../semmle/python/security/dataflow}/NoSQLInjection.qll | 0 .../src/{experimental => }/Security/CWE-943/NoSQLInjection.qhelp | 0 .../ql/src/{experimental => }/Security/CWE-943/NoSQLInjection.ql | 0 .../Security/CWE-943/examples/NoSQLInjection-bad.py | 0 .../Security/CWE-943/examples/NoSQLInjection-good.py | 0 python/ql/src/experimental/semmle/python/Frameworks.qll | 1 - .../query-tests/Security/CWE-943/NoSQLInjection.expected | 0 .../query-tests/Security/CWE-943/NoSQLInjection.qlref | 0 .../query-tests/Security/CWE-943/flask_mongoengine_bad.py | 0 .../query-tests/Security/CWE-943/flask_mongoengine_good.py | 0 .../query-tests/Security/CWE-943/flask_pymongo_bad.py | 0 .../query-tests/Security/CWE-943/flask_pymongo_good.py | 0 .../query-tests/Security/CWE-943/mongoengine_bad.py | 0 .../query-tests/Security/CWE-943/mongoengine_good.py | 0 .../query-tests/Security/CWE-943/pymongo_test.py | 0 17 files changed, 1 insertion(+), 1 deletion(-) rename python/ql/{src/experimental => lib}/semmle/python/frameworks/NoSQL.qll (100%) rename python/ql/{src/experimental/semmle/python/security/injection => lib/semmle/python/security/dataflow}/NoSQLInjection.qll (100%) rename python/ql/src/{experimental => }/Security/CWE-943/NoSQLInjection.qhelp (100%) rename python/ql/src/{experimental => }/Security/CWE-943/NoSQLInjection.ql (100%) rename python/ql/src/{experimental => }/Security/CWE-943/examples/NoSQLInjection-bad.py (100%) rename python/ql/src/{experimental => }/Security/CWE-943/examples/NoSQLInjection-good.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-943/NoSQLInjection.expected (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-943/NoSQLInjection.qlref (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-943/flask_mongoengine_bad.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-943/flask_mongoengine_good.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-943/flask_pymongo_bad.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-943/flask_pymongo_good.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-943/mongoengine_bad.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-943/mongoengine_good.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-943/pymongo_test.py (100%) diff --git a/python/ql/lib/semmle/python/Frameworks.qll b/python/ql/lib/semmle/python/Frameworks.qll index 82cb69679cb..171918349c6 100644 --- a/python/ql/lib/semmle/python/Frameworks.qll +++ b/python/ql/lib/semmle/python/Frameworks.qll @@ -36,6 +36,7 @@ private import semmle.python.frameworks.MarkupSafe private import semmle.python.frameworks.Multidict private import semmle.python.frameworks.Mysql private import semmle.python.frameworks.MySQLdb +private import semmle.python.frameworks.NoSQL private import semmle.python.frameworks.Oracledb private import semmle.python.frameworks.Peewee private import semmle.python.frameworks.Phoenixdb diff --git a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll b/python/ql/lib/semmle/python/frameworks/NoSQL.qll similarity index 100% rename from python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll rename to python/ql/lib/semmle/python/frameworks/NoSQL.qll diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjection.qll similarity index 100% rename from python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll rename to python/ql/lib/semmle/python/security/dataflow/NoSQLInjection.qll diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp b/python/ql/src/Security/CWE-943/NoSQLInjection.qhelp similarity index 100% rename from python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp rename to python/ql/src/Security/CWE-943/NoSQLInjection.qhelp diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/Security/CWE-943/NoSQLInjection.ql similarity index 100% rename from python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql rename to python/ql/src/Security/CWE-943/NoSQLInjection.ql diff --git a/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-bad.py b/python/ql/src/Security/CWE-943/examples/NoSQLInjection-bad.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-bad.py rename to python/ql/src/Security/CWE-943/examples/NoSQLInjection-bad.py diff --git a/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-good.py b/python/ql/src/Security/CWE-943/examples/NoSQLInjection-good.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-good.py rename to python/ql/src/Security/CWE-943/examples/NoSQLInjection-good.py diff --git a/python/ql/src/experimental/semmle/python/Frameworks.qll b/python/ql/src/experimental/semmle/python/Frameworks.qll index 98fb86f6d92..2fc78b7f53b 100644 --- a/python/ql/src/experimental/semmle/python/Frameworks.qll +++ b/python/ql/src/experimental/semmle/python/Frameworks.qll @@ -7,7 +7,6 @@ private import experimental.semmle.python.frameworks.Flask private import experimental.semmle.python.frameworks.Django private import experimental.semmle.python.frameworks.Werkzeug private import experimental.semmle.python.frameworks.LDAP -private import experimental.semmle.python.frameworks.NoSQL private import experimental.semmle.python.frameworks.JWT private import experimental.semmle.python.frameworks.Csv private import experimental.semmle.python.libraries.PyJWT diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.expected similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected rename to python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.expected diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.qlref b/python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.qlref similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.qlref rename to python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.qlref diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py b/python/ql/test/query-tests/Security/CWE-943/flask_mongoengine_bad.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py rename to python/ql/test/query-tests/Security/CWE-943/flask_mongoengine_bad.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/query-tests/Security/CWE-943/flask_mongoengine_good.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py rename to python/ql/test/query-tests/Security/CWE-943/flask_mongoengine_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py b/python/ql/test/query-tests/Security/CWE-943/flask_pymongo_bad.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py rename to python/ql/test/query-tests/Security/CWE-943/flask_pymongo_bad.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py b/python/ql/test/query-tests/Security/CWE-943/flask_pymongo_good.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py rename to python/ql/test/query-tests/Security/CWE-943/flask_pymongo_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py b/python/ql/test/query-tests/Security/CWE-943/mongoengine_bad.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py rename to python/ql/test/query-tests/Security/CWE-943/mongoengine_bad.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/query-tests/Security/CWE-943/mongoengine_good.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py rename to python/ql/test/query-tests/Security/CWE-943/mongoengine_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_test.py b/python/ql/test/query-tests/Security/CWE-943/pymongo_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_test.py rename to python/ql/test/query-tests/Security/CWE-943/pymongo_test.py From 55707d395e4949640e6b523414988f28d8cfd2a5 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 15 Aug 2023 10:34:43 +0200 Subject: [PATCH 011/325] Python: Make things compile in their new location - Move NoSQL concepts to the non-experimental concepts file - fix references --- python/ql/lib/semmle/python/Concepts.qll | 50 +++++++++++++++++++ .../ql/lib/semmle/python/frameworks/NoSQL.qll | 2 +- .../security/dataflow/NoSQLInjection.qll | 1 - .../ql/src/Security/CWE-943/NoSQLInjection.ql | 2 +- .../experimental/semmle/python/Concepts.qll | 50 ------------------- .../Security/CWE-943/NoSQLInjection.qlref | 2 +- 6 files changed, 53 insertions(+), 54 deletions(-) diff --git a/python/ql/lib/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll index f3026d8faad..0a7b6744016 100644 --- a/python/ql/lib/semmle/python/Concepts.qll +++ b/python/ql/lib/semmle/python/Concepts.qll @@ -378,6 +378,56 @@ module SqlExecution { } } +/** Provides a class for modeling NoSql execution APIs. */ +module NoSqlQuery { + /** + * A data-flow node that executes NoSQL queries. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `NoSQLQuery` instead. + */ + abstract class Range extends DataFlow::Node { + /** Gets the argument that specifies the NoSql query to be executed. */ + abstract DataFlow::Node getQuery(); + } +} + +/** + * A data-flow node that executes NoSQL queries. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `NoSQLQuery::Range` instead. + */ +class NoSqlQuery extends DataFlow::Node instanceof NoSqlQuery::Range { + /** Gets the argument that specifies the NoSql query to be executed. */ + DataFlow::Node getQuery() { result = super.getQuery() } +} + +/** Provides classes for modeling NoSql sanitization-related APIs. */ +module NoSqlSanitizer { + /** + * A data-flow node that collects functions sanitizing NoSQL queries. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `NoSQLSanitizer` instead. + */ + abstract class Range extends DataFlow::Node { + /** Gets the argument that specifies the NoSql query to be sanitized. */ + abstract DataFlow::Node getAnInput(); + } +} + +/** + * A data-flow node that collects functions sanitizing NoSQL queries. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `NoSQLSanitizer::Range` instead. + */ +class NoSqlSanitizer extends DataFlow::Node instanceof NoSqlSanitizer::Range { + /** Gets the argument that specifies the NoSql query to be sanitized. */ + DataFlow::Node getAnInput() { result = super.getAnInput() } +} + /** * A data-flow node that executes a regular expression. * diff --git a/python/ql/lib/semmle/python/frameworks/NoSQL.qll b/python/ql/lib/semmle/python/frameworks/NoSQL.qll index ed0ce0315df..fafc555a638 100644 --- a/python/ql/lib/semmle/python/frameworks/NoSQL.qll +++ b/python/ql/lib/semmle/python/frameworks/NoSQL.qll @@ -7,7 +7,7 @@ private import python private import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.TaintTracking private import semmle.python.dataflow.new.RemoteFlowSources -private import experimental.semmle.python.Concepts +private import semmle.python.Concepts private import semmle.python.ApiGraphs private module NoSql { diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjection.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjection.qll index f7a40fb3ee6..6c1a52efe68 100644 --- a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjection.qll +++ b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjection.qll @@ -2,7 +2,6 @@ import python import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TaintTracking import semmle.python.dataflow.new.RemoteFlowSources -import experimental.semmle.python.Concepts import semmle.python.Concepts module NoSqlInjection { diff --git a/python/ql/src/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/Security/CWE-943/NoSQLInjection.ql index a73202ca082..2d9dbc0bb6d 100644 --- a/python/ql/src/Security/CWE-943/NoSQLInjection.ql +++ b/python/ql/src/Security/CWE-943/NoSQLInjection.ql @@ -11,7 +11,7 @@ */ import python -import experimental.semmle.python.security.injection.NoSQLInjection +import semmle.python.security.dataflow.NoSQLInjection import DataFlow::PathGraph from NoSqlInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 3331e1117e0..a289cedb6df 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -216,56 +216,6 @@ class SqlEscape extends DataFlow::Node instanceof SqlEscape::Range { DataFlow::Node getAnInput() { result = super.getAnInput() } } -/** Provides a class for modeling NoSql execution APIs. */ -module NoSqlQuery { - /** - * A data-flow node that executes NoSQL queries. - * - * Extend this class to model new APIs. If you want to refine existing API models, - * extend `NoSQLQuery` instead. - */ - abstract class Range extends DataFlow::Node { - /** Gets the argument that specifies the NoSql query to be executed. */ - abstract DataFlow::Node getQuery(); - } -} - -/** - * A data-flow node that executes NoSQL queries. - * - * Extend this class to refine existing API models. If you want to model new APIs, - * extend `NoSQLQuery::Range` instead. - */ -class NoSqlQuery extends DataFlow::Node instanceof NoSqlQuery::Range { - /** Gets the argument that specifies the NoSql query to be executed. */ - DataFlow::Node getQuery() { result = super.getQuery() } -} - -/** Provides classes for modeling NoSql sanitization-related APIs. */ -module NoSqlSanitizer { - /** - * A data-flow node that collects functions sanitizing NoSQL queries. - * - * Extend this class to model new APIs. If you want to refine existing API models, - * extend `NoSQLSanitizer` instead. - */ - abstract class Range extends DataFlow::Node { - /** Gets the argument that specifies the NoSql query to be sanitized. */ - abstract DataFlow::Node getAnInput(); - } -} - -/** - * A data-flow node that collects functions sanitizing NoSQL queries. - * - * Extend this class to model new APIs. If you want to refine existing API models, - * extend `NoSQLSanitizer::Range` instead. - */ -class NoSqlSanitizer extends DataFlow::Node instanceof NoSqlSanitizer::Range { - /** Gets the argument that specifies the NoSql query to be sanitized. */ - DataFlow::Node getAnInput() { result = super.getAnInput() } -} - /** Provides classes for modeling HTTP Header APIs. */ module HeaderDeclaration { /** diff --git a/python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.qlref b/python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.qlref index 3ca00df892b..a3f577c4cdc 100644 --- a/python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.qlref +++ b/python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.qlref @@ -1 +1 @@ -experimental/Security/CWE-943/NoSQLInjection.ql +Security/CWE-943/NoSQLInjection.ql From db0459739f5b837a008816475ccd3632eefef6de Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 23 Aug 2023 13:48:43 +0200 Subject: [PATCH 012/325] Python: rename file --- .../dataflow/{NoSQLInjection.qll => NoSQLInjectionQuery.qll} | 0 python/ql/src/Security/CWE-943/NoSQLInjection.ql | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename python/ql/lib/semmle/python/security/dataflow/{NoSQLInjection.qll => NoSQLInjectionQuery.qll} (100%) diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjection.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll similarity index 100% rename from python/ql/lib/semmle/python/security/dataflow/NoSQLInjection.qll rename to python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll diff --git a/python/ql/src/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/Security/CWE-943/NoSQLInjection.ql index 2d9dbc0bb6d..bfa753e78a8 100644 --- a/python/ql/src/Security/CWE-943/NoSQLInjection.ql +++ b/python/ql/src/Security/CWE-943/NoSQLInjection.ql @@ -11,7 +11,7 @@ */ import python -import semmle.python.security.dataflow.NoSQLInjection +import semmle.python.security.dataflow.NoSQLInjectionQuery import DataFlow::PathGraph from NoSqlInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink From 087961d179fa9809bf379aff916644605654fe6b Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 23 Aug 2023 15:03:37 +0200 Subject: [PATCH 013/325] Python: Refactor to allow customizations Also use new DataFlow API --- .../dataflow/NoSQLInjectionCustomizations.qll | 50 ++++++++++++ .../security/dataflow/NoSQLInjectionQuery.qll | 77 +++++++++---------- .../ql/src/Security/CWE-943/NoSQLInjection.ql | 8 +- 3 files changed, 90 insertions(+), 45 deletions(-) create mode 100644 python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll new file mode 100644 index 00000000000..eb7516f8fa0 --- /dev/null +++ b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll @@ -0,0 +1,50 @@ +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.RemoteFlowSources +import semmle.python.Concepts + +module NoSqlInjection { + private newtype TFlowState = + TStringInput() or + TDictInput() + + abstract class FlowState extends TFlowState { + abstract string toString(); + } + + class StringInput extends FlowState, TStringInput { + override string toString() { result = "StringInput" } + } + + class DictInput extends FlowState, TDictInput { + override string toString() { result = "DictInput" } + } + + abstract class StringSource extends DataFlow::Node { } + + abstract class DictSource extends DataFlow::Node { } + + abstract class StringSink extends DataFlow::Node { } + + abstract class DictSink extends DataFlow::Node { } + + abstract class StringToDictConversion extends DataFlow::Node { + abstract DataFlow::Node getAnInput(); + + abstract DataFlow::Node getOutput(); + } + + class RemoteFlowSourceAsStringSource extends RemoteFlowSource, StringSource { } + + class NoSqlQueryAsDictSink extends DictSink { + NoSqlQueryAsDictSink() { this = any(NoSqlQuery noSqlQuery).getQuery() } + } + + class JsonDecoding extends Decoding, StringToDictConversion { + JsonDecoding() { this.getFormat() = "JSON" } + + override DataFlow::Node getAnInput() { result = Decoding.super.getAnInput() } + + override DataFlow::Node getOutput() { result = Decoding.super.getOutput() } + } +} diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll index 6c1a52efe68..0f5748a9ecc 100644 --- a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll +++ b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll @@ -1,53 +1,48 @@ import python import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TaintTracking -import semmle.python.dataflow.new.RemoteFlowSources import semmle.python.Concepts +private import NoSQLInjectionCustomizations::NoSqlInjection as C -module NoSqlInjection { - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "NoSQLInjection" } +module Config implements DataFlow::StateConfigSig { + class FlowState = C::FlowState; - override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { - source instanceof RemoteFlowSource and - state instanceof RemoteInput - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { - sink = any(NoSqlQuery noSqlQuery).getQuery() and - state instanceof ConvertedToDict - } - - override predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { - // Block `RemoteInput` paths here, since they change state to `ConvertedToDict` - exists(Decoding decoding | decoding.getFormat() = "JSON" and node = decoding.getOutput()) and - state instanceof RemoteInput - } - - override predicate isAdditionalTaintStep( - DataFlow::Node nodeFrom, DataFlow::FlowState stateFrom, DataFlow::Node nodeTo, - DataFlow::FlowState stateTo - ) { - exists(Decoding decoding | decoding.getFormat() = "JSON" | - nodeFrom = decoding.getAnInput() and - nodeTo = decoding.getOutput() - ) and - stateFrom instanceof RemoteInput and - stateTo instanceof ConvertedToDict - } - - override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer = any(NoSqlSanitizer noSqlSanitizer).getAnInput() - } + predicate isSource(DataFlow::Node source, FlowState state) { + source instanceof C::StringSource and + state instanceof C::StringInput + or + source instanceof C::DictSource and + state instanceof C::DictInput } - /** A flow state signifying remote input. */ - class RemoteInput extends DataFlow::FlowState { - RemoteInput() { this = "RemoteInput" } + predicate isSink(DataFlow::Node source, FlowState state) { + source instanceof C::StringSink and + state instanceof C::StringInput + or + source instanceof C::DictSink and + state instanceof C::DictInput } - /** A flow state signifying remote input converted to a dictionary. */ - class ConvertedToDict extends DataFlow::FlowState { - ConvertedToDict() { this = "ConvertedToDict" } + predicate isBarrier(DataFlow::Node node, FlowState state) { + // Block `StringInput` paths here, since they change state to `DictInput` + exists(C::StringToDictConversion c | node = c.getOutput()) and + state instanceof C::StringInput + } + + predicate isAdditionalFlowStep( + DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo + ) { + exists(C::StringToDictConversion c | + nodeFrom = c.getAnInput() and + nodeTo = c.getOutput() + ) and + stateFrom instanceof C::StringInput and + stateTo instanceof C::DictInput + } + + predicate isBarrier(DataFlow::Node node) { + node = any(NoSqlSanitizer noSqlSanitizer).getAnInput() } } + +module Flow = TaintTracking::GlobalWithState; diff --git a/python/ql/src/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/Security/CWE-943/NoSQLInjection.ql index bfa753e78a8..fd588f009f0 100644 --- a/python/ql/src/Security/CWE-943/NoSQLInjection.ql +++ b/python/ql/src/Security/CWE-943/NoSQLInjection.ql @@ -12,9 +12,9 @@ import python import semmle.python.security.dataflow.NoSQLInjectionQuery -import DataFlow::PathGraph +import Flow::PathGraph -from NoSqlInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) -select sink, source, sink, "This NoSQL query contains an unsanitized $@.", source, +from Flow::PathNode source, Flow::PathNode sink +where Flow::flowPath(source, sink) +select sink.getNode(), source, sink, "This NoSQL query contains an unsanitized $@.", source, "user-provided value" From 19046ea417e1efae5308c17012d974ca5b1a0762 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 23 Aug 2023 19:58:18 +0200 Subject: [PATCH 014/325] Python: more renames --- .../NoSqlInjection.expected} | 0 .../NoSqlInjection.qlref} | 0 .../{CWE-943 => CWE-943-NoSqlInjection}/flask_mongoengine_bad.py | 0 .../{CWE-943 => CWE-943-NoSqlInjection}/flask_mongoengine_good.py | 0 .../{CWE-943 => CWE-943-NoSqlInjection}/flask_pymongo_bad.py | 0 .../{CWE-943 => CWE-943-NoSqlInjection}/flask_pymongo_good.py | 0 .../{CWE-943 => CWE-943-NoSqlInjection}/mongoengine_bad.py | 0 .../{CWE-943 => CWE-943-NoSqlInjection}/mongoengine_good.py | 0 .../Security/{CWE-943 => CWE-943-NoSqlInjection}/pymongo_test.py | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename python/ql/test/query-tests/Security/{CWE-943/NoSQLInjection.expected => CWE-943-NoSqlInjection/NoSqlInjection.expected} (100%) rename python/ql/test/query-tests/Security/{CWE-943/NoSQLInjection.qlref => CWE-943-NoSqlInjection/NoSqlInjection.qlref} (100%) rename python/ql/test/query-tests/Security/{CWE-943 => CWE-943-NoSqlInjection}/flask_mongoengine_bad.py (100%) rename python/ql/test/query-tests/Security/{CWE-943 => CWE-943-NoSqlInjection}/flask_mongoengine_good.py (100%) rename python/ql/test/query-tests/Security/{CWE-943 => CWE-943-NoSqlInjection}/flask_pymongo_bad.py (100%) rename python/ql/test/query-tests/Security/{CWE-943 => CWE-943-NoSqlInjection}/flask_pymongo_good.py (100%) rename python/ql/test/query-tests/Security/{CWE-943 => CWE-943-NoSqlInjection}/mongoengine_bad.py (100%) rename python/ql/test/query-tests/Security/{CWE-943 => CWE-943-NoSqlInjection}/mongoengine_good.py (100%) rename python/ql/test/query-tests/Security/{CWE-943 => CWE-943-NoSqlInjection}/pymongo_test.py (100%) diff --git a/python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.expected rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected diff --git a/python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.qlref b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943/NoSQLInjection.qlref rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.qlref diff --git a/python/ql/test/query-tests/Security/CWE-943/flask_mongoengine_bad.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_bad.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943/flask_mongoengine_bad.py rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_bad.py diff --git a/python/ql/test/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_good.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943/flask_mongoengine_good.py rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_good.py diff --git a/python/ql/test/query-tests/Security/CWE-943/flask_pymongo_bad.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_bad.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943/flask_pymongo_bad.py rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_bad.py diff --git a/python/ql/test/query-tests/Security/CWE-943/flask_pymongo_good.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_good.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943/flask_pymongo_good.py rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_good.py diff --git a/python/ql/test/query-tests/Security/CWE-943/mongoengine_bad.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_bad.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943/mongoengine_bad.py rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_bad.py diff --git a/python/ql/test/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_good.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943/mongoengine_good.py rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_good.py diff --git a/python/ql/test/query-tests/Security/CWE-943/pymongo_test.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/pymongo_test.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943/pymongo_test.py rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/pymongo_test.py From bf8bfd91cd6e47c068a2e5bc31cf82513d2a1140 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 7 Sep 2023 10:22:30 +0200 Subject: [PATCH 015/325] Python: Add inline query test --- .../DataflowQueryTest.expected | 3 +++ .../CWE-943-NoSqlInjection/DataflowQueryTest.ql | 4 ++++ .../CWE-943-NoSqlInjection/flask_mongoengine_bad.py | 4 ++-- .../CWE-943-NoSqlInjection/flask_mongoengine_good.py | 2 +- .../CWE-943-NoSqlInjection/flask_pymongo_bad.py | 2 +- .../CWE-943-NoSqlInjection/flask_pymongo_good.py | 2 +- .../CWE-943-NoSqlInjection/mongoengine_bad.py | 12 ++++++------ .../CWE-943-NoSqlInjection/mongoengine_good.py | 2 +- .../Security/CWE-943-NoSqlInjection/pymongo_test.py | 8 ++++---- 9 files changed, 23 insertions(+), 16 deletions(-) create mode 100644 python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.expected create mode 100644 python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.ql diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.expected b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.expected new file mode 100644 index 00000000000..303d04688ff --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.expected @@ -0,0 +1,3 @@ +failures +missingAnnotationOnSink +testFailures diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.ql b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.ql new file mode 100644 index 00000000000..f3709acc913 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.ql @@ -0,0 +1,4 @@ +import python +import experimental.dataflow.TestUtil.DataflowQueryTest +import semmle.python.security.dataflow.NoSQLInjectionQuery +import FromTaintTrackingStateConfig diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_bad.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_bad.py index 9fc8aaefc0f..76ac28edf79 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_bad.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_bad.py @@ -19,7 +19,7 @@ def subclass_objects(): unsafe_search = request.args['search'] json_search = json.loads(unsafe_search) - return Movie.objects(__raw__=json_search) + return Movie.objects(__raw__=json_search) #$ result=BAD @app.route("/get_db_find") def get_db_find(): @@ -27,7 +27,7 @@ def get_db_find(): json_search = json.loads(unsafe_search) retrieved_db = db.get_db() - return retrieved_db["Movie"].find({'name': json_search}) + return retrieved_db["Movie"].find({'name': json_search}) #$ result=BAD # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_good.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_good.py index 29a2c75d664..1ce065569f2 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_good.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_mongoengine_good.py @@ -21,7 +21,7 @@ def subclass_objects(): json_search = json.loads(unsafe_search) safe_search = sanitize(json_search) - return Movie.objects(__raw__=safe_search) + return Movie.objects(__raw__=safe_search) #$ result=OK # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_bad.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_bad.py index 0c1023971da..735fbff9b34 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_bad.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_bad.py @@ -11,7 +11,7 @@ def home_page(): unsafe_search = request.args['search'] json_search = json.loads(unsafe_search) - return mongo.db.user.find({'name': json_search}) + return mongo.db.user.find({'name': json_search}) #$ result=BAD # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_good.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_good.py index 6576ba88af8..f2458f91b89 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_good.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/flask_pymongo_good.py @@ -13,7 +13,7 @@ def home_page(): json_search = json.loads(unsafe_search) safe_search = sanitize(json_search) - return mongo.db.user.find({'name': safe_search}) + return mongo.db.user.find({'name': safe_search}) #$ result=OK # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_bad.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_bad.py index 81800425e46..4367f9e1ff7 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_bad.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_bad.py @@ -19,7 +19,7 @@ def connect_find(): json_search = json.loads(unsafe_search) db = me.connect('mydb') - return db.movie.find({'name': json_search}) + return db.movie.find({'name': json_search}) #$ result=BAD @app.route("/connection_connect_find") def connection_connect_find(): @@ -27,7 +27,7 @@ def connection_connect_find(): json_search = json.loads(unsafe_search) db = connect('mydb') - return db.movie.find({'name': json_search}) + return db.movie.find({'name': json_search}) #$ result=BAD @app.route("/get_db_find") def get_db_find(): @@ -35,7 +35,7 @@ def get_db_find(): json_search = json.loads(unsafe_search) db = me.get_db() - return db.movie.find({'name': json_search}) + return db.movie.find({'name': json_search}) #$ result=BAD @app.route("/connection_get_db_find") def connection_get_db_find(): @@ -43,14 +43,14 @@ def connection_get_db_find(): json_search = json.loads(unsafe_search) db = get_db() - return db.movie.find({'name': json_search}) + return db.movie.find({'name': json_search}) #$ result=BAD @app.route("/subclass_objects") def subclass_objects(): unsafe_search = request.args['search'] json_search = json.loads(unsafe_search) - return Movie.objects(__raw__=json_search) + return Movie.objects(__raw__=json_search) #$ result=BAD @app.route("/subscript_find") def subscript_find(): @@ -58,7 +58,7 @@ def subscript_find(): json_search = json.loads(unsafe_search) db = me.connect('mydb') - return db['movie'].find({'name': json_search}) + return db['movie'].find({'name': json_search}) #$ result=BAD # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_good.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_good.py index c9b2b8e762f..e8ac68cccba 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_good.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/mongoengine_good.py @@ -21,7 +21,7 @@ def connect_find(): safe_search = sanitize(json_search) db = me.connect('mydb') - return db.movie.find({'name': safe_search}) + return db.movie.find({'name': safe_search}) #$ result=OK # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/pymongo_test.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/pymongo_test.py index ecf53ec4f9a..3dd667a3f2d 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/pymongo_test.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/pymongo_test.py @@ -12,7 +12,7 @@ def bad(): unsafe_search = request.args['search'] json_search = json.loads(unsafe_search) - return client.db.collection.find_one({'data': json_search}) + return client.db.collection.find_one({'data': json_search}) #$ result=BAD @app.route("/good") @@ -21,7 +21,7 @@ def good(): json_search = json.loads(unsafe_search) safe_search = sanitize(json_search) - return client.db.collection.find_one({'data': safe_search}) + return client.db.collection.find_one({'data': safe_search}) #$ result=OK @app.route("/bad2") @@ -30,7 +30,7 @@ def bad2(): client = MongoClient("localhost", 27017, maxPoolSize=50) db = client.localhost collection = db['collection'] - cursor = collection.find_one({"$where": f"this._id == '${event_id}'"}) + cursor = collection.find_one({"$where": f"this._id == '${event_id}'"}) #$ result=BAD @app.route("/bad3") @@ -40,7 +40,7 @@ def bad3(): client = MongoClient("localhost", 27017, maxPoolSize=50) db = client.get_database(name="localhost") collection = db.get_collection("collection") - cursor = collection.find_one({"$where": f"this._id == '${event_id}'"}) + cursor = collection.find_one({"$where": f"this._id == '${event_id}'"}) #$ result=BAD if __name__ == "__main__": From 114984bd8cb92ba8f06dbb3902eb48d3481a1a67 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 29 Aug 2023 16:16:38 +0200 Subject: [PATCH 016/325] Python: Added tests based on security analysis currently we do not: - recognize the pattern `{'author': {"$eq": author}}` as protected - recognize arguements to `$where` (and friends) as vulnerable --- .../CWE-943-NoSqlInjection/PoC/populate.py | 16 ++++++ .../CWE-943-NoSqlInjection/PoC/readme.md | 19 +++++++ .../PoC/requirements.txt | 2 + .../CWE-943-NoSqlInjection/PoC/server.py | 55 +++++++++++++++++++ .../Security/CWE-943-NoSqlInjection/options | 1 + 5 files changed, 93 insertions(+) create mode 100644 python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/populate.py create mode 100644 python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/readme.md create mode 100644 python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/requirements.txt create mode 100644 python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py create mode 100644 python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/options diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/populate.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/populate.py new file mode 100644 index 00000000000..026f72bdfe5 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/populate.py @@ -0,0 +1,16 @@ +from pymongo import MongoClient +client = MongoClient() + +db = client.test_database + +import datetime +post = { + "author": "Mike", + "text": "My first blog post!", + "tags": ["mongodb", "python", "pymongo"], + "date": datetime.datetime.now(tz=datetime.timezone.utc), +} + +posts = db.posts +post_id = posts.insert_one(post).inserted_id +post_id diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/readme.md b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/readme.md new file mode 100644 index 00000000000..78e7e92e48f --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/readme.md @@ -0,0 +1,19 @@ +Tutorials: +- [pymongo](https://pymongo.readthedocs.io/en/stable/tutorial.html) +- [install mongodb](https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-os-x/#std-label-install-mdb-community-macos) + +I recommend creating a virtual environment with venv and then installing dependencies via +``` +python -m pip --install -r requirements.txt +``` + +Start mongodb: +``` +mongod --config /usr/local/etc/mongod.conf --fork +``` +run flask app: +``` +flask --app server run +``` + +Navigate to the root to see routes. For each route try to get the system to reveal the person in the database. If you know the name, you can just input it, but in some cases you can get to the person without knowing the name! diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/requirements.txt b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/requirements.txt new file mode 100644 index 00000000000..a98715ed1e4 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/requirements.txt @@ -0,0 +1,2 @@ +flask +pymongo diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py new file mode 100644 index 00000000000..59b51963583 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py @@ -0,0 +1,55 @@ +from flask import Flask, request +from pymongo import MongoClient +import json + +client = MongoClient() +db = client.test_database +posts = db.posts + +app = Flask(__name__) + + +def show_post(post, query): + if post: + return "You found " + post['author'] + "!" + else: + return "You did not find " + query + +@app.route('/plain', methods=['GET']) +def plain(): + author = request.args['author'] + post = posts.find_one({'author': author}) # $ result=OK + return show_post(post, author) + +@app.route('/dict', methods=['GET']) +def as_dict(): + author_string = request.args['author'] + author = json.loads(author_string) + # Use {"$ne": 1} as author + # Found by http://127.0.0.1:5000/dict?author={%22$ne%22:1} + post = posts.find_one({'author': author}) # $ result=BAD + return show_post(post, author) + +@app.route('/dictHardened', methods=['GET']) +def as_dict_hardened(): + author_string = request.args['author'] + author = json.loads(author_string) + post = posts.find_one({'author': {"$eq": author}}) # $ SPURIOUS: result=BAD + return show_post(post, author) + +@app.route('/byWhere', methods=['GET']) +def by_where(): + author = request.args['author'] + # Use `" | "a" === "a` as author + # making the query `this.author === "" | "a" === "a"` + # Found by http://127.0.0.1:5000/byWhere?author=%22%20|%20%22a%22%20===%20%22a + post = posts.find_one({'$where': 'this.author === "'+author+'"'}) # $ MISSING: result=BAD + return show_post(post, author) + +@app.route('/', methods=['GET']) +def show_routes(): + links = [] + for rule in app.url_map.iter_rules(): + if "GET" in rule.methods: + links.append((rule.rule, rule.endpoint)) + return links diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/options b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/options new file mode 100644 index 00000000000..48ecb907736 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/options @@ -0,0 +1 @@ +semmle-extractor-options: --max-import-depth=1 -r PoC From c0b3245a5393306660a04026357cf1ae2eb2a4e2 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 31 Aug 2023 20:30:03 +0200 Subject: [PATCH 017/325] Python: Enrich the NoSql concept This allows us to make more precise modelling The query tests now pass. I do wonder, if there is a cleaner approach, similar to `TaintedObject` in JavaScript. I want the option to get this query in the hands of the custumors before such an investigation, though. --- python/ql/lib/semmle/python/Concepts.qll | 12 ++++ .../ql/lib/semmle/python/frameworks/NoSQL.qll | 61 ++++++++++++++++--- .../dataflow/NoSQLInjectionCustomizations.qll | 8 +++ .../security/dataflow/NoSQLInjectionQuery.qll | 7 ++- .../CWE-943-NoSqlInjection/PoC/server.py | 4 +- 5 files changed, 80 insertions(+), 12 deletions(-) diff --git a/python/ql/lib/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll index 0a7b6744016..ea6310e326c 100644 --- a/python/ql/lib/semmle/python/Concepts.qll +++ b/python/ql/lib/semmle/python/Concepts.qll @@ -389,6 +389,12 @@ module NoSqlQuery { abstract class Range extends DataFlow::Node { /** Gets the argument that specifies the NoSql query to be executed. */ abstract DataFlow::Node getQuery(); + + /** Holds if this query will unpack/interpret a dictionary */ + abstract predicate interpretsDict(); + + /** Holds if this query can be dangerous when run on a user-controlled string */ + abstract predicate vulnerableToStrings(); } } @@ -401,6 +407,12 @@ module NoSqlQuery { class NoSqlQuery extends DataFlow::Node instanceof NoSqlQuery::Range { /** Gets the argument that specifies the NoSql query to be executed. */ DataFlow::Node getQuery() { result = super.getQuery() } + + /** Holds if this query will unpack/interpret a dictionary */ + predicate interpretsDict() { super.interpretsDict() } + + /** Holds if this query can be dangerous when run on a user-controlled string */ + predicate vulnerableToStrings() { super.vulnerableToStrings() } } /** Provides classes for modeling NoSql sanitization-related APIs. */ diff --git a/python/ql/lib/semmle/python/frameworks/NoSQL.qll b/python/ql/lib/semmle/python/frameworks/NoSQL.qll index fafc555a638..ba17d593a60 100644 --- a/python/ql/lib/semmle/python/frameworks/NoSQL.qll +++ b/python/ql/lib/semmle/python/frameworks/NoSQL.qll @@ -91,16 +91,17 @@ private module NoSql { result = mongoDBInstance().getMember(["get_collection", "create_collection"]).getReturn() } - /** This class represents names of find_* relevant `Mongo` collection-level operation methods. */ - private class MongoCollectionMethodNames extends string { - MongoCollectionMethodNames() { - this in [ - "find", "find_raw_batches", "find_one", "find_one_and_delete", "find_and_modify", - "find_one_and_replace", "find_one_and_update", "find_one_or_404" - ] - } + /** Gets the name of a find_* relevant `Mongo` collection-level operation method. */ + private string mongoCollectionMethodName() { + result in [ + "find", "find_raw_batches", "find_one", "find_one_and_delete", "find_and_modify", + "find_one_and_replace", "find_one_and_update", "find_one_or_404" + ] } + /** Gets the name of a mongo query operator that will interpret JavaScript. */ + private string mongoQueryOperator() { result in ["$where", "$function"] } + /** * Gets a reference to a `Mongo` collection method call * @@ -114,10 +115,29 @@ private module NoSql { */ private class MongoCollectionCall extends DataFlow::CallCfgNode, NoSqlQuery::Range { MongoCollectionCall() { - this = mongoCollection().getMember(any(MongoCollectionMethodNames m)).getACall() + this = mongoCollection().getMember(mongoCollectionMethodName()).getACall() } override DataFlow::Node getQuery() { result = this.getArg(0) } + + override predicate interpretsDict() { any() } + + override predicate vulnerableToStrings() { none() } + } + + private class MongoCollectionQueryOperator extends API::CallNode, NoSqlQuery::Range { + DataFlow::Node query; + + MongoCollectionQueryOperator() { + this = mongoCollection().getMember(mongoCollectionMethodName()).getACall() and + query = this.getParameter(0).getSubscript(mongoQueryOperator()).asSink() + } + + override DataFlow::Node getQuery() { result = query } + + override predicate interpretsDict() { none() } + + override predicate vulnerableToStrings() { any() } } /** @@ -146,6 +166,10 @@ private module NoSql { } override DataFlow::Node getQuery() { result = this.getArgByName(_) } + + override predicate interpretsDict() { any() } + + override predicate vulnerableToStrings() { none() } } /** Gets a reference to `mongosanitizer.sanitizer.sanitize` */ @@ -176,4 +200,23 @@ private module NoSql { override DataFlow::Node getAnInput() { result = this.getArg(0) } } + + /** + * An equality operator can protect against dictionary interpretation. + * For instance, in `{'password': {"$eq": password} }`, if a dictionary is injected into + * `password`, it will not match. + */ + private class EqualityOperator extends DataFlow::Node, NoSqlSanitizer::Range { + EqualityOperator() { + this = + mongoCollection() + .getMember(mongoCollectionMethodName()) + .getParameter(0) + .getASubscript*() + .getSubscript("$eq") + .asSink() + } + + override DataFlow::Node getAnInput() { result = this } + } } diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll index eb7516f8fa0..54c85ccf195 100644 --- a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll @@ -36,6 +36,14 @@ module NoSqlInjection { class RemoteFlowSourceAsStringSource extends RemoteFlowSource, StringSource { } + class NoSqlQueryAsStringSink extends StringSink { + NoSqlQueryAsStringSink() { + exists(NoSqlQuery noSqlQuery | this = noSqlQuery.getQuery() | + noSqlQuery.vulnerableToStrings() + ) + } + } + class NoSqlQueryAsDictSink extends DictSink { NoSqlQueryAsDictSink() { this = any(NoSqlQuery noSqlQuery).getQuery() } } diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll index 0f5748a9ecc..8a0e31ed544 100644 --- a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll +++ b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll @@ -17,7 +17,12 @@ module Config implements DataFlow::StateConfigSig { predicate isSink(DataFlow::Node source, FlowState state) { source instanceof C::StringSink and - state instanceof C::StringInput + ( + state instanceof C::StringInput + or + // since dictionaries can encode strings + state instanceof C::DictInput + ) or source instanceof C::DictSink and state instanceof C::DictInput diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py index 59b51963583..f2b4a4f0a43 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py @@ -34,7 +34,7 @@ def as_dict(): def as_dict_hardened(): author_string = request.args['author'] author = json.loads(author_string) - post = posts.find_one({'author': {"$eq": author}}) # $ SPURIOUS: result=BAD + post = posts.find_one({'author': {"$eq": author}}) # $ result=OK return show_post(post, author) @app.route('/byWhere', methods=['GET']) @@ -43,7 +43,7 @@ def by_where(): # Use `" | "a" === "a` as author # making the query `this.author === "" | "a" === "a"` # Found by http://127.0.0.1:5000/byWhere?author=%22%20|%20%22a%22%20===%20%22a - post = posts.find_one({'$where': 'this.author === "'+author+'"'}) # $ MISSING: result=BAD + post = posts.find_one({'$where': 'this.author === "'+author+'"'}) # $ result=BAD return show_post(post, author) @app.route('/', methods=['GET']) From 7edebbeaffe10c5d8b7774666c34d8d58d6e194c Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 6 Sep 2023 11:46:49 +0200 Subject: [PATCH 018/325] Python: Add QLDocs --- .../dataflow/NoSQLInjectionCustomizations.qll | 26 +++++++++++++++++++ .../security/dataflow/NoSQLInjectionQuery.qll | 7 +++++ 2 files changed, 33 insertions(+) diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll index 54c85ccf195..d3348b8df8d 100644 --- a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll @@ -1,41 +1,65 @@ +/** + * Provides default sources, sinks and sanitizers for detecting + * "NoSql injection" + * vulnerabilities, as well as extension points for adding your own. + */ + import python import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.RemoteFlowSources import semmle.python.Concepts +/** + * Provides default sources, sinks and sanitizers for detecting + * "NoSql injection" + * vulnerabilities, as well as extension points for adding your own. + */ module NoSqlInjection { private newtype TFlowState = TStringInput() or TDictInput() + /** A flow state, tracking the structure of the input. */ abstract class FlowState extends TFlowState { + /** Gets a textual representation of this element. */ abstract string toString(); } + /** A state where input is only a string. */ class StringInput extends FlowState, TStringInput { override string toString() { result = "StringInput" } } + /** A state where input is a dictionary. */ class DictInput extends FlowState, TDictInput { override string toString() { result = "DictInput" } } + /** A source allowing string inputs. */ abstract class StringSource extends DataFlow::Node { } + /** A source allowing dictionary inputs. */ abstract class DictSource extends DataFlow::Node { } + /** A sink vulnerable to user controlled strings. */ abstract class StringSink extends DataFlow::Node { } + /** A sink vulnerable to user controlled dictionaries. */ abstract class DictSink extends DataFlow::Node { } + /** A data flow node where a string is converted into a dictionary. */ abstract class StringToDictConversion extends DataFlow::Node { + /** Gets the argument that specifies the string to be converted. */ abstract DataFlow::Node getAnInput(); + /** Gets the resulting dictionary. */ abstract DataFlow::Node getOutput(); } + /** A remote flow source considered a source of user controlled strings. */ class RemoteFlowSourceAsStringSource extends RemoteFlowSource, StringSource { } + /** A NoSQL query that is vulnerable to user controlled strings. */ class NoSqlQueryAsStringSink extends StringSink { NoSqlQueryAsStringSink() { exists(NoSqlQuery noSqlQuery | this = noSqlQuery.getQuery() | @@ -44,10 +68,12 @@ module NoSqlInjection { } } + /** A NoSQL query that is vulnerable to user controlled dictionaries. */ class NoSqlQueryAsDictSink extends DictSink { NoSqlQueryAsDictSink() { this = any(NoSqlQuery noSqlQuery).getQuery() } } + /** A JSON decoding converts a string to a dictionary. */ class JsonDecoding extends Decoding, StringToDictConversion { JsonDecoding() { this.getFormat() = "JSON" } diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll index 8a0e31ed544..da3432e44ad 100644 --- a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll +++ b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll @@ -1,9 +1,16 @@ +/** + * Provides a taint-tracking configuration for detecting NoSQL injection vulnerabilities + */ + import python import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TaintTracking import semmle.python.Concepts private import NoSQLInjectionCustomizations::NoSqlInjection as C +/** + * A taint-tracking configuration for detecting NoSQL injection vulnerabilities. + */ module Config implements DataFlow::StateConfigSig { class FlowState = C::FlowState; From f253f9797fe448c076ceb639734f3111ce8a7ebe Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 6 Sep 2023 11:53:44 +0200 Subject: [PATCH 019/325] Python: update test expectations --- .../NoSqlInjection.expected | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected index 01532803122..89b0684744c 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected @@ -1,4 +1,15 @@ edges +| PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | PoC/server.py:1:26:1:32 | GSSA Variable request | +| PoC/server.py:1:26:1:32 | GSSA Variable request | PoC/server.py:26:21:26:27 | ControlFlowNode for request | +| PoC/server.py:1:26:1:32 | GSSA Variable request | PoC/server.py:42:14:42:20 | ControlFlowNode for request | +| PoC/server.py:26:5:26:17 | SSA variable author_string | PoC/server.py:27:25:27:37 | ControlFlowNode for author_string | +| PoC/server.py:26:21:26:27 | ControlFlowNode for request | PoC/server.py:26:5:26:17 | SSA variable author_string | +| PoC/server.py:27:5:27:10 | SSA variable author | PoC/server.py:30:27:30:44 | ControlFlowNode for Dict | +| PoC/server.py:27:14:27:38 | ControlFlowNode for Attribute() | PoC/server.py:27:5:27:10 | SSA variable author | +| PoC/server.py:27:25:27:37 | ControlFlowNode for author_string | PoC/server.py:27:14:27:38 | ControlFlowNode for Attribute() | +| PoC/server.py:42:5:42:10 | SSA variable author | PoC/server.py:46:27:46:68 | ControlFlowNode for Dict | +| PoC/server.py:42:5:42:10 | SSA variable author | PoC/server.py:46:38:46:67 | ControlFlowNode for BinaryExpr | +| PoC/server.py:42:14:42:20 | ControlFlowNode for request | PoC/server.py:42:5:42:10 | SSA variable author | | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | @@ -66,14 +77,28 @@ edges | pymongo_test.py:13:19:13:43 | ControlFlowNode for Attribute() | pymongo_test.py:13:5:13:15 | SSA variable json_search | | pymongo_test.py:13:30:13:42 | ControlFlowNode for unsafe_search | pymongo_test.py:13:19:13:43 | ControlFlowNode for Attribute() | | pymongo_test.py:29:5:29:12 | SSA variable event_id | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | +| pymongo_test.py:29:5:29:12 | SSA variable event_id | pymongo_test.py:33:45:33:72 | ControlFlowNode for Fstring | | pymongo_test.py:29:16:29:51 | ControlFlowNode for Attribute() | pymongo_test.py:29:5:29:12 | SSA variable event_id | | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | pymongo_test.py:29:27:29:50 | ControlFlowNode for Subscript | | pymongo_test.py:29:27:29:50 | ControlFlowNode for Subscript | pymongo_test.py:29:16:29:51 | ControlFlowNode for Attribute() | | pymongo_test.py:39:5:39:12 | SSA variable event_id | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | +| pymongo_test.py:39:5:39:12 | SSA variable event_id | pymongo_test.py:43:45:43:72 | ControlFlowNode for Fstring | | pymongo_test.py:39:16:39:51 | ControlFlowNode for Attribute() | pymongo_test.py:39:5:39:12 | SSA variable event_id | | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | pymongo_test.py:39:27:39:50 | ControlFlowNode for Subscript | | pymongo_test.py:39:27:39:50 | ControlFlowNode for Subscript | pymongo_test.py:39:16:39:51 | ControlFlowNode for Attribute() | nodes +| PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| PoC/server.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| PoC/server.py:26:5:26:17 | SSA variable author_string | semmle.label | SSA variable author_string | +| PoC/server.py:26:21:26:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| PoC/server.py:27:5:27:10 | SSA variable author | semmle.label | SSA variable author | +| PoC/server.py:27:14:27:38 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| PoC/server.py:27:25:27:37 | ControlFlowNode for author_string | semmle.label | ControlFlowNode for author_string | +| PoC/server.py:30:27:30:44 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| PoC/server.py:42:5:42:10 | SSA variable author | semmle.label | SSA variable author | +| PoC/server.py:42:14:42:20 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| PoC/server.py:46:27:46:68 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| PoC/server.py:46:38:46:67 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_mongoengine_bad.py:19:5:19:17 | SSA variable unsafe_search | semmle.label | SSA variable unsafe_search | @@ -147,13 +172,18 @@ nodes | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_test.py:29:27:29:50 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| pymongo_test.py:33:45:33:72 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring | | pymongo_test.py:39:5:39:12 | SSA variable event_id | semmle.label | SSA variable event_id | | pymongo_test.py:39:16:39:51 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_test.py:39:27:39:50 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| pymongo_test.py:43:45:43:72 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring | subpaths #select +| PoC/server.py:30:27:30:44 | ControlFlowNode for Dict | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | PoC/server.py:30:27:30:44 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| PoC/server.py:46:27:46:68 | ControlFlowNode for Dict | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | PoC/server.py:46:27:46:68 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| PoC/server.py:46:38:46:67 | ControlFlowNode for BinaryExpr | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | PoC/server.py:46:38:46:67 | ControlFlowNode for BinaryExpr | This NoSQL query contains an unsanitized $@. | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | @@ -165,4 +195,6 @@ subpaths | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| pymongo_test.py:33:45:33:72 | ControlFlowNode for Fstring | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:33:45:33:72 | ControlFlowNode for Fstring | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| pymongo_test.py:43:45:43:72 | ControlFlowNode for Fstring | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:43:45:43:72 | ControlFlowNode for Fstring | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | From 970e881697b0e8a3301eb068e779a3810cd11664 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 7 Sep 2023 15:03:51 +0200 Subject: [PATCH 020/325] Python: Follow naming convention --- .../semmle/python/security/dataflow/NoSQLInjectionQuery.qll | 4 ++-- .../Security/CWE-943-NoSqlInjection/DataflowQueryTest.ql | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll index da3432e44ad..8c6f06949d6 100644 --- a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll +++ b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll @@ -11,7 +11,7 @@ private import NoSQLInjectionCustomizations::NoSqlInjection as C /** * A taint-tracking configuration for detecting NoSQL injection vulnerabilities. */ -module Config implements DataFlow::StateConfigSig { +module NoSQLInjectionConfig implements DataFlow::StateConfigSig { class FlowState = C::FlowState; predicate isSource(DataFlow::Node source, FlowState state) { @@ -57,4 +57,4 @@ module Config implements DataFlow::StateConfigSig { } } -module Flow = TaintTracking::GlobalWithState; +module Flow = TaintTracking::GlobalWithState; diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.ql b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.ql index f3709acc913..e71c10b3d56 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.ql +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/DataflowQueryTest.ql @@ -1,4 +1,4 @@ import python import experimental.dataflow.TestUtil.DataflowQueryTest import semmle.python.security.dataflow.NoSQLInjectionQuery -import FromTaintTrackingStateConfig +import FromTaintTrackingStateConfig From b07d085157e64ab774e99201da4244f9249d7b70 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 7 Sep 2023 15:04:27 +0200 Subject: [PATCH 021/325] Python: make test PoC a proper package --- .../query-tests/Security/CWE-943-NoSqlInjection/PoC/__init.py__ | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/__init.py__ diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/__init.py__ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/__init.py__ new file mode 100644 index 00000000000..e69de29bb2d From d91cd21204c9951ff5675ef063387fafbcab5a08 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Fri, 8 Sep 2023 13:37:54 +0200 Subject: [PATCH 022/325] Python: rename file --- .../CWE-943-NoSqlInjection/PoC/{__init.py__ => __init__.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/{__init.py__ => __init__.py} (100%) diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/__init.py__ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/__init__.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/__init.py__ rename to python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/__init__.py From 154a36934d87a21e1cc0932960bf9d15fb694fa7 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 11 Sep 2023 14:49:03 +0200 Subject: [PATCH 023/325] Python: Add test for function --- .../CWE-943-NoSqlInjection/PoC/server.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py index f2b4a4f0a43..a94583d8177 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py @@ -46,6 +46,32 @@ def by_where(): post = posts.find_one({'$where': 'this.author === "'+author+'"'}) # $ result=BAD return show_post(post, author) + +@app.route('/byFunction', methods=['GET']) +def by_function(): + author = request.args['author'] + search = { + "body": 'function(author) { return(author === "'+author+'") }', + "args": [ "$author" ], + "lang": "js" + } + # Use `" | "a" === "a` as author + # making the query `this.author === "" | "a" === "a"` + # Found by http://127.0.0.1:5000/byFunction?author=%22%20|%20%22a%22%20===%20%22a + post = posts.find_one({'$expr': {'$function': search}}) # $ MISING: result=BAD + return show_post(post, author) + +@app.route('/byFunctionArg', methods=['GET']) +def by_function_arg(): + author = request.args['author'] + search = { + "body": 'function(author, target) { return(author === target) }', + "args": [ "$author", author ], + "lang": "js" + } + post = posts.find_one({'$expr': {'$function': search}}) # $ result=OK + return show_post(post, author) + @app.route('/', methods=['GET']) def show_routes(): links = [] From d9f63e1ed3ee01a580fa19fd03bb2590daeb3ccb Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 11 Sep 2023 15:54:00 +0200 Subject: [PATCH 024/325] Python: Split modelling of query operators `$where` and `$function` behave quite differently. --- .../ql/lib/semmle/python/frameworks/NoSQL.qll | 31 +++++++++++++++---- .../CWE-943-NoSqlInjection/PoC/server.py | 9 +++--- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/NoSQL.qll b/python/ql/lib/semmle/python/frameworks/NoSQL.qll index ba17d593a60..d7a0848ae9c 100644 --- a/python/ql/lib/semmle/python/frameworks/NoSQL.qll +++ b/python/ql/lib/semmle/python/frameworks/NoSQL.qll @@ -99,9 +99,6 @@ private module NoSql { ] } - /** Gets the name of a mongo query operator that will interpret JavaScript. */ - private string mongoQueryOperator() { result in ["$where", "$function"] } - /** * Gets a reference to a `Mongo` collection method call * @@ -125,12 +122,34 @@ private module NoSql { override predicate vulnerableToStrings() { none() } } - private class MongoCollectionQueryOperator extends API::CallNode, NoSqlQuery::Range { + /** The `$where` query operator executes a string as JavaScript. */ + private class WhereQueryOperator extends API::CallNode, NoSqlQuery::Range { DataFlow::Node query; - MongoCollectionQueryOperator() { + WhereQueryOperator() { this = mongoCollection().getMember(mongoCollectionMethodName()).getACall() and - query = this.getParameter(0).getSubscript(mongoQueryOperator()).asSink() + query = this.getParameter(0).getSubscript("$where").asSink() + } + + override DataFlow::Node getQuery() { result = query } + + override predicate interpretsDict() { none() } + + override predicate vulnerableToStrings() { any() } + } + + /** The `$function` query operator executes its `body` string as JavaScript. */ + private class FunctionQueryOperator extends API::CallNode, NoSqlQuery::Range { + DataFlow::Node query; + + FunctionQueryOperator() { + this = mongoCollection().getMember(mongoCollectionMethodName()).getACall() and + query = + this.getParameter(0) + .getASubscript*() + .getSubscript("$function") + .getSubscript("body") + .asSink() } override DataFlow::Node getQuery() { result = query } diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py index a94583d8177..6a0099a4f5d 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py @@ -46,30 +46,29 @@ def by_where(): post = posts.find_one({'$where': 'this.author === "'+author+'"'}) # $ result=BAD return show_post(post, author) - @app.route('/byFunction', methods=['GET']) def by_function(): author = request.args['author'] search = { - "body": 'function(author) { return(author === "'+author+'") }', + "body": 'function(author) { return(author === "'+author+'") }', # $ result=BAD "args": [ "$author" ], "lang": "js" } # Use `" | "a" === "a` as author # making the query `this.author === "" | "a" === "a"` # Found by http://127.0.0.1:5000/byFunction?author=%22%20|%20%22a%22%20===%20%22a - post = posts.find_one({'$expr': {'$function': search}}) # $ MISING: result=BAD + post = posts.find_one({'$expr': {'$function': search}}) # $ result=BAD return show_post(post, author) @app.route('/byFunctionArg', methods=['GET']) def by_function_arg(): author = request.args['author'] search = { - "body": 'function(author, target) { return(author === target) }', + "body": 'function(author, target) { return(author === target) }', # $ result=OK "args": [ "$author", author ], "lang": "js" } - post = posts.find_one({'$expr': {'$function': search}}) # $ result=OK + post = posts.find_one({'$expr': {'$function': search}}) # $ SPURIOUS: result=BAD return show_post(post, author) @app.route('/', methods=['GET']) From a063d7d5104c12f785532cdc9b6358cb87a84777 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 11 Sep 2023 16:33:20 +0200 Subject: [PATCH 025/325] Python: sinks -> decodings Query operators that interpret JavaScript are no longer considered sinks. Instead they are considered decodings and the output is the tainted dictionary. The state changes to `DictInput` to reflect that the user now controls a dangerous dictionary. This fixes the spurious result and moves the error reporting to a more logical place. --- .../ql/lib/semmle/python/frameworks/NoSQL.qll | 43 +++++++++++-------- .../dataflow/NoSQLInjectionCustomizations.qll | 2 +- .../NoSqlInjection.expected | 20 ++++++--- .../CWE-943-NoSqlInjection/PoC/server.py | 6 +-- 4 files changed, 44 insertions(+), 27 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/NoSQL.qll b/python/ql/lib/semmle/python/frameworks/NoSQL.qll index d7a0848ae9c..f122f4b2000 100644 --- a/python/ql/lib/semmle/python/frameworks/NoSQL.qll +++ b/python/ql/lib/semmle/python/frameworks/NoSQL.qll @@ -123,40 +123,49 @@ private module NoSql { } /** The `$where` query operator executes a string as JavaScript. */ - private class WhereQueryOperator extends API::CallNode, NoSqlQuery::Range { + private class WhereQueryOperator extends DataFlow::Node, Decoding::Range { + API::Node dictionary; DataFlow::Node query; WhereQueryOperator() { - this = mongoCollection().getMember(mongoCollectionMethodName()).getACall() and - query = this.getParameter(0).getSubscript("$where").asSink() + dictionary = + mongoCollection().getMember(mongoCollectionMethodName()).getACall().getParameter(0) and + query = dictionary.getSubscript("$where").asSink() and + this = dictionary.asSink() } - override DataFlow::Node getQuery() { result = query } + override DataFlow::Node getAnInput() { result = query } - override predicate interpretsDict() { none() } + override DataFlow::Node getOutput() { result = this } - override predicate vulnerableToStrings() { any() } + override string getFormat() { result = "NoSQL" } + + override predicate mayExecuteInput() { any() } } /** The `$function` query operator executes its `body` string as JavaScript. */ - private class FunctionQueryOperator extends API::CallNode, NoSqlQuery::Range { + private class FunctionQueryOperator extends DataFlow::Node, Decoding::Range { + API::Node dictionary; DataFlow::Node query; FunctionQueryOperator() { - this = mongoCollection().getMember(mongoCollectionMethodName()).getACall() and - query = - this.getParameter(0) - .getASubscript*() - .getSubscript("$function") - .getSubscript("body") - .asSink() + dictionary = + mongoCollection() + .getMember(mongoCollectionMethodName()) + .getACall() + .getParameter(0) + .getASubscript*() and + query = dictionary.getSubscript("$function").getSubscript("body").asSink() and + this = dictionary.asSink() } - override DataFlow::Node getQuery() { result = query } + override DataFlow::Node getAnInput() { result = query } - override predicate interpretsDict() { none() } + override DataFlow::Node getOutput() { result = this } - override predicate vulnerableToStrings() { any() } + override string getFormat() { result = "NoSQL" } + + override predicate mayExecuteInput() { any() } } /** diff --git a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll index d3348b8df8d..debefd525a7 100644 --- a/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll @@ -75,7 +75,7 @@ module NoSqlInjection { /** A JSON decoding converts a string to a dictionary. */ class JsonDecoding extends Decoding, StringToDictConversion { - JsonDecoding() { this.getFormat() = "JSON" } + JsonDecoding() { this.getFormat() in ["JSON", "NoSQL"] } override DataFlow::Node getAnInput() { result = Decoding.super.getAnInput() } diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected index 89b0684744c..fdabe8cb977 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/NoSqlInjection.expected @@ -2,14 +2,19 @@ edges | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | PoC/server.py:1:26:1:32 | GSSA Variable request | | PoC/server.py:1:26:1:32 | GSSA Variable request | PoC/server.py:26:21:26:27 | ControlFlowNode for request | | PoC/server.py:1:26:1:32 | GSSA Variable request | PoC/server.py:42:14:42:20 | ControlFlowNode for request | +| PoC/server.py:1:26:1:32 | GSSA Variable request | PoC/server.py:51:14:51:20 | ControlFlowNode for request | | PoC/server.py:26:5:26:17 | SSA variable author_string | PoC/server.py:27:25:27:37 | ControlFlowNode for author_string | | PoC/server.py:26:21:26:27 | ControlFlowNode for request | PoC/server.py:26:5:26:17 | SSA variable author_string | | PoC/server.py:27:5:27:10 | SSA variable author | PoC/server.py:30:27:30:44 | ControlFlowNode for Dict | | PoC/server.py:27:14:27:38 | ControlFlowNode for Attribute() | PoC/server.py:27:5:27:10 | SSA variable author | | PoC/server.py:27:25:27:37 | ControlFlowNode for author_string | PoC/server.py:27:14:27:38 | ControlFlowNode for Attribute() | -| PoC/server.py:42:5:42:10 | SSA variable author | PoC/server.py:46:27:46:68 | ControlFlowNode for Dict | | PoC/server.py:42:5:42:10 | SSA variable author | PoC/server.py:46:38:46:67 | ControlFlowNode for BinaryExpr | | PoC/server.py:42:14:42:20 | ControlFlowNode for request | PoC/server.py:42:5:42:10 | SSA variable author | +| PoC/server.py:46:38:46:67 | ControlFlowNode for BinaryExpr | PoC/server.py:46:27:46:68 | ControlFlowNode for Dict | +| PoC/server.py:51:5:51:10 | SSA variable author | PoC/server.py:53:17:53:70 | ControlFlowNode for BinaryExpr | +| PoC/server.py:51:14:51:20 | ControlFlowNode for request | PoC/server.py:51:5:51:10 | SSA variable author | +| PoC/server.py:53:17:53:70 | ControlFlowNode for BinaryExpr | PoC/server.py:60:37:60:57 | ControlFlowNode for Dict | +| PoC/server.py:60:37:60:57 | ControlFlowNode for Dict | PoC/server.py:60:27:60:58 | ControlFlowNode for Dict | | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | @@ -76,16 +81,16 @@ edges | pymongo_test.py:13:5:13:15 | SSA variable json_search | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | | pymongo_test.py:13:19:13:43 | ControlFlowNode for Attribute() | pymongo_test.py:13:5:13:15 | SSA variable json_search | | pymongo_test.py:13:30:13:42 | ControlFlowNode for unsafe_search | pymongo_test.py:13:19:13:43 | ControlFlowNode for Attribute() | -| pymongo_test.py:29:5:29:12 | SSA variable event_id | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | | pymongo_test.py:29:5:29:12 | SSA variable event_id | pymongo_test.py:33:45:33:72 | ControlFlowNode for Fstring | | pymongo_test.py:29:16:29:51 | ControlFlowNode for Attribute() | pymongo_test.py:29:5:29:12 | SSA variable event_id | | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | pymongo_test.py:29:27:29:50 | ControlFlowNode for Subscript | | pymongo_test.py:29:27:29:50 | ControlFlowNode for Subscript | pymongo_test.py:29:16:29:51 | ControlFlowNode for Attribute() | -| pymongo_test.py:39:5:39:12 | SSA variable event_id | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | +| pymongo_test.py:33:45:33:72 | ControlFlowNode for Fstring | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | | pymongo_test.py:39:5:39:12 | SSA variable event_id | pymongo_test.py:43:45:43:72 | ControlFlowNode for Fstring | | pymongo_test.py:39:16:39:51 | ControlFlowNode for Attribute() | pymongo_test.py:39:5:39:12 | SSA variable event_id | | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | pymongo_test.py:39:27:39:50 | ControlFlowNode for Subscript | | pymongo_test.py:39:27:39:50 | ControlFlowNode for Subscript | pymongo_test.py:39:16:39:51 | ControlFlowNode for Attribute() | +| pymongo_test.py:43:45:43:72 | ControlFlowNode for Fstring | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | nodes | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | PoC/server.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | @@ -99,6 +104,11 @@ nodes | PoC/server.py:42:14:42:20 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | PoC/server.py:46:27:46:68 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | PoC/server.py:46:38:46:67 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| PoC/server.py:51:5:51:10 | SSA variable author | semmle.label | SSA variable author | +| PoC/server.py:51:14:51:20 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| PoC/server.py:53:17:53:70 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| PoC/server.py:60:27:60:58 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| PoC/server.py:60:37:60:57 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_mongoengine_bad.py:19:5:19:17 | SSA variable unsafe_search | semmle.label | SSA variable unsafe_search | @@ -183,7 +193,7 @@ subpaths #select | PoC/server.py:30:27:30:44 | ControlFlowNode for Dict | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | PoC/server.py:30:27:30:44 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | PoC/server.py:46:27:46:68 | ControlFlowNode for Dict | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | PoC/server.py:46:27:46:68 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| PoC/server.py:46:38:46:67 | ControlFlowNode for BinaryExpr | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | PoC/server.py:46:38:46:67 | ControlFlowNode for BinaryExpr | This NoSQL query contains an unsanitized $@. | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| PoC/server.py:60:27:60:58 | ControlFlowNode for Dict | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | PoC/server.py:60:27:60:58 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | PoC/server.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | @@ -195,6 +205,4 @@ subpaths | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| pymongo_test.py:33:45:33:72 | ControlFlowNode for Fstring | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:33:45:33:72 | ControlFlowNode for Fstring | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| pymongo_test.py:43:45:43:72 | ControlFlowNode for Fstring | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:43:45:43:72 | ControlFlowNode for Fstring | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py index 6a0099a4f5d..4f608c5e584 100644 --- a/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py +++ b/python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC/server.py @@ -50,7 +50,7 @@ def by_where(): def by_function(): author = request.args['author'] search = { - "body": 'function(author) { return(author === "'+author+'") }', # $ result=BAD + "body": 'function(author) { return(author === "'+author+'") }', "args": [ "$author" ], "lang": "js" } @@ -64,11 +64,11 @@ def by_function(): def by_function_arg(): author = request.args['author'] search = { - "body": 'function(author, target) { return(author === target) }', # $ result=OK + "body": 'function(author, target) { return(author === target) }', "args": [ "$author", author ], "lang": "js" } - post = posts.find_one({'$expr': {'$function': search}}) # $ SPURIOUS: result=BAD + post = posts.find_one({'$expr': {'$function': search}}) # $ result=OK return show_post(post, author) @app.route('/', methods=['GET']) From d8a99e6b7d51d9bc74b261e7eaddab0100a3ba17 Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Tue, 12 Sep 2023 11:13:58 +0100 Subject: [PATCH 026/325] Kotlin: Regenerate expected test output It's now in the order generated by the new CLI. This means that changes in test output are easier to understand. --- .../annotation_classes/classes.expected | 22 +-- .../kotlin/library-tests/arrays/test.expected | 14 +- .../library-tests/classes/superTypes.expected | 186 +++++++++--------- .../controlflow/basic/getASuccessor.expected | 2 +- .../kotlin/library-tests/enum/test.expected | 8 +- .../extensions/parameters.expected | 38 ++-- .../field-initializer-flow/test.expected | 2 +- .../java-map-methods/test.expected | 4 +- .../java_and_kotlin/test.expected | 10 +- .../visibility.expected | 12 +- .../private-anonymous-types/test.expected | 12 +- .../properties/properties.expected | 48 ++--- .../special-method-getters/test.expected | 2 +- .../kotlin/library-tests/stmts/stmts.expected | 144 +++++++------- .../kotlin/library-tests/this/this.expected | 18 +- .../variables/variables.expected | 20 +- 16 files changed, 271 insertions(+), 271 deletions(-) diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected index 01f5581b73a..94b71230531 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -1,3 +1,14 @@ +#select +| Annot0j.java:1:19:1:25 | Annot0j | Interface | +| Annot1j.java:1:19:1:25 | Annot1j | Interface | +| def.kt:0:0:0:0 | DefKt | Class | +| def.kt:5:1:21:60 | Annot0k | Interface | +| def.kt:23:1:31:1 | Annot1k | Interface | +| def.kt:33:1:33:10 | X | Class | +| def.kt:34:1:36:1 | Y | Class | +| def.kt:38:1:43:1 | Z | Class | +| use.java:1:14:1:16 | use | Class | +| use.java:14:18:14:18 | Z | Class | annotationDeclarations | Annot0j.java:1:19:1:25 | Annot0j | Annot0j.java:2:9:2:11 | abc | | Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:2:9:2:9 | a | @@ -69,14 +80,3 @@ annotationValues | use.java:13:5:13:88 | Annot1k | use.java:13:57:13:66 | {...} | | use.java:13:5:13:88 | Annot1k | use.java:13:73:13:87 | Annot0k | | use.java:13:73:13:87 | Annot0k | use.java:13:86:13:86 | 2 | -#select -| Annot0j.java:1:19:1:25 | Annot0j | Interface | -| Annot1j.java:1:19:1:25 | Annot1j | Interface | -| def.kt:0:0:0:0 | DefKt | Class | -| def.kt:5:1:21:60 | Annot0k | Interface | -| def.kt:23:1:31:1 | Annot1k | Interface | -| def.kt:33:1:33:10 | X | Class | -| def.kt:34:1:36:1 | Y | Class | -| def.kt:38:1:43:1 | Z | Class | -| use.java:1:14:1:16 | use | Class | -| use.java:14:18:14:18 | Z | Class | diff --git a/java/ql/test/kotlin/library-tests/arrays/test.expected b/java/ql/test/kotlin/library-tests/arrays/test.expected index 7693b3acd6b..efdc5179609 100644 --- a/java/ql/test/kotlin/library-tests/arrays/test.expected +++ b/java/ql/test/kotlin/library-tests/arrays/test.expected @@ -1,3 +1,10 @@ +#select +| primitiveArrays.kt:5:12:5:24 | a | file://:0:0:0:0 | Integer[] | Integer | Integer | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | +| primitiveArrays.kt:5:27:5:40 | b | file://:0:0:0:0 | Integer[] | Integer | Integer | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | +| primitiveArrays.kt:5:43:5:53 | c | file://:0:0:0:0 | int[] | int | int | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | +| primitiveArrays.kt:5:56:5:76 | d | file://:0:0:0:0 | Integer[][] | Integer[] | Integer | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | +| primitiveArrays.kt:5:79:5:98 | e | file://:0:0:0:0 | Integer[][] | Integer[] | Integer | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | +| primitiveArrays.kt:5:101:5:118 | f | file://:0:0:0:0 | int[][] | int[] | int | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | cloneMethods | file://:0:0:0:0 | clone | clone() | file://:0:0:0:0 | Integer[] | file://:0:0:0:0 | Integer[] | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | | file://:0:0:0:0 | clone | clone() | file://:0:0:0:0 | Integer[][] | file://:0:0:0:0 | Integer[][] | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | @@ -21,10 +28,3 @@ sourceSignatures | arrayIterators.kt:1:1:13:1 | test | test(java.lang.Integer[],int[],boolean[]) | | primitiveArrays.kt:3:1:7:1 | Test | Test() | | primitiveArrays.kt:5:3:5:123 | test | test(java.lang.Integer[],java.lang.Integer[],int[],java.lang.Integer[][],java.lang.Integer[][],int[][]) | -#select -| primitiveArrays.kt:5:12:5:24 | a | file://:0:0:0:0 | Integer[] | Integer | Integer | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | -| primitiveArrays.kt:5:27:5:40 | b | file://:0:0:0:0 | Integer[] | Integer | Integer | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | -| primitiveArrays.kt:5:43:5:53 | c | file://:0:0:0:0 | int[] | int | int | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | -| primitiveArrays.kt:5:56:5:76 | d | file://:0:0:0:0 | Integer[][] | Integer[] | Integer | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | -| primitiveArrays.kt:5:79:5:98 | e | file://:0:0:0:0 | Integer[][] | Integer[] | Integer | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | -| primitiveArrays.kt:5:101:5:118 | f | file://:0:0:0:0 | int[][] | int[] | int | file://:0:0:0:0 | Kotlin nullable FakeKotlinClass | diff --git a/java/ql/test/kotlin/library-tests/classes/superTypes.expected b/java/ql/test/kotlin/library-tests/classes/superTypes.expected index 31b8979e0b3..57b683230dd 100644 --- a/java/ql/test/kotlin/library-tests/classes/superTypes.expected +++ b/java/ql/test/kotlin/library-tests/classes/superTypes.expected @@ -1,3 +1,96 @@ +#select +| classes.kt:2:1:2:18 | ClassOne | file:///Object.class:0:0:0:0 | Object | +| classes.kt:4:1:6:1 | ClassTwo | file:///Object.class:0:0:0:0 | Object | +| classes.kt:8:1:10:1 | ClassThree | file:///Object.class:0:0:0:0 | Object | +| classes.kt:12:1:15:1 | ClassFour | classes.kt:8:1:10:1 | ClassThree | +| classes.kt:17:1:18:1 | ClassFive | classes.kt:12:1:15:1 | ClassFour | +| classes.kt:28:1:30:1 | ClassSix | classes.kt:12:1:15:1 | ClassFour | +| classes.kt:28:1:30:1 | ClassSix | classes.kt:20:1:22:1 | IF1 | +| classes.kt:28:1:30:1 | ClassSix | classes.kt:24:1:26:1 | IF2 | +| classes.kt:34:1:47:1 | ClassSeven | file:///Object.class:0:0:0:0 | Object | +| classes.kt:49:1:51:1 | Direction | file:///Enum.class:0:0:0:0 | Enum | +| classes.kt:53:1:57:1 | Color | file:///Enum.class:0:0:0:0 | Enum | +| classes.kt:63:1:91:1 | Class1 | file:///Object.class:0:0:0:0 | Object | +| classes.kt:66:20:66:54 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | +| classes.kt:66:20:66:54 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | +| classes.kt:68:20:68:74 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | +| classes.kt:68:20:68:74 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | +| classes.kt:68:20:68:74 | new Object(...) { ... } | file:///Interface3.class:0:0:0:0 | Interface3 | +| classes.kt:72:16:77:10 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | +| classes.kt:72:16:77:10 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | +| classes.kt:75:24:75:33 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | +| classes.kt:81:16:81:38 | new Interface1(...) { ... } | classes.kt:59:1:59:23 | Interface1 | +| classes.kt:85:16:85:25 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | +| classes.kt:89:16:89:44 | new Interface3(...) { ... } | file:///Interface3.class:0:0:0:0 | Interface3 | +| classes.kt:93:1:93:26 | pulicClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:94:1:94:29 | privateClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:95:1:95:31 | internalClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:96:1:96:34 | noExplicitVisibilityClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:98:1:104:1 | nestedClassVisibilities | file:///Object.class:0:0:0:0 | Object | +| classes.kt:99:5:99:36 | pulicNestedClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:100:5:100:43 | protectedNestedClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:101:5:101:39 | privateNestedClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:102:5:102:41 | internalNestedClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:103:5:103:44 | noExplicitVisibilityNestedClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:106:1:106:27 | sealedClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:107:1:107:23 | openClass | file:///Object.class:0:0:0:0 | Object | +| classes.kt:109:1:136:1 | C1 | file:///Object.class:0:0:0:0 | Object | +| classes.kt:111:9:113:9 | Local1 | file:///Object.class:0:0:0:0 | Object | +| classes.kt:118:9:123:9 | | file:///Object.class:0:0:0:0 | Object | +| classes.kt:119:13:121:13 | Local2 | file:///Object.class:0:0:0:0 | Object | +| classes.kt:127:16:134:9 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | +| classes.kt:129:17:131:17 | Local3 | file:///Object.class:0:0:0:0 | Object | +| classes.kt:138:1:148:1 | Cl0 | file:///Object.class:0:0:0:0 | Object | +| classes.kt:140:9:146:9 | | file:///Object.class:0:0:0:0 | Object | +| classes.kt:141:13:145:13 | Cl1 | file:///Object.class:0:0:0:0 | Object | +| classes.kt:150:1:156:1 | Cl00 | file:///Object.class:0:0:0:0 | Object | +| classes.kt:151:5:155:5 | Cl01 | file:///Object.class:0:0:0:0 | Object | +| classes.kt:159:5:159:14 | X | file:///Object.class:0:0:0:0 | Object | +| classes.kt:162:13:162:22 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | +| file:///C1$$Local3.class:0:0:0:0 | Local3 | file:///Object.class:0:0:0:0 | Object | +| file:///C1$Local1.class:0:0:0:0 | Local1 | file:///Object.class:0:0:0:0 | Object | +| file:///C1$Local2.class:0:0:0:0 | Local2 | file:///Object.class:0:0:0:0 | Object | +| file:///Generic.class:0:0:0:0 | Generic | file:///Object.class:0:0:0:0 | Object | +| file:///Generic.class:0:0:0:0 | Generic | generic_anonymous.kt:1:1:9:1 | Generic<> | +| file:///Generic.class:0:0:0:0 | Generic | file:///Object.class:0:0:0:0 | Object | +| file:///Generic.class:0:0:0:0 | Generic | generic_anonymous.kt:1:1:9:1 | Generic<> | +| file:///SuperChain1.class:0:0:0:0 | SuperChain1 | file:///Object.class:0:0:0:0 | Object | +| file:///SuperChain1.class:0:0:0:0 | SuperChain1 | file:///Object.class:0:0:0:0 | Object | +| file:///SuperChain2.class:0:0:0:0 | SuperChain2 | file:///SuperChain1.class:0:0:0:0 | SuperChain1 | +| generic_anonymous.kt:1:1:9:1 | Generic | file:///Object.class:0:0:0:0 | Object | +| generic_anonymous.kt:1:1:9:1 | Generic | generic_anonymous.kt:1:1:9:1 | Generic<> | +| generic_anonymous.kt:1:1:9:1 | Generic<> | file:///Object.class:0:0:0:0 | Object | +| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | +| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... }<> | file:///Object.class:0:0:0:0 | Object | +| generic_anonymous.kt:15:1:33:1 | Outer | file:///Object.class:0:0:0:0 | Object | +| generic_anonymous.kt:25:9:31:9 | | file:///Object.class:0:0:0:0 | Object | +| generic_anonymous.kt:26:13:26:37 | new Object(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | +| generic_anonymous.kt:26:13:26:37 | new Object(...) { ... } | file:///Outer$C1.class:0:0:0:0 | C1 | +| generic_anonymous.kt:27:13:27:37 | new Object(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | +| generic_anonymous.kt:27:13:27:37 | new Object(...) { ... } | file:///Outer$C1.class:0:0:0:0 | C1 | +| generic_anonymous.kt:28:13:28:41 | new Object(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | +| generic_anonymous.kt:28:13:28:41 | new Object(...) { ... } | file:///Outer$C1.class:0:0:0:0 | C1 | +| generic_anonymous.kt:29:13:29:29 | new C0(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | +| generic_anonymous.kt:30:13:30:33 | new C0(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | +| localClassField.kt:1:1:11:1 | A | file:///Object.class:0:0:0:0 | Object | +| localClassField.kt:3:9:3:19 | L | file:///Object.class:0:0:0:0 | Object | +| localClassField.kt:8:9:8:19 | L | file:///Object.class:0:0:0:0 | Object | +| local_anonymous.kt:3:1:36:1 | Class1 | file:///Object.class:0:0:0:0 | Object | +| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | +| local_anonymous.kt:11:9:11:24 | | file:///Object.class:0:0:0:0 | Object | +| local_anonymous.kt:16:23:16:49 | new Function2(...) { ... } | file:///Function2.class:0:0:0:0 | Function2 | +| local_anonymous.kt:16:23:16:49 | new Function2(...) { ... } | file:///Object.class:0:0:0:0 | Object | +| local_anonymous.kt:17:23:17:49 | new Function2(...) { ... } | file:///Function2.class:0:0:0:0 | Function2 | +| local_anonymous.kt:17:23:17:49 | new Function2(...) { ... } | file:///Object.class:0:0:0:0 | Object | +| local_anonymous.kt:21:21:21:31 | new Function1(...) { ... } | file:///Function1.class:0:0:0:0 | Function1 | +| local_anonymous.kt:21:21:21:31 | new Function1(...) { ... } | file:///FunctionReference.class:0:0:0:0 | FunctionReference | +| local_anonymous.kt:25:9:25:27 | LocalClass | file:///Object.class:0:0:0:0 | Object | +| local_anonymous.kt:29:31:35:5 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | +| local_anonymous.kt:39:1:45:1 | Class2 | file:///Object.class:0:0:0:0 | Object | +| local_anonymous.kt:40:14:44:5 | new Interface2(...) { ... } | local_anonymous.kt:38:1:38:23 | Interface2 | +| superChain.kt:1:1:1:33 | SuperChain1 | file:///Object.class:0:0:0:0 | Object | +| superChain.kt:2:1:2:60 | SuperChain2 | file:///SuperChain1.class:0:0:0:0 | SuperChain1 | +| superChain.kt:3:1:3:60 | SuperChain3 | file:///SuperChain2.class:0:0:0:0 | SuperChain2 | extendsOrImplements | classes.kt:2:1:2:18 | ClassOne | file:///Object.class:0:0:0:0 | Object | extends | | classes.kt:4:1:6:1 | ClassTwo | file:///Object.class:0:0:0:0 | Object | extends | @@ -103,96 +196,3 @@ extendsOrImplements | superChain.kt:1:1:1:33 | SuperChain1 | file:///Object.class:0:0:0:0 | Object | extends | | superChain.kt:2:1:2:60 | SuperChain2 | file:///SuperChain1.class:0:0:0:0 | SuperChain1 | extends | | superChain.kt:3:1:3:60 | SuperChain3 | file:///SuperChain2.class:0:0:0:0 | SuperChain2 | extends | -#select -| classes.kt:2:1:2:18 | ClassOne | file:///Object.class:0:0:0:0 | Object | -| classes.kt:4:1:6:1 | ClassTwo | file:///Object.class:0:0:0:0 | Object | -| classes.kt:8:1:10:1 | ClassThree | file:///Object.class:0:0:0:0 | Object | -| classes.kt:12:1:15:1 | ClassFour | classes.kt:8:1:10:1 | ClassThree | -| classes.kt:17:1:18:1 | ClassFive | classes.kt:12:1:15:1 | ClassFour | -| classes.kt:28:1:30:1 | ClassSix | classes.kt:12:1:15:1 | ClassFour | -| classes.kt:28:1:30:1 | ClassSix | classes.kt:20:1:22:1 | IF1 | -| classes.kt:28:1:30:1 | ClassSix | classes.kt:24:1:26:1 | IF2 | -| classes.kt:34:1:47:1 | ClassSeven | file:///Object.class:0:0:0:0 | Object | -| classes.kt:49:1:51:1 | Direction | file:///Enum.class:0:0:0:0 | Enum | -| classes.kt:53:1:57:1 | Color | file:///Enum.class:0:0:0:0 | Enum | -| classes.kt:63:1:91:1 | Class1 | file:///Object.class:0:0:0:0 | Object | -| classes.kt:66:20:66:54 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | -| classes.kt:66:20:66:54 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | -| classes.kt:68:20:68:74 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | -| classes.kt:68:20:68:74 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | -| classes.kt:68:20:68:74 | new Object(...) { ... } | file:///Interface3.class:0:0:0:0 | Interface3 | -| classes.kt:72:16:77:10 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | -| classes.kt:72:16:77:10 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | -| classes.kt:75:24:75:33 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | -| classes.kt:81:16:81:38 | new Interface1(...) { ... } | classes.kt:59:1:59:23 | Interface1 | -| classes.kt:85:16:85:25 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | -| classes.kt:89:16:89:44 | new Interface3(...) { ... } | file:///Interface3.class:0:0:0:0 | Interface3 | -| classes.kt:93:1:93:26 | pulicClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:94:1:94:29 | privateClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:95:1:95:31 | internalClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:96:1:96:34 | noExplicitVisibilityClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:98:1:104:1 | nestedClassVisibilities | file:///Object.class:0:0:0:0 | Object | -| classes.kt:99:5:99:36 | pulicNestedClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:100:5:100:43 | protectedNestedClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:101:5:101:39 | privateNestedClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:102:5:102:41 | internalNestedClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:103:5:103:44 | noExplicitVisibilityNestedClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:106:1:106:27 | sealedClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:107:1:107:23 | openClass | file:///Object.class:0:0:0:0 | Object | -| classes.kt:109:1:136:1 | C1 | file:///Object.class:0:0:0:0 | Object | -| classes.kt:111:9:113:9 | Local1 | file:///Object.class:0:0:0:0 | Object | -| classes.kt:118:9:123:9 | | file:///Object.class:0:0:0:0 | Object | -| classes.kt:119:13:121:13 | Local2 | file:///Object.class:0:0:0:0 | Object | -| classes.kt:127:16:134:9 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | -| classes.kt:129:17:131:17 | Local3 | file:///Object.class:0:0:0:0 | Object | -| classes.kt:138:1:148:1 | Cl0 | file:///Object.class:0:0:0:0 | Object | -| classes.kt:140:9:146:9 | | file:///Object.class:0:0:0:0 | Object | -| classes.kt:141:13:145:13 | Cl1 | file:///Object.class:0:0:0:0 | Object | -| classes.kt:150:1:156:1 | Cl00 | file:///Object.class:0:0:0:0 | Object | -| classes.kt:151:5:155:5 | Cl01 | file:///Object.class:0:0:0:0 | Object | -| classes.kt:159:5:159:14 | X | file:///Object.class:0:0:0:0 | Object | -| classes.kt:162:13:162:22 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | -| file:///C1$$Local3.class:0:0:0:0 | Local3 | file:///Object.class:0:0:0:0 | Object | -| file:///C1$Local1.class:0:0:0:0 | Local1 | file:///Object.class:0:0:0:0 | Object | -| file:///C1$Local2.class:0:0:0:0 | Local2 | file:///Object.class:0:0:0:0 | Object | -| file:///Generic.class:0:0:0:0 | Generic | file:///Object.class:0:0:0:0 | Object | -| file:///Generic.class:0:0:0:0 | Generic | generic_anonymous.kt:1:1:9:1 | Generic<> | -| file:///Generic.class:0:0:0:0 | Generic | file:///Object.class:0:0:0:0 | Object | -| file:///Generic.class:0:0:0:0 | Generic | generic_anonymous.kt:1:1:9:1 | Generic<> | -| file:///SuperChain1.class:0:0:0:0 | SuperChain1 | file:///Object.class:0:0:0:0 | Object | -| file:///SuperChain1.class:0:0:0:0 | SuperChain1 | file:///Object.class:0:0:0:0 | Object | -| file:///SuperChain2.class:0:0:0:0 | SuperChain2 | file:///SuperChain1.class:0:0:0:0 | SuperChain1 | -| generic_anonymous.kt:1:1:9:1 | Generic | file:///Object.class:0:0:0:0 | Object | -| generic_anonymous.kt:1:1:9:1 | Generic | generic_anonymous.kt:1:1:9:1 | Generic<> | -| generic_anonymous.kt:1:1:9:1 | Generic<> | file:///Object.class:0:0:0:0 | Object | -| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | -| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... }<> | file:///Object.class:0:0:0:0 | Object | -| generic_anonymous.kt:15:1:33:1 | Outer | file:///Object.class:0:0:0:0 | Object | -| generic_anonymous.kt:25:9:31:9 | | file:///Object.class:0:0:0:0 | Object | -| generic_anonymous.kt:26:13:26:37 | new Object(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | -| generic_anonymous.kt:26:13:26:37 | new Object(...) { ... } | file:///Outer$C1.class:0:0:0:0 | C1 | -| generic_anonymous.kt:27:13:27:37 | new Object(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | -| generic_anonymous.kt:27:13:27:37 | new Object(...) { ... } | file:///Outer$C1.class:0:0:0:0 | C1 | -| generic_anonymous.kt:28:13:28:41 | new Object(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | -| generic_anonymous.kt:28:13:28:41 | new Object(...) { ... } | file:///Outer$C1.class:0:0:0:0 | C1 | -| generic_anonymous.kt:29:13:29:29 | new C0(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | -| generic_anonymous.kt:30:13:30:33 | new C0(...) { ... } | file:///Outer$C0.class:0:0:0:0 | C0 | -| localClassField.kt:1:1:11:1 | A | file:///Object.class:0:0:0:0 | Object | -| localClassField.kt:3:9:3:19 | L | file:///Object.class:0:0:0:0 | Object | -| localClassField.kt:8:9:8:19 | L | file:///Object.class:0:0:0:0 | Object | -| local_anonymous.kt:3:1:36:1 | Class1 | file:///Object.class:0:0:0:0 | Object | -| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | -| local_anonymous.kt:11:9:11:24 | | file:///Object.class:0:0:0:0 | Object | -| local_anonymous.kt:16:23:16:49 | new Function2(...) { ... } | file:///Function2.class:0:0:0:0 | Function2 | -| local_anonymous.kt:16:23:16:49 | new Function2(...) { ... } | file:///Object.class:0:0:0:0 | Object | -| local_anonymous.kt:17:23:17:49 | new Function2(...) { ... } | file:///Function2.class:0:0:0:0 | Function2 | -| local_anonymous.kt:17:23:17:49 | new Function2(...) { ... } | file:///Object.class:0:0:0:0 | Object | -| local_anonymous.kt:21:21:21:31 | new Function1(...) { ... } | file:///Function1.class:0:0:0:0 | Function1 | -| local_anonymous.kt:21:21:21:31 | new Function1(...) { ... } | file:///FunctionReference.class:0:0:0:0 | FunctionReference | -| local_anonymous.kt:25:9:25:27 | LocalClass | file:///Object.class:0:0:0:0 | Object | -| local_anonymous.kt:29:31:35:5 | new Object(...) { ... } | file:///Object.class:0:0:0:0 | Object | -| local_anonymous.kt:39:1:45:1 | Class2 | file:///Object.class:0:0:0:0 | Object | -| local_anonymous.kt:40:14:44:5 | new Interface2(...) { ... } | local_anonymous.kt:38:1:38:23 | Interface2 | -| superChain.kt:1:1:1:33 | SuperChain1 | file:///Object.class:0:0:0:0 | Object | -| superChain.kt:2:1:2:60 | SuperChain2 | file:///SuperChain1.class:0:0:0:0 | SuperChain1 | -| superChain.kt:3:1:3:60 | SuperChain3 | file:///SuperChain2.class:0:0:0:0 | SuperChain2 | diff --git a/java/ql/test/kotlin/library-tests/controlflow/basic/getASuccessor.expected b/java/ql/test/kotlin/library-tests/controlflow/basic/getASuccessor.expected index 36544bd2d93..993e707744e 100644 --- a/java/ql/test/kotlin/library-tests/controlflow/basic/getASuccessor.expected +++ b/java/ql/test/kotlin/library-tests/controlflow/basic/getASuccessor.expected @@ -1,4 +1,3 @@ -missingSuccessor #select | Test.kt:0:0:0:0 | TestKt | Class | file://:0:0:0:0 | | | | Test.kt:3:1:80:1 | Test | Class | file://:0:0:0:0 | | | @@ -259,3 +258,4 @@ missingSuccessor | Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | fn_when | Method | | Test.kt:122:12:122:16 | true | BooleanLiteral | Test.kt:122:12:122:16 | ; | ExprStmt | | Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | fn_when | Method | +missingSuccessor diff --git a/java/ql/test/kotlin/library-tests/enum/test.expected b/java/ql/test/kotlin/library-tests/enum/test.expected index 2484ff2e2ba..b8be8ed4152 100644 --- a/java/ql/test/kotlin/library-tests/enum/test.expected +++ b/java/ql/test/kotlin/library-tests/enum/test.expected @@ -1,7 +1,3 @@ -enumConstants -| enumUser.kt:3:16:3:17 | A | -| enumUser.kt:3:19:3:20 | B | -| enumUser.kt:3:22:3:22 | C | #select | addAll | | addRange | @@ -35,3 +31,7 @@ enumConstants | usesEnum | | valueOf | | writeReplace | +enumConstants +| enumUser.kt:3:16:3:17 | A | +| enumUser.kt:3:19:3:20 | B | +| enumUser.kt:3:22:3:22 | C | diff --git a/java/ql/test/kotlin/library-tests/extensions/parameters.expected b/java/ql/test/kotlin/library-tests/extensions/parameters.expected index 65906e57dd2..dfbf92eb4f9 100644 --- a/java/ql/test/kotlin/library-tests/extensions/parameters.expected +++ b/java/ql/test/kotlin/library-tests/extensions/parameters.expected @@ -1,3 +1,22 @@ +#select +| extensions.kt:3:5:3:38 | someClassMethod | extensions.kt:3:25:3:34 | p1 | 0 | +| extensions.kt:6:5:6:41 | anotherClassMethod | extensions.kt:6:28:6:37 | p1 | 0 | +| extensions.kt:9:1:9:36 | someFun | extensions.kt:9:5:9:13 | | 0 | +| extensions.kt:9:1:9:36 | someFun | extensions.kt:9:23:9:32 | p1 | 1 | +| extensions.kt:10:1:10:42 | anotherFun | extensions.kt:10:5:10:16 | | 0 | +| extensions.kt:10:1:10:42 | anotherFun | extensions.kt:10:29:10:38 | p1 | 1 | +| extensions.kt:12:1:12:36 | bothFun | extensions.kt:12:5:12:13 | | 0 | +| extensions.kt:12:1:12:36 | bothFun | extensions.kt:12:23:12:32 | p1 | 1 | +| extensions.kt:13:1:13:39 | bothFun | extensions.kt:13:5:13:16 | | 0 | +| extensions.kt:13:1:13:39 | bothFun | extensions.kt:13:26:13:35 | p1 | 1 | +| extensions.kt:15:1:15:57 | bothFunDiffTypes | extensions.kt:15:5:15:13 | | 0 | +| extensions.kt:15:1:15:57 | bothFunDiffTypes | extensions.kt:15:32:15:38 | p1 | 1 | +| extensions.kt:16:1:16:70 | bothFunDiffTypes | extensions.kt:16:5:16:16 | | 0 | +| extensions.kt:16:1:16:70 | bothFunDiffTypes | extensions.kt:16:35:16:44 | p1 | 1 | +| extensions.kt:18:1:18:51 | bar | extensions.kt:18:5:18:10 | | 0 | +| extensions.kt:18:1:18:51 | bar | extensions.kt:18:16:18:25 | p1 | 1 | +| extensions.kt:30:5:30:55 | baz | extensions.kt:30:9:30:14 | | 0 | +| extensions.kt:30:5:30:55 | baz | extensions.kt:30:20:30:29 | p1 | 1 | parametersWithArgs | extensions.kt:3:25:3:34 | p1 | 0 | extensions.kt:21:34:21:36 | "foo" | | extensions.kt:6:28:6:37 | p1 | 0 | extensions.kt:25:40:25:42 | "foo" | @@ -28,22 +47,3 @@ extensionParameter | extensions.kt:16:5:16:16 | | | extensions.kt:18:5:18:10 | | | extensions.kt:30:9:30:14 | | -#select -| extensions.kt:3:5:3:38 | someClassMethod | extensions.kt:3:25:3:34 | p1 | 0 | -| extensions.kt:6:5:6:41 | anotherClassMethod | extensions.kt:6:28:6:37 | p1 | 0 | -| extensions.kt:9:1:9:36 | someFun | extensions.kt:9:5:9:13 | | 0 | -| extensions.kt:9:1:9:36 | someFun | extensions.kt:9:23:9:32 | p1 | 1 | -| extensions.kt:10:1:10:42 | anotherFun | extensions.kt:10:5:10:16 | | 0 | -| extensions.kt:10:1:10:42 | anotherFun | extensions.kt:10:29:10:38 | p1 | 1 | -| extensions.kt:12:1:12:36 | bothFun | extensions.kt:12:5:12:13 | | 0 | -| extensions.kt:12:1:12:36 | bothFun | extensions.kt:12:23:12:32 | p1 | 1 | -| extensions.kt:13:1:13:39 | bothFun | extensions.kt:13:5:13:16 | | 0 | -| extensions.kt:13:1:13:39 | bothFun | extensions.kt:13:26:13:35 | p1 | 1 | -| extensions.kt:15:1:15:57 | bothFunDiffTypes | extensions.kt:15:5:15:13 | | 0 | -| extensions.kt:15:1:15:57 | bothFunDiffTypes | extensions.kt:15:32:15:38 | p1 | 1 | -| extensions.kt:16:1:16:70 | bothFunDiffTypes | extensions.kt:16:5:16:16 | | 0 | -| extensions.kt:16:1:16:70 | bothFunDiffTypes | extensions.kt:16:35:16:44 | p1 | 1 | -| extensions.kt:18:1:18:51 | bar | extensions.kt:18:5:18:10 | | 0 | -| extensions.kt:18:1:18:51 | bar | extensions.kt:18:16:18:25 | p1 | 1 | -| extensions.kt:30:5:30:55 | baz | extensions.kt:30:9:30:14 | | 0 | -| extensions.kt:30:5:30:55 | baz | extensions.kt:30:20:30:29 | p1 | 1 | diff --git a/java/ql/test/kotlin/library-tests/field-initializer-flow/test.expected b/java/ql/test/kotlin/library-tests/field-initializer-flow/test.expected index a959250456f..5c6353b87c9 100644 --- a/java/ql/test/kotlin/library-tests/field-initializer-flow/test.expected +++ b/java/ql/test/kotlin/library-tests/field-initializer-flow/test.expected @@ -1,3 +1,3 @@ isFinalField | test.kt:3:3:3:18 | x | -#select \ No newline at end of file +#select diff --git a/java/ql/test/kotlin/library-tests/java-map-methods/test.expected b/java/ql/test/kotlin/library-tests/java-map-methods/test.expected index 66fb9f6ea55..813df1c237a 100644 --- a/java/ql/test/kotlin/library-tests/java-map-methods/test.expected +++ b/java/ql/test/kotlin/library-tests/java-map-methods/test.expected @@ -1,7 +1,7 @@ -diagnostics -| file://:0:0:0:0 | Couldn't find a Java equivalent function to kotlin.Number.toChar in java.lang.Number | #select | Integer | | Iterable | | Object | | int | +diagnostics +| file://:0:0:0:0 | Couldn't find a Java equivalent function to kotlin.Number.toChar in java.lang.Number | diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin/test.expected b/java/ql/test/kotlin/library-tests/java_and_kotlin/test.expected index fa37843355f..3ae886713c3 100644 --- a/java/ql/test/kotlin/library-tests/java_and_kotlin/test.expected +++ b/java/ql/test/kotlin/library-tests/java_and_kotlin/test.expected @@ -1,3 +1,8 @@ +#select +| Java.java:5:3:5:26 | kotlinFun(...) | Kotlin.kt:2:2:4:2 | kotlinFun | +| Java.java:11:11:11:22 | fn0(...) | Kotlin.kt:8:10:8:38 | fn0 | +| Kotlin.kt:13:40:13:51 | fn0(...) | Kotlin.kt:8:10:8:38 | fn0 | +| Kotlin.kt:14:48:14:59 | fn1(...) | Kotlin.kt:9:18:9:46 | fn1 | methods | Java.java:4:7:4:13 | javaFun | javaFun() | | Java.java:10:17:10:19 | fn0 | fn0(int) | @@ -12,8 +17,3 @@ overrides | Kotlin.kt:14:22:14:59 | fn1 | Kotlin.kt:9:18:9:46 | fn1 | signature_mismatch | Kotlin.kt:9:18:9:46 | fn1 | fn1(int) | -#select -| Java.java:5:3:5:26 | kotlinFun(...) | Kotlin.kt:2:2:4:2 | kotlinFun | -| Java.java:11:11:11:22 | fn0(...) | Kotlin.kt:8:10:8:38 | fn0 | -| Kotlin.kt:13:40:13:51 | fn0(...) | Kotlin.kt:8:10:8:38 | fn0 | -| Kotlin.kt:14:48:14:59 | fn1(...) | Kotlin.kt:9:18:9:46 | fn1 | diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin_internal/visibility.expected b/java/ql/test/kotlin/library-tests/java_and_kotlin_internal/visibility.expected index 378da6dd22f..43e5e8eefbe 100644 --- a/java/ql/test/kotlin/library-tests/java_and_kotlin_internal/visibility.expected +++ b/java/ql/test/kotlin/library-tests/java_and_kotlin_internal/visibility.expected @@ -1,3 +1,9 @@ +#select +| Kotlin.kt:2:11:3:2 | kotlinFun$main | final | +| Kotlin.kt:2:11:3:2 | kotlinFun$main | internal | +| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | final | +| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | internal | +| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | static | isPublic isInternal | Kotlin.kt:2:11:3:2 | kotlinFun$main | @@ -8,9 +14,3 @@ modifiers_methods | file://:0:0:0:0 | internal | Kotlin.kt:2:11:3:2 | kotlinFun$main | | file://:0:0:0:0 | internal | Kotlin.kt:6:10:6:36 | topLevelKotlinFun | | file://:0:0:0:0 | static | Kotlin.kt:6:10:6:36 | topLevelKotlinFun | -#select -| Kotlin.kt:2:11:3:2 | kotlinFun$main | final | -| Kotlin.kt:2:11:3:2 | kotlinFun$main | internal | -| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | final | -| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | internal | -| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | static | diff --git a/java/ql/test/kotlin/library-tests/private-anonymous-types/test.expected b/java/ql/test/kotlin/library-tests/private-anonymous-types/test.expected index 40de73eadd9..766185e4931 100644 --- a/java/ql/test/kotlin/library-tests/private-anonymous-types/test.expected +++ b/java/ql/test/kotlin/library-tests/private-anonymous-types/test.expected @@ -1,9 +1,3 @@ -enclosingTypes -| file:///!unknown-binary-location/A$.class:0:0:0:0 | new If(...) { ... }<> | file:///!unknown-binary-location/A.class:0:0:0:0 | A | -| file:///!unknown-binary-location/A$.class:0:0:0:0 | new If(...) { ... }<> | file:///!unknown-binary-location/A.class:0:0:0:0 | A | -| test.kt:9:18:11:3 | new If(...) { ... } | test.kt:7:1:22:1 | A | -| test.kt:13:33:15:3 | new If(...) { ... } | test.kt:7:1:22:1 | A | -| test.kt:13:33:15:3 | new If(...) { ... }<> | test.kt:7:1:22:1 | A<> | #select | file:///!unknown-binary-location/A$.class:0:0:0:0 | new If(...) { ... }<> | file:///!unknown-binary-location/A$.class:0:0:0:0 | | | file:///!unknown-binary-location/A$.class:0:0:0:0 | new If(...) { ... }<> | file:///!unknown-binary-location/A$.class:0:0:0:0 | | @@ -34,3 +28,9 @@ enclosingTypes | test.kt:13:33:15:3 | new If(...) { ... } | test.kt:13:33:15:3 | | | test.kt:13:33:15:3 | new If(...) { ... } | test.kt:14:5:14:22 | x | | test.kt:13:33:15:3 | new If(...) { ... } | test.kt:14:14:14:22 | getX | +enclosingTypes +| file:///!unknown-binary-location/A$.class:0:0:0:0 | new If(...) { ... }<> | file:///!unknown-binary-location/A.class:0:0:0:0 | A | +| file:///!unknown-binary-location/A$.class:0:0:0:0 | new If(...) { ... }<> | file:///!unknown-binary-location/A.class:0:0:0:0 | A | +| test.kt:9:18:11:3 | new If(...) { ... } | test.kt:7:1:22:1 | A | +| test.kt:13:33:15:3 | new If(...) { ... } | test.kt:7:1:22:1 | A | +| test.kt:13:33:15:3 | new If(...) { ... }<> | test.kt:7:1:22:1 | A<> | diff --git a/java/ql/test/kotlin/library-tests/properties/properties.expected b/java/ql/test/kotlin/library-tests/properties/properties.expected index 01c82187a81..1f60e9054b2 100644 --- a/java/ql/test/kotlin/library-tests/properties/properties.expected +++ b/java/ql/test/kotlin/library-tests/properties/properties.expected @@ -1,27 +1,3 @@ -fieldDeclarations -| properties.kt:2:27:2:50 | int constructorProp; | properties.kt:2:27:2:50 | constructorProp | 0 | -| properties.kt:2:53:2:83 | int mutableConstructorProp; | properties.kt:2:53:2:83 | mutableConstructorProp | 0 | -| properties.kt:3:5:3:25 | int modifiableInt; | properties.kt:3:5:3:25 | modifiableInt | 0 | -| properties.kt:4:5:4:24 | int immutableInt; | properties.kt:4:5:4:24 | immutableInt | 0 | -| properties.kt:5:5:5:26 | int typedProp; | properties.kt:5:5:5:26 | typedProp | 0 | -| properties.kt:7:5:7:30 | int initialisedInInit; | properties.kt:7:5:7:30 | initialisedInInit | 0 | -| properties.kt:11:5:11:40 | int useConstructorArg; | properties.kt:11:5:11:40 | useConstructorArg | 0 | -| properties.kt:19:5:20:15 | int defaultGetter; | properties.kt:19:5:20:15 | defaultGetter | 0 | -| properties.kt:21:5:22:15 | int varDefaultGetter; | properties.kt:21:5:22:15 | varDefaultGetter | 0 | -| properties.kt:23:5:24:15 | int varDefaultSetter; | properties.kt:23:5:24:15 | varDefaultSetter | 0 | -| properties.kt:25:5:27:15 | int varDefaultGetterSetter; | properties.kt:25:5:27:15 | varDefaultGetterSetter | 0 | -| properties.kt:28:5:29:22 | int overrideGetter; | properties.kt:28:5:29:22 | overrideGetter | 0 | -| properties.kt:30:5:31:29 | int overrideGetterUseField; | properties.kt:30:5:31:29 | overrideGetterUseField | 0 | -| properties.kt:32:5:33:29 | int useField; | properties.kt:32:5:33:29 | useField | 0 | -| properties.kt:34:5:34:36 | String lateInitVar; | properties.kt:34:5:34:36 | lateInitVar | 0 | -| properties.kt:35:5:35:32 | int privateProp; | properties.kt:35:5:35:32 | privateProp | 0 | -| properties.kt:36:5:36:36 | int protectedProp; | properties.kt:36:5:36:36 | protectedProp | 0 | -| properties.kt:37:5:37:30 | int publicProp; | properties.kt:37:5:37:30 | publicProp | 0 | -| properties.kt:38:5:38:34 | int internalProp; | properties.kt:38:5:38:34 | internalProp | 0 | -| properties.kt:67:1:67:23 | int constVal; | properties.kt:67:1:67:23 | constVal | 0 | -| properties.kt:70:5:70:16 | int prop; | properties.kt:70:5:70:16 | prop | 0 | -| properties.kt:84:5:84:29 | int data; | properties.kt:84:5:84:29 | data | 0 | -| properties.kt:92:5:93:18 | int data; | properties.kt:92:5:93:18 | data | 0 | #select | properties.kt:2:27:2:50 | constructorProp | properties.kt:2:27:2:50 | getConstructorProp | file://:0:0:0:0 | | properties.kt:2:27:2:50 | constructorProp | public | | properties.kt:2:53:2:83 | mutableConstructorProp | properties.kt:2:53:2:83 | getMutableConstructorProp | properties.kt:2:53:2:83 | setMutableConstructorProp | properties.kt:2:53:2:83 | mutableConstructorProp | public | @@ -52,3 +28,27 @@ fieldDeclarations | properties.kt:80:1:81:13 | x | properties.kt:81:5:81:13 | getX | file://:0:0:0:0 | | file://:0:0:0:0 | | public | | properties.kt:84:5:84:29 | data | properties.kt:84:13:84:29 | getData$private | properties.kt:84:13:84:29 | setData$private | properties.kt:84:5:84:29 | data | private | | properties.kt:92:5:93:18 | data | properties.kt:93:9:93:18 | getData | properties.kt:92:13:93:18 | setData$private | properties.kt:92:5:93:18 | data | private | +fieldDeclarations +| properties.kt:2:27:2:50 | int constructorProp; | properties.kt:2:27:2:50 | constructorProp | 0 | +| properties.kt:2:53:2:83 | int mutableConstructorProp; | properties.kt:2:53:2:83 | mutableConstructorProp | 0 | +| properties.kt:3:5:3:25 | int modifiableInt; | properties.kt:3:5:3:25 | modifiableInt | 0 | +| properties.kt:4:5:4:24 | int immutableInt; | properties.kt:4:5:4:24 | immutableInt | 0 | +| properties.kt:5:5:5:26 | int typedProp; | properties.kt:5:5:5:26 | typedProp | 0 | +| properties.kt:7:5:7:30 | int initialisedInInit; | properties.kt:7:5:7:30 | initialisedInInit | 0 | +| properties.kt:11:5:11:40 | int useConstructorArg; | properties.kt:11:5:11:40 | useConstructorArg | 0 | +| properties.kt:19:5:20:15 | int defaultGetter; | properties.kt:19:5:20:15 | defaultGetter | 0 | +| properties.kt:21:5:22:15 | int varDefaultGetter; | properties.kt:21:5:22:15 | varDefaultGetter | 0 | +| properties.kt:23:5:24:15 | int varDefaultSetter; | properties.kt:23:5:24:15 | varDefaultSetter | 0 | +| properties.kt:25:5:27:15 | int varDefaultGetterSetter; | properties.kt:25:5:27:15 | varDefaultGetterSetter | 0 | +| properties.kt:28:5:29:22 | int overrideGetter; | properties.kt:28:5:29:22 | overrideGetter | 0 | +| properties.kt:30:5:31:29 | int overrideGetterUseField; | properties.kt:30:5:31:29 | overrideGetterUseField | 0 | +| properties.kt:32:5:33:29 | int useField; | properties.kt:32:5:33:29 | useField | 0 | +| properties.kt:34:5:34:36 | String lateInitVar; | properties.kt:34:5:34:36 | lateInitVar | 0 | +| properties.kt:35:5:35:32 | int privateProp; | properties.kt:35:5:35:32 | privateProp | 0 | +| properties.kt:36:5:36:36 | int protectedProp; | properties.kt:36:5:36:36 | protectedProp | 0 | +| properties.kt:37:5:37:30 | int publicProp; | properties.kt:37:5:37:30 | publicProp | 0 | +| properties.kt:38:5:38:34 | int internalProp; | properties.kt:38:5:38:34 | internalProp | 0 | +| properties.kt:67:1:67:23 | int constVal; | properties.kt:67:1:67:23 | constVal | 0 | +| properties.kt:70:5:70:16 | int prop; | properties.kt:70:5:70:16 | prop | 0 | +| properties.kt:84:5:84:29 | int data; | properties.kt:84:5:84:29 | data | 0 | +| properties.kt:92:5:93:18 | int data; | properties.kt:92:5:93:18 | data | 0 | diff --git a/java/ql/test/kotlin/library-tests/special-method-getters/test.expected b/java/ql/test/kotlin/library-tests/special-method-getters/test.expected index 64b59974fa9..7bdebe05c72 100644 --- a/java/ql/test/kotlin/library-tests/special-method-getters/test.expected +++ b/java/ql/test/kotlin/library-tests/special-method-getters/test.expected @@ -1,4 +1,3 @@ -diag #select | test.kt:1:81:1:89 | length(...) | java.lang.CharSequence | length | | test.kt:1:93:1:100 | size(...) | java.util.Collection | size | @@ -9,3 +8,4 @@ diag | test.kt:1:131:1:145 | size(...) | java.util.Collection | size | | test.kt:1:149:1:159 | entrySet(...) | java.util.Map | entrySet | | test.kt:1:149:1:164 | size(...) | java.util.Set> | size | +diag diff --git a/java/ql/test/kotlin/library-tests/stmts/stmts.expected b/java/ql/test/kotlin/library-tests/stmts/stmts.expected index 716bea1649a..a374ed7e222 100644 --- a/java/ql/test/kotlin/library-tests/stmts/stmts.expected +++ b/java/ql/test/kotlin/library-tests/stmts/stmts.expected @@ -1,75 +1,3 @@ -enclosing -| stmts.kt:3:5:6:5 | ; | stmts.kt:2:41:20:1 | { ... } | -| stmts.kt:3:8:4:5 | ... -> ... | stmts.kt:3:5:6:5 | ; | -| stmts.kt:3:15:4:5 | { ... } | stmts.kt:3:8:4:5 | ... -> ... | -| stmts.kt:4:15:5:5 | ... -> ... | stmts.kt:3:5:6:5 | ; | -| stmts.kt:4:22:5:5 | { ... } | stmts.kt:4:15:5:5 | ... -> ... | -| stmts.kt:5:12:6:5 | ... -> ... | stmts.kt:3:5:6:5 | ; | -| stmts.kt:5:12:6:5 | { ... } | stmts.kt:5:12:6:5 | ... -> ... | -| stmts.kt:7:5:8:16 | while (...) | stmts.kt:2:41:20:1 | { ... } | -| stmts.kt:8:9:8:16 | return ... | stmts.kt:7:5:8:16 | while (...) | -| stmts.kt:9:5:11:5 | while (...) | stmts.kt:2:41:20:1 | { ... } | -| stmts.kt:9:18:11:5 | { ... } | stmts.kt:9:5:11:5 | while (...) | -| stmts.kt:10:9:10:16 | return ... | stmts.kt:9:18:11:5 | { ... } | -| stmts.kt:12:5:14:18 | do ... while (...) | stmts.kt:12:5:14:18 | { ... } | -| stmts.kt:12:5:14:18 | { ... } | stmts.kt:2:41:20:1 | { ... } | -| stmts.kt:12:8:14:5 | { ... } | stmts.kt:12:5:14:18 | do ... while (...) | -| stmts.kt:13:9:13:16 | return ... | stmts.kt:12:8:14:5 | { ... } | -| stmts.kt:15:9:15:9 | var ...; | stmts.kt:2:41:20:1 | { ... } | -| stmts.kt:17:9:17:10 | var ...; | stmts.kt:2:41:20:1 | { ... } | -| stmts.kt:17:26:17:58 | ... -> ... | stmts.kt:17:9:17:10 | var ...; | -| stmts.kt:17:26:17:58 | ... -> ... | stmts.kt:17:9:17:10 | var ...; | -| stmts.kt:17:35:17:43 | { ... } | stmts.kt:17:26:17:58 | ... -> ... | -| stmts.kt:17:37:17:37 | ; | stmts.kt:17:35:17:43 | { ... } | -| stmts.kt:17:50:17:58 | { ... } | stmts.kt:17:26:17:58 | ... -> ... | -| stmts.kt:17:52:17:52 | ; | stmts.kt:17:50:17:58 | { ... } | -| stmts.kt:18:9:18:10 | var ...; | stmts.kt:2:41:20:1 | { ... } | -| stmts.kt:18:26:18:56 | ... -> ... | stmts.kt:18:9:18:10 | var ...; | -| stmts.kt:18:26:18:56 | ... -> ... | stmts.kt:18:9:18:10 | var ...; | -| stmts.kt:18:37:18:37 | ; | stmts.kt:18:26:18:56 | ... -> ... | -| stmts.kt:18:52:18:52 | ; | stmts.kt:18:26:18:56 | ... -> ... | -| stmts.kt:19:5:19:16 | return ... | stmts.kt:2:41:20:1 | { ... } | -| stmts.kt:23:11:27:5 |