From e45a31744f31acf3dc27c2602ab23210c1b48bf5 Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Sun, 9 Jul 2023 04:17:35 +0200 Subject: [PATCH 01/32] Initial commit --- .../security/CommandInjectionExtensions.qll | 50 +++++++++++++++++++ .../swift/security/CommandInjectionQuery.qll | 27 ++++++++++ 2 files changed, 77 insertions(+) create mode 100644 swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll create mode 100644 swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll diff --git a/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll new file mode 100644 index 00000000000..a553ab08955 --- /dev/null +++ b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll @@ -0,0 +1,50 @@ +/** + * Provides classes and predicates for reasoning about system + * commands built from user-controlled sources (that is, command injection + * vulnerabilities). + */ + +import swift +import codeql.swift.dataflow.DataFlow +import codeql.swift.dataflow.ExternalFlow + +/** + * A dataflow sink for command injection vulnerabilities. + */ +abstract class CommandInjectionSink extends DataFlow::Node { } + +/** + * A barrier for command injection vulnerabilities. + */ +abstract class CommandInjectionBarrier extends DataFlow::Node { } + +/** + * A unit class for adding additional flow steps. + */ +class CommandInjectionAdditionalFlowStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a flow + * step for paths related to command injection vulnerabilities. + */ + abstract predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo); +} + +/** An expression of type `Process`. */ +private class ProcessRef extends Expr { + ProcessRef() { + this.getType() instanceof ProcessType or + this.getType() = any(OptionalType t | t.getBaseType() instanceof ProcessType) + } +} + +/** The type `Process`. */ +private class ProcessType extends NominalType { + ProcessType() { this.getFullName() = "Process" } +} + +/** + * A sink defined in a CSV model. + */ +private class DefaultCommandInjectionSink extends CommandInjectionSink { + DefaultCommandInjectionSink() { sinkNode(this, "command-injection") } +} diff --git a/swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll b/swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll new file mode 100644 index 00000000000..520794a365e --- /dev/null +++ b/swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll @@ -0,0 +1,27 @@ +/** + * Provides a taint-tracking configuration for reasoning about system + * commands built from user-controlled sources (that is, Command injection + * vulnerabilities). + */ + +import swift +import codeql.swift.dataflow.DataFlow +import codeql.swift.dataflow.TaintTracking +import codeql.swift.dataflow.FlowSources +import codeql.swift.security.CommandInjectionExtensions + +/** + * A taint configuration for tainted data that reaches a Command Injection sink. + */ +module CommandInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof FlowSource } + + predicate isSink(DataFlow::Node node) { node instanceof CommandInjectionSink } + + predicate isBarrier(DataFlow::Node barrier) { barrier instanceof CommandInjectionBarrier } +} + +/** + * Detect taint flow of tainted data that reaches a Command Injection sink. + */ +module CommandInjectionFlow = TaintTracking::Global; From cea3477ac204424b1ecdc05f14a8ec894c9c12d5 Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Wed, 12 Jul 2023 02:13:07 +0200 Subject: [PATCH 02/32] Qhelp and examples --- .../security/CommandInjectionExtensions.qll | 19 +++++++- .../2023-07-12-command-injection.md | 4 ++ .../Security/CWE-078/CommandInjection.qhelp | 45 +++++++++++++++++++ .../Security/CWE-078/CommandInjection.ql | 21 +++++++++ .../CWE-078/CommandInjectionBad.swift | 5 +++ .../CWE-078/CommandInjectionGood.swift | 13 ++++++ 6 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 swift/ql/src/change-notes/2023-07-12-command-injection.md create mode 100644 swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp create mode 100644 swift/ql/src/queries/Security/CWE-078/CommandInjection.ql create mode 100644 swift/ql/src/queries/Security/CWE-078/CommandInjectionBad.swift create mode 100644 swift/ql/src/queries/Security/CWE-078/CommandInjectionGood.swift diff --git a/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll index a553ab08955..5c34a2b9a85 100644 --- a/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll @@ -42,9 +42,26 @@ private class ProcessType extends NominalType { ProcessType() { this.getFullName() = "Process" } } +/** + * A `DataFlow::Node` that is an expression stored with the Realm database + * library. + */ +private class ProcessSink extends CommandInjectionSink instanceof DataFlow::Node { + ProcessSink() { + // any write into a class derived from `Process` is a sink. For + // example in `Process.launchPath = sensitive` the post-update node corresponding + // with `Process.launchPath` is a sink. + exists(NominalType t, Expr e | + t.getABaseType*().getUnderlyingType().getName() = "Process" and + e.getFullyConverted() = this.asExpr() and + e.getFullyConverted().getType() = t + ) + } +} + /** * A sink defined in a CSV model. */ private class DefaultCommandInjectionSink extends CommandInjectionSink { - DefaultCommandInjectionSink() { sinkNode(this, "command-injection") } + DefaultCommandInjectionSink() { sinkNode(this, "command-line-injection") } } diff --git a/swift/ql/src/change-notes/2023-07-12-command-injection.md b/swift/ql/src/change-notes/2023-07-12-command-injection.md new file mode 100644 index 00000000000..2befc7592b9 --- /dev/null +++ b/swift/ql/src/change-notes/2023-07-12-command-injection.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* Added new query "Command injection" (`swift/command-line-injection`). The query finds places where user input is used to execute system commands without proper escaping. \ No newline at end of file diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp b/swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp new file mode 100644 index 00000000000..80ebda716e0 --- /dev/null +++ b/swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp @@ -0,0 +1,45 @@ + + + + +

+Constructing a system command with unsanitized user input is dangerous, +since a malicious user to execute code. +

+
+ + +

+If possible, use hard-coded string literals to specify the command to run. Instead of interpreting +user input directly as command names, examine the input and then choose among hard-coded string +literals. +

+

+If this is not possible, then add sanitization code to verify that the user input is safe before +using it. +

+
+ + +

+The following examples execute code from user input without +sanitizing it first: +

+ +

+If user input is used to construct a regular expression it should be checked +first. This ensures that the user cannot insert characters that have special +meanings. +

+ +
+ + +
  • +OWASP: +Command Injection. +
  • +
    +
    \ No newline at end of file diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql b/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql new file mode 100644 index 00000000000..c81b13af10f --- /dev/null +++ b/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql @@ -0,0 +1,21 @@ +/** + * @name System command built from user-controlled sources + * @description Building a system command from user-controlled sources is vulnerable to insertion of malicious code by the user. + * @kind path-problem + * @problem.severity error + * @security-severity 9.8 + * @precision high + * @id swift/command-line-injection + * @tags security + * external/cwe/cwe-078 + */ + +import swift +import codeql.swift.dataflow.DataFlow +import codeql.swift.security.CommandInjectionQuery +import CommandInjectionFlow::PathGraph + +from CommandInjectionFlow::PathNode sourceNode, CommandInjectionFlow::PathNode sinkNode +where CommandInjectionFlow::flowPath(sourceNode, sinkNode) +select sinkNode.getNode(), sourceNode, sinkNode, "This command depends on a $@.", + sourceNode.getNode(), "user-provided value" diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjectionBad.swift b/swift/ql/src/queries/Security/CWE-078/CommandInjectionBad.swift new file mode 100644 index 00000000000..ffdaaf907ca --- /dev/null +++ b/swift/ql/src/queries/Security/CWE-078/CommandInjectionBad.swift @@ -0,0 +1,5 @@ +var task = Process() +task.launchPath = "/bin/bash" +task.arguments = ["-c", userControlledString] // BAD + +task.launch() \ No newline at end of file diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjectionGood.swift b/swift/ql/src/queries/Security/CWE-078/CommandInjectionGood.swift new file mode 100644 index 00000000000..3482718eeac --- /dev/null +++ b/swift/ql/src/queries/Security/CWE-078/CommandInjectionGood.swift @@ -0,0 +1,13 @@ +func validateCommand(_ command: String) -> String? { + let allowedCommands = ["ls -l", "pwd", "echo"] + if allowedCommands.contains(command) { + return command + } + return nil +} + +var task = Process() +task.launchPath = "/bin/bash" +task.arguments = ["-c", validateCommand(userControlledString)] // GOOD + +task.launch() \ No newline at end of file From d7d9ffc449b6d0f76702c937ce734f1b8071a233 Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Wed, 12 Jul 2023 16:44:17 +0200 Subject: [PATCH 03/32] Doc error Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com> --- .../lib/codeql/swift/security/CommandInjectionExtensions.qll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll index 5c34a2b9a85..bbcbe244daa 100644 --- a/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll @@ -43,8 +43,7 @@ private class ProcessType extends NominalType { } /** - * A `DataFlow::Node` that is an expression stored with the Realm database - * library. + * A `DataFlow::Node` that is written into a `Process` object. */ private class ProcessSink extends CommandInjectionSink instanceof DataFlow::Node { ProcessSink() { From c9fadd98f47fe8c5a050c6baed4fa53782b5a6b3 Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Wed, 12 Jul 2023 16:48:27 +0200 Subject: [PATCH 04/32] Support `CommandInjectionAdditionalFlowStep` and fix doc errors --- .../lib/codeql/swift/security/CommandInjectionExtensions.qll | 2 +- swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll | 4 ++++ swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp | 4 ++-- swift/ql/src/queries/Security/CWE-078/CommandInjection.ql | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll index bbcbe244daa..fee86714cf2 100644 --- a/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll @@ -62,5 +62,5 @@ private class ProcessSink extends CommandInjectionSink instanceof DataFlow::Node * A sink defined in a CSV model. */ private class DefaultCommandInjectionSink extends CommandInjectionSink { - DefaultCommandInjectionSink() { sinkNode(this, "command-line-injection") } + DefaultCommandInjectionSink() { sinkNode(this, "command-injection") } } diff --git a/swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll b/swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll index 520794a365e..4b67932209d 100644 --- a/swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll +++ b/swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll @@ -19,6 +19,10 @@ module CommandInjectionConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node node) { node instanceof CommandInjectionSink } predicate isBarrier(DataFlow::Node barrier) { barrier instanceof CommandInjectionBarrier } + + predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + any(CommandInjectionAdditionalFlowStep s).step(nodeFrom, nodeTo) + } } /** diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp b/swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp index 80ebda716e0..ab9562af12c 100644 --- a/swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp +++ b/swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp @@ -6,7 +6,7 @@

    Constructing a system command with unsanitized user input is dangerous, -since a malicious user to execute code. +since a malicious user may be able to craft input that executes arbitrary code.

    @@ -29,7 +29,7 @@ sanitizing it first:

    -If user input is used to construct a regular expression it should be checked +If user input is used to construct a command it should be checked first. This ensures that the user cannot insert characters that have special meanings.

    diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql b/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql index c81b13af10f..148676e1ac3 100644 --- a/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql +++ b/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql @@ -8,6 +8,7 @@ * @id swift/command-line-injection * @tags security * external/cwe/cwe-078 + * external/cwe/cwe-088 */ import swift From 378313332be8e3c8d473f89260bf27da665ba7ac Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Fri, 14 Jul 2023 20:55:24 +0200 Subject: [PATCH 05/32] Fix sink --- .../security/CommandInjectionExtensions.qll | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll index fee86714cf2..26e8782a799 100644 --- a/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll @@ -29,6 +29,25 @@ class CommandInjectionAdditionalFlowStep extends Unit { abstract predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo); } +private class ProcessSink2 extends CommandInjectionSink instanceof DataFlow::Node { + ProcessSink2() { + exists(AssignExpr assign, ProcessHost s | + assign.getDest() = s and + this.asExpr() = assign.getSource() + ) + or + exists(AssignExpr assign, ProcessHost s, ArrayExpr a | + assign.getDest() = s and + a = assign.getSource() and + this.asExpr() = a.getAnElement() + ) + } +} + +private class ProcessHost extends MemberRefExpr { + ProcessHost() { this.getBase() instanceof ProcessRef } +} + /** An expression of type `Process`. */ private class ProcessRef extends Expr { ProcessRef() { From bc4724b1fb374766e523c5bfdedd37cf104a6def Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Jul 2023 09:40:41 +0100 Subject: [PATCH 06/32] Swift: Test the customurlschemes fields that inherit taint. --- .../dataflow/flowsources/FlowSourcesInline.ql | 25 ++++- .../flowsources/customurlschemes.swift | 98 ++++++++++++++++--- 2 files changed, 110 insertions(+), 13 deletions(-) diff --git a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql index 71e6055b7d4..507f3582936 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql +++ b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql @@ -1,6 +1,16 @@ import swift import TestUtilities.InlineExpectationsTest import FlowConfig +import codeql.swift.dataflow.TaintTracking +import codeql.swift.dataflow.DataFlow + +module TaintReachConfiguration implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof FlowSource } + + predicate isSink(DataFlow::Node sink) { any() } +} + +module TaintReachFlow = TaintTracking::Global; string describe(FlowSource source) { source instanceof RemoteFlowSource and result = "remote" @@ -9,7 +19,7 @@ string describe(FlowSource source) { } module FlowSourcesTest implements TestSig { - string getARelevantTag() { result = "source" } + string getARelevantTag() { result = ["source", "tainted"] } predicate hasActualResult(Location location, string element, string tag, string value) { exists(FlowSource source | @@ -20,6 +30,19 @@ module FlowSourcesTest implements TestSig { value = describe(source) ) } + + predicate hasOptionalResult(Location location, string element, string tag, string value) { + // this is not really what the "flowsources" test is about, but sometimes it's helpful to + // confirm that taint reaches certain obvious points in the flow source test code. + exists(DataFlow::Node n | + TaintReachFlow::flowTo(n) and + location = n.getLocation() and + location.getFile().getBaseName() != "" and + element = n.toString() and + tag = "tainted" and + value = "" + ) + } } import MakeTest diff --git a/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift index 4a300dcd217..aeffb78c19c 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift @@ -26,12 +26,24 @@ protocol UIApplicationDelegate { } class UIScene { - class ConnectionOptions {} + class ConnectionOptions { + var userActivities: Set { get { return Set() } } + var urlContexts: Set { get { return Set() } } + } } class UISceneSession {} -class NSUserActivity {} +class NSUserActivity: Hashable { + static func == (lhs: NSUserActivity, rhs: NSUserActivity) -> Bool { + return true; + } + + func hash(into hasher: inout Hasher) {} + + var webpageURL: URL? { get { return nil } set { } } + var referrerURL: URL? { get { return nil } set { } } +} class UIOpenURLContext: Hashable { static func == (lhs: UIOpenURLContext, rhs: UIOpenURLContext) -> Bool { @@ -39,6 +51,8 @@ class UIOpenURLContext: Hashable { } func hash(into hasher: inout Hasher) {} + + var url: URL { get { return URL() } } } protocol UISceneDelegate { @@ -64,28 +78,88 @@ class AppDelegate: UIApplicationDelegate { } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool { - launchOptions?[.url] // $ source=remote + _ = launchOptions?[.url] // $ source=remote return true } func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool { - launchOptions?[.url] // $ source=remote + _ = launchOptions?[.url] // $ source=remote return true } } class SceneDelegate : UISceneDelegate { - func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // $ source=remote - func scene(_: UIScene, continue: NSUserActivity) {} // $ source=remote - func scene(_: UIScene, didUpdate: NSUserActivity) {} // $ source=remote - func scene(_: UIScene, openURLContexts: Set) {} // $ source=remote + func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) { // $ source=remote + for userActivity in options.userActivities { + let x = userActivity.webpageURL + x // $ MISSING: tainted + let y = userActivity.referrerURL + y // $ MISSING: tainted + } + + for urlContext in options.urlContexts { + let z = urlContext.url + z // $ MISSING: tainted + } + } + + func scene(_: UIScene, continue: NSUserActivity) { // $ source=remote + let x = `continue`.webpageURL + x // $ tainted + let y = `continue`.referrerURL + y // $ MISSING: tainted + } + + func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote + let x = didUpdate.webpageURL + x // $ tainted + let y = didUpdate.referrerURL + y // $ MISSING: tainted + } + + func scene(_: UIScene, openURLContexts: Set) { // $ source=remote + for openURLContext in openURLContexts { + let x = openURLContext.url + x // $ MISSING: tainted + } + } } class Extended {} extension Extended : UISceneDelegate { - func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // $ source=remote - func scene(_: UIScene, continue: NSUserActivity) {} // $ source=remote - func scene(_: UIScene, didUpdate: NSUserActivity) {} // $ source=remote - func scene(_: UIScene, openURLContexts: Set) {} // $ source=remote + func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) { // $ source=remote + for userActivity in options.userActivities { + let x = userActivity.webpageURL + x // $ MISSING: tainted + let y = userActivity.referrerURL + y // $ MISSING: tainted + } + + for urlContext in options.urlContexts { + let z = urlContext.url + z // $ MISSING: tainted + } + } + + func scene(_: UIScene, continue: NSUserActivity) { // $ source=remote + let x = `continue`.webpageURL + x // $ tainted + let y = `continue`.referrerURL + y // $ MISSING: tainted + } + + func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote + let x = didUpdate.webpageURL + x // $ tainted + let y = didUpdate.referrerURL + y // $ MISSING: tainted + } + + func scene(_: UIScene, openURLContexts: Set) { // $ source=remote + for openURLContext in openURLContexts { + let x = openURLContext.url + x // $ MISSING: tainted + } + } } From eca2c21af50666ecd59e304e8d8e496869da6878 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Sat, 15 Jul 2023 21:54:21 +0100 Subject: [PATCH 07/32] Swift: Model referrerURL. --- .../swift/frameworks/StandardLibrary/CustomUrlSchemes.qll | 2 +- .../dataflow/flowsources/customurlschemes.swift | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll index e217de4478d..3e2e8f76714 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll @@ -81,7 +81,7 @@ private class UserActivityUrlInheritTaint extends TaintInheritingContent, { UserActivityUrlInheritTaint() { this.getField().getEnclosingDecl().asNominalTypeDecl().getName() = "NSUserActivity" and - this.getField().getName() = "webpageURL" + this.getField().getName() = ["webpageURL", "referrerURL"] } } diff --git a/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift index aeffb78c19c..b26a411c2de 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift @@ -107,14 +107,14 @@ class SceneDelegate : UISceneDelegate { let x = `continue`.webpageURL x // $ tainted let y = `continue`.referrerURL - y // $ MISSING: tainted + y // $ tainted } func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote let x = didUpdate.webpageURL x // $ tainted let y = didUpdate.referrerURL - y // $ MISSING: tainted + y // $ tainted } func scene(_: UIScene, openURLContexts: Set) { // $ source=remote @@ -146,14 +146,14 @@ extension Extended : UISceneDelegate { let x = `continue`.webpageURL x // $ tainted let y = `continue`.referrerURL - y // $ MISSING: tainted + y // $ tainted } func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote let x = didUpdate.webpageURL x // $ tainted let y = didUpdate.referrerURL - y // $ MISSING: tainted + y // $ tainted } func scene(_: UIScene, openURLContexts: Set) { // $ source=remote From 70a9fe39748b29c800ecac5a9260ab9fc4f756b8 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Jul 2023 15:31:49 +0100 Subject: [PATCH 08/32] Swift: Change note. --- .../change-notes/2023-07-17-nsuseractivity-referrer-url.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 swift/ql/lib/change-notes/2023-07-17-nsuseractivity-referrer-url.md diff --git a/swift/ql/lib/change-notes/2023-07-17-nsuseractivity-referrer-url.md b/swift/ql/lib/change-notes/2023-07-17-nsuseractivity-referrer-url.md new file mode 100644 index 00000000000..03e90b39c05 --- /dev/null +++ b/swift/ql/lib/change-notes/2023-07-17-nsuseractivity-referrer-url.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- + +* Added taint flow for `NSUserActivity.referrerURL`. From 05cb429635ef8b50eaf0fd0a5f3260151d880c88 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Jul 2023 15:59:18 +0100 Subject: [PATCH 09/32] Swift: Add CfgConsistency.expected. --- .../dataflow/flowsources/CONSISTENCY/CfgConsistency.expected | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 swift/ql/test/library-tests/dataflow/flowsources/CONSISTENCY/CfgConsistency.expected diff --git a/swift/ql/test/library-tests/dataflow/flowsources/CONSISTENCY/CfgConsistency.expected b/swift/ql/test/library-tests/dataflow/flowsources/CONSISTENCY/CfgConsistency.expected new file mode 100644 index 00000000000..9a45a9ab720 --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/flowsources/CONSISTENCY/CfgConsistency.expected @@ -0,0 +1,3 @@ +deadEnd +| customurlschemes.swift:92:59:92:76 | options | +| customurlschemes.swift:131:59:131:76 | options | From 00e0e5a61a9570b19ede598668ca6eb074ddedbf Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 19 Jul 2023 11:36:09 +0200 Subject: [PATCH 10/32] Java: Add taint step for InputStream wrappers --- java/ql/lib/semmle/code/java/JDK.qll | 48 ++++++++++ .../code/java/dataflow/RangeAnalysis.qll | 2 +- .../library-tests/dataflow/stream-read/A.java | 87 +++++++++++++++++++ .../dataflow/stream-read/test.expected | 2 + .../dataflow/stream-read/test.ql | 2 + 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 java/ql/test/library-tests/dataflow/stream-read/A.java create mode 100644 java/ql/test/library-tests/dataflow/stream-read/test.expected create mode 100644 java/ql/test/library-tests/dataflow/stream-read/test.ql diff --git a/java/ql/lib/semmle/code/java/JDK.qll b/java/ql/lib/semmle/code/java/JDK.qll index 156cbbc0f93..59c132e16c9 100644 --- a/java/ql/lib/semmle/code/java/JDK.qll +++ b/java/ql/lib/semmle/code/java/JDK.qll @@ -4,6 +4,7 @@ import Member import semmle.code.java.security.ExternalProcess +private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.FlowSteps // --- Standard types --- @@ -177,6 +178,11 @@ class TypeObjectInputStream extends RefType { TypeObjectInputStream() { this.hasQualifiedName("java.io", "ObjectInputStream") } } +/** The class `java.io.InputStream`. */ +class TypeInputStream extends RefType { + TypeInputStream() { this.hasQualifiedName("java.io", "InputStream") } +} + /** The class `java.nio.file.Paths`. */ class TypePaths extends Class { TypePaths() { this.hasQualifiedName("java.nio.file", "Paths") } @@ -197,6 +203,48 @@ class TypeFile extends Class { TypeFile() { this.hasQualifiedName("java.io", "File") } } +/** + * A taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method + * to a class instance expression of the type extending `InputStream`. + * + * This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will + * normally only happen in anonymous classes. + */ +private class InputStreamWrapperAnonymousStep extends AdditionalTaintStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(Method m, AnonymousClass wrapper | + m.hasName("read") and + m.getDeclaringType() = wrapper and + wrapper.getASourceSupertype+() instanceof TypeInputStream + | + n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and + n2.asExpr() = wrapper.getClassInstanceExpr() + ) + } +} + +/** + * A taint step from an `InputStream` argument of the constructor of an `InputStream` subtype + * to the call of the constructor, only if the argument is assigned to a class field. + * + * This models how it's assumed that an `InputStream` wrapper is tainted by the wrapped stream, + * and is a workaround to low `fieldFlowBranchLimit`s in dataflow configurations. + */ +private class InputStreamWrapperConstructorStep extends AdditionalTaintStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(ClassInstanceExpr cc, Argument a, AssignExpr ae | + cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and + cc.getAnArgument() = a and + cc.getCallee().getParameter(a.getParameterPos()).getAnAccess() = ae.getRhs() and + ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof + TypeInputStream + | + n1.asExpr() = a and + n2.asExpr() = cc + ) + } +} + // --- Standard methods --- /** * DEPRECATED: Any constructor of class `java.lang.ProcessBuilder`. diff --git a/java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll b/java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll index c061f559251..53c0a83a536 100644 --- a/java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll +++ b/java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll @@ -757,7 +757,7 @@ private predicate baseBound(Expr e, int b, boolean upper) { or exists(Method read | e.(MethodAccess).getMethod().overrides*(read) and - read.getDeclaringType().hasQualifiedName("java.io", "InputStream") and + read.getDeclaringType() instanceof TypeInputStream and read.hasName("read") and read.getNumberOfParameters() = 0 | diff --git a/java/ql/test/library-tests/dataflow/stream-read/A.java b/java/ql/test/library-tests/dataflow/stream-read/A.java new file mode 100644 index 00000000000..a1b208a898a --- /dev/null +++ b/java/ql/test/library-tests/dataflow/stream-read/A.java @@ -0,0 +1,87 @@ +import java.io.InputStream; +import java.io.IOException; + +public class A { + + private static InputStream source() { + return null; + } + + private static void sink(Object s) {} + + static class MyStream extends InputStream { + private InputStream wrapped; + + MyStream(InputStream wrapped) { + this.wrapped = wrapped; + } + + @Override + public int read() throws IOException { + return 0; + } + + @Override + public int read(byte[] b) throws IOException { + return wrapped.read(b); + } + } + + public static void testSeveralWrappers() { + InputStream src = source(); + InputStream wrapper1 = new MyStream(src); + sink(wrapper1); // $ hasTaintFlow + InputStream wrapper2 = new MyStream(wrapper1); + sink(wrapper2); // $ hasTaintFlow + InputStream wrapper3 = new MyStream(wrapper2); + sink(wrapper3); // $ hasTaintFlow + + InputStream wrapper4 = new InputStream() { + @Override + public int read() throws IOException { + return 0; + } + + @Override + public int read(byte[] b) throws IOException { + return wrapper3.read(b); + + } + }; + sink(wrapper4); // $ hasTaintFlow + } + + public static void testAnonymous() throws Exception { + InputStream wrapper = new InputStream() { + @Override + public int read() throws IOException { + return 0; + } + + @Override + public int read(byte[] b) throws IOException { + InputStream in = source(); + return in.read(b); + } + }; + sink(wrapper); // $ hasTaintFlow + } + + public static void testAnonymousVarCapture() throws Exception { + InputStream in = source(); + InputStream wrapper = new InputStream() { + @Override + public int read() throws IOException { + return 0; + } + + @Override + public int read(byte[] b) throws IOException { + return in.read(b); + + } + }; + sink(wrapper); // $ hasTaintFlow + } + +} diff --git a/java/ql/test/library-tests/dataflow/stream-read/test.expected b/java/ql/test/library-tests/dataflow/stream-read/test.expected new file mode 100644 index 00000000000..48de9172b36 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/stream-read/test.expected @@ -0,0 +1,2 @@ +failures +testFailures diff --git a/java/ql/test/library-tests/dataflow/stream-read/test.ql b/java/ql/test/library-tests/dataflow/stream-read/test.ql new file mode 100644 index 00000000000..50e3f8d2f7d --- /dev/null +++ b/java/ql/test/library-tests/dataflow/stream-read/test.ql @@ -0,0 +1,2 @@ +import TestUtilities.InlineFlowTest +import DefaultFlowTest From 5330ce12cc1be4080af977698dee4c00b9a491da Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 19 Jul 2023 11:36:57 +0200 Subject: [PATCH 11/32] Use new TypeInputStream --- .../semmle/code/java/dataflow/internal/TaintTrackingUtil.qll | 4 ++-- java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll | 2 +- .../code/java/frameworks/javaee/ejb/EJBRestrictions.qll | 2 +- .../semmle/code/java/frameworks/spring/SpringController.qll | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index c992f92ee8a..6f8dbb1771b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -239,7 +239,7 @@ private class BulkData extends RefType { this.(Array).getElementType().(PrimitiveType).hasName(["byte", "char"]) or exists(RefType t | this.getASourceSupertype*() = t | - t.hasQualifiedName("java.io", "InputStream") or + t instanceof TypeInputStream or t.hasQualifiedName("java.nio", "ByteBuffer") or t.hasQualifiedName("java.lang", "Readable") or t.hasQualifiedName("java.io", "DataInput") or @@ -259,7 +259,7 @@ private class BulkData extends RefType { private predicate inputStreamWrapper(Constructor c, int argi) { not c.fromSource() and c.getParameterType(argi) instanceof BulkData and - c.getDeclaringType().getASourceSupertype+().hasQualifiedName("java.io", "InputStream") + c.getDeclaringType().getASourceSupertype+() instanceof TypeInputStream } /** An object construction that preserves the data flow status of any of its arguments. */ diff --git a/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll b/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll index c22f77725a1..64f26685b68 100644 --- a/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll +++ b/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll @@ -102,7 +102,7 @@ private module Dispatch { or t instanceof Interface and not t.fromSource() or - t.hasQualifiedName("java.io", "InputStream") + t instanceof TypeInputStream or t.hasQualifiedName("java.io", "Serializable") or diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll index 8df603c5d6a..461a7dc8208 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll @@ -317,7 +317,7 @@ class SystemSetInputStreamMethod extends Method { SystemSetInputStreamMethod() { this.hasName("setIn") and this.getNumberOfParameters() = 1 and - this.getParameter(0).getType().(RefType).hasQualifiedName("java.io", "InputStream") and + this.getParameter(0).getType() instanceof TypeInputStream and this.getDeclaringType() .getAnAncestor() .getSourceDeclaration() diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll index d40d1608969..f2611d6e2d1 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -237,7 +237,7 @@ class SpringRequestMappingParameter extends Parameter { private predicate isExplicitlyTaintedInput() { // InputStream or Reader parameters allow access to the body of a request - this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "InputStream") or + this.getType().(RefType).getAnAncestor() instanceof TypeInputStream or this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "Reader") or // The SpringServletInputAnnotations allow access to the URI, request parameters, cookie values and the body of the request this.getAnAnnotation() instanceof SpringServletInputAnnotation or From 3a6665b0ed9af96ad504652dd8f506a50cf63228 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 19 Jul 2023 12:51:00 +0200 Subject: [PATCH 12/32] Add change note --- .../lib/change-notes/2023-07-19-inputstream-wrapper-steps.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/lib/change-notes/2023-07-19-inputstream-wrapper-steps.md diff --git a/java/ql/lib/change-notes/2023-07-19-inputstream-wrapper-steps.md b/java/ql/lib/change-notes/2023-07-19-inputstream-wrapper-steps.md new file mode 100644 index 00000000000..aaeacf93e34 --- /dev/null +++ b/java/ql/lib/change-notes/2023-07-19-inputstream-wrapper-steps.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added more dataflow steps for `java.io.InputStream`s that wrap other `java.io.InputStream`s. From 0156fcc381f37f7773bd576ddf4277398f45f59d Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jul 2023 11:18:55 +0200 Subject: [PATCH 13/32] Apply suggestions from code review Co-authored-by: Anders Schack-Mulligen --- java/ql/lib/semmle/code/java/JDK.qll | 6 +++--- .../library-tests/dataflow/stream-read/A.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/JDK.qll b/java/ql/lib/semmle/code/java/JDK.qll index 59c132e16c9..c0c388f9308 100644 --- a/java/ql/lib/semmle/code/java/JDK.qll +++ b/java/ql/lib/semmle/code/java/JDK.qll @@ -232,10 +232,10 @@ private class InputStreamWrapperAnonymousStep extends AdditionalTaintStep { */ private class InputStreamWrapperConstructorStep extends AdditionalTaintStep { override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(ClassInstanceExpr cc, Argument a, AssignExpr ae | + exists(ClassInstanceExpr cc, Argument a, AssignExpr ae, int pos | cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and - cc.getAnArgument() = a and - cc.getCallee().getParameter(a.getParameterPos()).getAnAccess() = ae.getRhs() and + cc.getArgument(pragma[only_bind_into](pos)) = a and + cc.getCallee().getParameter(pragma[only_bind_into](pos)).getAnAccess() = ae.getRhs() and ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof TypeInputStream | diff --git a/java/ql/test/library-tests/dataflow/stream-read/A.java b/java/ql/test/library-tests/dataflow/stream-read/A.java index a1b208a898a..e66b99400d2 100644 --- a/java/ql/test/library-tests/dataflow/stream-read/A.java +++ b/java/ql/test/library-tests/dataflow/stream-read/A.java @@ -84,4 +84,22 @@ public class A { sink(wrapper); // $ hasTaintFlow } + public static InputStream wrapStream(InputStream in) { + return new InputStream() { + @Override + public int read() throws IOException { + return 0; + } + + @Override + public int read(byte[] b) throws IOException { + return in.read(b); + } + }; + } + + public static void testWrapCall() { + sink(wrapStream(null)); // no flow + sink(wrapStream(source())); // $ hasTaintFlow + } } From 1de68457aebe91818669d27a56353d8024c88a17 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jul 2023 11:18:17 +0200 Subject: [PATCH 14/32] Move steps to InputStream.qll --- java/ql/lib/semmle/code/java/JDK.qll | 43 ----------------- .../semmle/code/java/dataflow/FlowSteps.qll | 2 +- .../code/java/frameworks/InputStream.qll | 47 +++++++++++++++++++ 3 files changed, 48 insertions(+), 44 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/frameworks/InputStream.qll diff --git a/java/ql/lib/semmle/code/java/JDK.qll b/java/ql/lib/semmle/code/java/JDK.qll index c0c388f9308..6372b22c8f4 100644 --- a/java/ql/lib/semmle/code/java/JDK.qll +++ b/java/ql/lib/semmle/code/java/JDK.qll @@ -4,7 +4,6 @@ import Member import semmle.code.java.security.ExternalProcess -private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.FlowSteps // --- Standard types --- @@ -203,48 +202,6 @@ class TypeFile extends Class { TypeFile() { this.hasQualifiedName("java.io", "File") } } -/** - * A taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method - * to a class instance expression of the type extending `InputStream`. - * - * This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will - * normally only happen in anonymous classes. - */ -private class InputStreamWrapperAnonymousStep extends AdditionalTaintStep { - override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(Method m, AnonymousClass wrapper | - m.hasName("read") and - m.getDeclaringType() = wrapper and - wrapper.getASourceSupertype+() instanceof TypeInputStream - | - n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and - n2.asExpr() = wrapper.getClassInstanceExpr() - ) - } -} - -/** - * A taint step from an `InputStream` argument of the constructor of an `InputStream` subtype - * to the call of the constructor, only if the argument is assigned to a class field. - * - * This models how it's assumed that an `InputStream` wrapper is tainted by the wrapped stream, - * and is a workaround to low `fieldFlowBranchLimit`s in dataflow configurations. - */ -private class InputStreamWrapperConstructorStep extends AdditionalTaintStep { - override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(ClassInstanceExpr cc, Argument a, AssignExpr ae, int pos | - cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and - cc.getArgument(pragma[only_bind_into](pos)) = a and - cc.getCallee().getParameter(pragma[only_bind_into](pos)).getAnAccess() = ae.getRhs() and - ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof - TypeInputStream - | - n1.asExpr() = a and - n2.asExpr() = cc - ) - } -} - // --- Standard methods --- /** * DEPRECATED: Any constructor of class `java.lang.ProcessBuilder`. diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll index 1619965f0f0..fef69bec7fd 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll @@ -20,11 +20,11 @@ private module Frameworks { private import semmle.code.java.frameworks.Guice private import semmle.code.java.frameworks.IoJsonWebToken private import semmle.code.java.frameworks.jackson.JacksonSerializability + private import semmle.code.java.frameworks.InputStream private import semmle.code.java.frameworks.Properties private import semmle.code.java.frameworks.Protobuf private import semmle.code.java.frameworks.ratpack.RatpackExec private import semmle.code.java.frameworks.stapler.Stapler - private import semmle.code.java.JDK } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll new file mode 100644 index 00000000000..e0c524bd1a4 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll @@ -0,0 +1,47 @@ +/** Provides definitions related to `java.io.InputStream`. */ + +import java +private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.dataflow.FlowSteps + +/** + * A taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method + * to a class instance expression of the type extending `InputStream`. + * + * This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will + * normally only happen in anonymous classes. + */ +private class InputStreamWrapperAnonymousStep extends AdditionalTaintStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(Method m, AnonymousClass wrapper | + m.hasName("read") and + m.getDeclaringType() = wrapper and + wrapper.getASourceSupertype+() instanceof TypeInputStream + | + n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and + n2.asExpr() = wrapper.getClassInstanceExpr() + ) + } +} + +/** + * A taint step from an `InputStream` argument of the constructor of an `InputStream` subtype + * to the call of the constructor, only if the argument is assigned to a class field. + * + * This models how it's assumed that an `InputStream` wrapper is tainted by the wrapped stream, + * and is a workaround to low `fieldFlowBranchLimit`s in dataflow configurations. + */ +private class InputStreamWrapperConstructorStep extends AdditionalTaintStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(ClassInstanceExpr cc, Argument a, AssignExpr ae, int pos | + cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and + cc.getArgument(pragma[only_bind_into](pos)) = a and + cc.getCallee().getParameter(pragma[only_bind_into](pos)).getAnAccess() = ae.getRhs() and + ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof + TypeInputStream + | + n1.asExpr() = a and + n2.asExpr() = cc + ) + } +} From f054f738368b6819c66b41b716dde9ce586f23cb Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jul 2023 12:00:33 +0200 Subject: [PATCH 15/32] Apply suggestions from code review Co-authored-by: Anders Schack-Mulligen --- java/ql/lib/semmle/code/java/frameworks/InputStream.qll | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll index e0c524bd1a4..2f40220855a 100644 --- a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll +++ b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll @@ -13,13 +13,17 @@ private import semmle.code.java.dataflow.FlowSteps */ private class InputStreamWrapperAnonymousStep extends AdditionalTaintStep { override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(Method m, AnonymousClass wrapper | + exists(Method m, NestedClass wrapper | m.hasName("read") and m.getDeclaringType() = wrapper and wrapper.getASourceSupertype+() instanceof TypeInputStream | n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and - n2.asExpr() = wrapper.getClassInstanceExpr() + n2.asExpr() + .(ClassInstanceExpr) + .getConstructedType() + .getASourceSupertype*() + .getSourceDeclaration() = wrapper ) } } From 226103b246784f739dae09e049844809fe88de41 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jul 2023 12:01:26 +0200 Subject: [PATCH 16/32] Add local class test --- .../library-tests/dataflow/stream-read/A.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/java/ql/test/library-tests/dataflow/stream-read/A.java b/java/ql/test/library-tests/dataflow/stream-read/A.java index e66b99400d2..2ca284f483d 100644 --- a/java/ql/test/library-tests/dataflow/stream-read/A.java +++ b/java/ql/test/library-tests/dataflow/stream-read/A.java @@ -102,4 +102,21 @@ public class A { sink(wrapStream(null)); // no flow sink(wrapStream(source())); // $ hasTaintFlow } + + public static void testLocalClass() { + InputStream in = source(); + + class LocalInputStream extends InputStream { + @Override + public int read() throws IOException { + return 0; + } + + @Override + public int read(byte[] b) throws IOException { + return in.read(b); + } + } + sink(new LocalInputStream()); // $ hasTaintFlow + } } From cc5a404149ed29fe432ec59e9793f73bcf017515 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jul 2023 13:51:21 +0200 Subject: [PATCH 17/32] Add more test cases --- .../library-tests/dataflow/stream-read/A.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/java/ql/test/library-tests/dataflow/stream-read/A.java b/java/ql/test/library-tests/dataflow/stream-read/A.java index 2ca284f483d..705977757a1 100644 --- a/java/ql/test/library-tests/dataflow/stream-read/A.java +++ b/java/ql/test/library-tests/dataflow/stream-read/A.java @@ -103,7 +103,24 @@ public class A { sink(wrapStream(source())); // $ hasTaintFlow } - public static void testLocalClass() { + public static void testLocal() { + + class LocalInputStream extends InputStream { + @Override + public int read() throws IOException { + return 0; + } + + @Override + public int read(byte[] b) throws IOException { + InputStream in = source(); + return in.read(b); + } + } + sink(new LocalInputStream()); // $ hasTaintFlow + } + + public static void testLocalVarCapture() { InputStream in = source(); class LocalInputStream extends InputStream { From 36ff54b48b30076d7cb624549f537d9de36c1a01 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jul 2023 13:53:12 +0200 Subject: [PATCH 18/32] Convert jump step into local step Note that this has FNs in the test cases where the source is used locally in the nested classes' methods --- .../code/java/frameworks/InputStream.qll | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll index 2f40220855a..27d7da1b03a 100644 --- a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll +++ b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll @@ -3,27 +3,36 @@ import java private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.FlowSteps +private import semmle.code.java.dataflow.SSA +private import semmle.code.java.dataflow.TaintTracking /** - * A taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method + * A local taint step from the definition of a captured variable, the capturer of which + * updates the `bytes[]` parameter in an override of the `InputStream.read` method, * to a class instance expression of the type extending `InputStream`. * - * This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will - * normally only happen in anonymous classes. + * This models how a subtype of `InputStream` could be tainted by capturing tainted variables in + * the definition of its methods. */ -private class InputStreamWrapperAnonymousStep extends AdditionalTaintStep { +private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep { override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(Method m, NestedClass wrapper | - m.hasName("read") and + exists(InputStreamRead m, NestedClass wrapper, SsaVariable captured, SsaImplicitInit capturer | + wrapper.getASourceSupertype+() instanceof TypeInputStream and m.getDeclaringType() = wrapper and - wrapper.getASourceSupertype+() instanceof TypeInputStream - | - n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and + capturer.captures(captured) and + TaintTracking::localTaint(DataFlow::exprNode(capturer.getAFirstUse()), + any(DataFlow::PostUpdateNode pun | + pun.getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() + )) and n2.asExpr() .(ClassInstanceExpr) .getConstructedType() .getASourceSupertype*() .getSourceDeclaration() = wrapper + | + n1.asExpr() = captured.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() + or + captured.(SsaImplicitInit).isParameterDefinition(n1.asParameter()) ) } } @@ -49,3 +58,10 @@ private class InputStreamWrapperConstructorStep extends AdditionalTaintStep { ) } } + +private class InputStreamRead extends Method { + InputStreamRead() { + this.hasName("read") and + this.getDeclaringType().getASourceSupertype*() instanceof TypeInputStream + } +} From d3b3af8ae666fdc5d235dcc867a77f1fd6fa6328 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jul 2023 13:54:09 +0200 Subject: [PATCH 19/32] Re-adds jump step Note that this causes FP flow in the call context test cases --- .../code/java/frameworks/InputStream.qll | 23 +++++++++++++++++++ .../library-tests/dataflow/stream-read/A.java | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll index 27d7da1b03a..8f37ecc24ea 100644 --- a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll +++ b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll @@ -6,6 +6,29 @@ private import semmle.code.java.dataflow.FlowSteps private import semmle.code.java.dataflow.SSA private import semmle.code.java.dataflow.TaintTracking +/** + * A jump taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method + * to a class instance expression of the type extending `InputStream`. + * + * This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will + * normally only happen in nested classes. + */ +private class InputStreamWrapperCapturedJumpStep extends AdditionalTaintStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(InputStreamRead m, NestedClass wrapper | + m.getDeclaringType() = wrapper and + wrapper.getASourceSupertype+() instanceof TypeInputStream + | + n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and + n2.asExpr() + .(ClassInstanceExpr) + .getConstructedType() + .getASourceSupertype*() + .getSourceDeclaration() = wrapper + ) + } +} + /** * A local taint step from the definition of a captured variable, the capturer of which * updates the `bytes[]` parameter in an override of the `InputStream.read` method, diff --git a/java/ql/test/library-tests/dataflow/stream-read/A.java b/java/ql/test/library-tests/dataflow/stream-read/A.java index 705977757a1..779f95bcefa 100644 --- a/java/ql/test/library-tests/dataflow/stream-read/A.java +++ b/java/ql/test/library-tests/dataflow/stream-read/A.java @@ -99,7 +99,7 @@ public class A { } public static void testWrapCall() { - sink(wrapStream(null)); // no flow + sink(wrapStream(null)); // $ SPURIOUS: hasTaintFlow sink(wrapStream(source())); // $ hasTaintFlow } From 4e7438ac5c8319386ee26ed914d1f4ba0e52fee8 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jul 2023 14:15:16 +0200 Subject: [PATCH 20/32] Make sure that InputStreamWrapperCapturedLocalStep is indeed local --- java/ql/lib/semmle/code/java/frameworks/InputStream.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll index 8f37ecc24ea..fe433831386 100644 --- a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll +++ b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll @@ -39,6 +39,7 @@ private class InputStreamWrapperCapturedJumpStep extends AdditionalTaintStep { */ private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep { override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + n1.getEnclosingCallable() = n2.getEnclosingCallable() and exists(InputStreamRead m, NestedClass wrapper, SsaVariable captured, SsaImplicitInit capturer | wrapper.getASourceSupertype+() instanceof TypeInputStream and m.getDeclaringType() = wrapper and From 6c0d47f122dfcad898c5b114b2836fbb01296297 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jul 2023 15:42:12 +0200 Subject: [PATCH 21/32] Update java/ql/lib/semmle/code/java/frameworks/InputStream.qll Co-authored-by: Anders Schack-Mulligen --- java/ql/lib/semmle/code/java/frameworks/InputStream.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll index fe433831386..8f37ecc24ea 100644 --- a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll +++ b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll @@ -39,7 +39,6 @@ private class InputStreamWrapperCapturedJumpStep extends AdditionalTaintStep { */ private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep { override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - n1.getEnclosingCallable() = n2.getEnclosingCallable() and exists(InputStreamRead m, NestedClass wrapper, SsaVariable captured, SsaImplicitInit capturer | wrapper.getASourceSupertype+() instanceof TypeInputStream and m.getDeclaringType() = wrapper and From 374c157afea86bf6d71f33b6b51837ff2aa27ea0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:17:51 +0100 Subject: [PATCH 22/32] Swift: Update the taint aspect of the flowsources test to use sinks like the regular taint test. --- .../dataflow/flowsources/FlowSourcesInline.ql | 28 ++++++++------- .../flowsources/customurlschemes.swift | 34 ++++++++++--------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql index 507f3582936..0aa66486d99 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql +++ b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql @@ -4,13 +4,18 @@ import FlowConfig import codeql.swift.dataflow.TaintTracking import codeql.swift.dataflow.DataFlow -module TaintReachConfiguration implements DataFlow::ConfigSig { +module TestConfiguration implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src instanceof FlowSource } - predicate isSink(DataFlow::Node sink) { any() } + predicate isSink(DataFlow::Node sink) { + exists(CallExpr sinkCall | + sinkCall.getStaticTarget().getName().matches("sink%") and + sinkCall.getAnArgument().getExpr() = sink.asExpr() + ) + } } -module TaintReachFlow = TaintTracking::Global; +module TestFlow = TaintTracking::Global; string describe(FlowSource source) { source instanceof RemoteFlowSource and result = "remote" @@ -29,16 +34,13 @@ module FlowSourcesTest implements TestSig { tag = "source" and value = describe(source) ) - } - - predicate hasOptionalResult(Location location, string element, string tag, string value) { - // this is not really what the "flowsources" test is about, but sometimes it's helpful to - // confirm that taint reaches certain obvious points in the flow source test code. - exists(DataFlow::Node n | - TaintReachFlow::flowTo(n) and - location = n.getLocation() and - location.getFile().getBaseName() != "" and - element = n.toString() and + or + exists(DataFlow::Node source, DataFlow::Node sink | + // this is not really what the "flowsources" test is about, but sometimes it's helpful to + // have sinks and confirm that taint reaches obvious points in the flow source test code. + TestFlow::flow(source, sink) and + location = sink.getLocation() and + element = sink.toString() and tag = "tainted" and value = "" ) diff --git a/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift index b26a411c2de..eb50c15824b 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift @@ -62,6 +62,8 @@ protocol UISceneDelegate { func scene(_: UIScene, openURLContexts: Set) } +func sink(arg: Any) {} + // --- tests --- class AppDelegate: UIApplicationDelegate { @@ -92,35 +94,35 @@ class SceneDelegate : UISceneDelegate { func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) { // $ source=remote for userActivity in options.userActivities { let x = userActivity.webpageURL - x // $ MISSING: tainted + sink(arg: x) // $ MISSING: tainted let y = userActivity.referrerURL - y // $ MISSING: tainted + sink(arg: y) // $ MISSING: tainted } for urlContext in options.urlContexts { let z = urlContext.url - z // $ MISSING: tainted + sink(arg: z) // $ MISSING: tainted } } func scene(_: UIScene, continue: NSUserActivity) { // $ source=remote let x = `continue`.webpageURL - x // $ tainted + sink(arg: x) // $ tainted let y = `continue`.referrerURL - y // $ tainted + sink(arg: y) // $ tainted } func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote let x = didUpdate.webpageURL - x // $ tainted + sink(arg: x) // $ tainted let y = didUpdate.referrerURL - y // $ tainted + sink(arg: y) // $ tainted } func scene(_: UIScene, openURLContexts: Set) { // $ source=remote for openURLContext in openURLContexts { let x = openURLContext.url - x // $ MISSING: tainted + sink(arg: x) // $ MISSING: tainted } } } @@ -131,35 +133,35 @@ extension Extended : UISceneDelegate { func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) { // $ source=remote for userActivity in options.userActivities { let x = userActivity.webpageURL - x // $ MISSING: tainted + sink(arg: x) // $ MISSING: tainted let y = userActivity.referrerURL - y // $ MISSING: tainted + sink(arg: y) // $ MISSING: tainted } for urlContext in options.urlContexts { let z = urlContext.url - z // $ MISSING: tainted + sink(arg: z) // $ MISSING: tainted } } func scene(_: UIScene, continue: NSUserActivity) { // $ source=remote let x = `continue`.webpageURL - x // $ tainted + sink(arg: x) // $ tainted let y = `continue`.referrerURL - y // $ tainted + sink(arg: y) // $ tainted } func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote let x = didUpdate.webpageURL - x // $ tainted + sink(arg: x) // $ tainted let y = didUpdate.referrerURL - y // $ tainted + sink(arg: y) // $ tainted } func scene(_: UIScene, openURLContexts: Set) { // $ source=remote for openURLContext in openURLContexts { let x = openURLContext.url - x // $ MISSING: tainted + sink(arg: x) // $ MISSING: tainted } } } From 44d785fabf6433857d13c907b2db19f7ae697c41 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:37:13 +0100 Subject: [PATCH 23/32] Swift: Make QL-for-QL happy. --- .../library-tests/dataflow/flowsources/FlowSourcesInline.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql index 0aa66486d99..25b3b327a70 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql +++ b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql @@ -35,10 +35,10 @@ module FlowSourcesTest implements TestSig { value = describe(source) ) or - exists(DataFlow::Node source, DataFlow::Node sink | + exists(DataFlow::Node sink | // this is not really what the "flowsources" test is about, but sometimes it's helpful to // have sinks and confirm that taint reaches obvious points in the flow source test code. - TestFlow::flow(source, sink) and + TestFlow::flow(_, sink) and location = sink.getLocation() and element = sink.toString() and tag = "tainted" and From 3eb1bac9df99f0ad2e90094a65d3a436b71a442b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 27 Jul 2023 16:11:59 +0100 Subject: [PATCH 24/32] Swift: Update consistency test failure (line numbers). --- .../dataflow/flowsources/CONSISTENCY/CfgConsistency.expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swift/ql/test/library-tests/dataflow/flowsources/CONSISTENCY/CfgConsistency.expected b/swift/ql/test/library-tests/dataflow/flowsources/CONSISTENCY/CfgConsistency.expected index 9a45a9ab720..ac216c004f2 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/CONSISTENCY/CfgConsistency.expected +++ b/swift/ql/test/library-tests/dataflow/flowsources/CONSISTENCY/CfgConsistency.expected @@ -1,3 +1,3 @@ deadEnd -| customurlschemes.swift:92:59:92:76 | options | -| customurlschemes.swift:131:59:131:76 | options | +| customurlschemes.swift:94:59:94:76 | options | +| customurlschemes.swift:133:59:133:76 | options | From d0a912fb025f75c0762fec39bd857b2f1dbb9752 Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Thu, 27 Jul 2023 22:45:05 +0200 Subject: [PATCH 25/32] Update swift/ql/src/queries/Security/CWE-078/CommandInjection.ql Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com> --- swift/ql/src/queries/Security/CWE-078/CommandInjection.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql b/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql index 148676e1ac3..eb501556b29 100644 --- a/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql +++ b/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql @@ -9,6 +9,7 @@ * @tags security * external/cwe/cwe-078 * external/cwe/cwe-088 + * external/cwe/cwe-088 */ import swift From d9800c7bb63a5246fc77a986e9273a91082deb22 Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Thu, 27 Jul 2023 22:45:50 +0200 Subject: [PATCH 26/32] Update CommandInjection.ql --- swift/ql/src/queries/Security/CWE-078/CommandInjection.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql b/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql index eb501556b29..148676e1ac3 100644 --- a/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql +++ b/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql @@ -9,7 +9,6 @@ * @tags security * external/cwe/cwe-078 * external/cwe/cwe-088 - * external/cwe/cwe-088 */ import swift From 2a49219127c4d0b289901ee8e062049ee560fc17 Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Fri, 28 Jul 2023 00:15:33 +0200 Subject: [PATCH 27/32] Move query to experimental --- .../Security/CWE-078/CommandInjection.qhelp | 0 .../Security/CWE-078/CommandInjection.ql | 0 .../Security/CWE-078/CommandInjectionBad.swift | 0 .../Security/CWE-078/CommandInjectionGood.swift | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename swift/ql/src/{queries => experimental}/Security/CWE-078/CommandInjection.qhelp (100%) rename swift/ql/src/{queries => experimental}/Security/CWE-078/CommandInjection.ql (100%) rename swift/ql/src/{queries => experimental}/Security/CWE-078/CommandInjectionBad.swift (100%) rename swift/ql/src/{queries => experimental}/Security/CWE-078/CommandInjectionGood.swift (100%) diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp b/swift/ql/src/experimental/Security/CWE-078/CommandInjection.qhelp similarity index 100% rename from swift/ql/src/queries/Security/CWE-078/CommandInjection.qhelp rename to swift/ql/src/experimental/Security/CWE-078/CommandInjection.qhelp diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjection.ql b/swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql similarity index 100% rename from swift/ql/src/queries/Security/CWE-078/CommandInjection.ql rename to swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjectionBad.swift b/swift/ql/src/experimental/Security/CWE-078/CommandInjectionBad.swift similarity index 100% rename from swift/ql/src/queries/Security/CWE-078/CommandInjectionBad.swift rename to swift/ql/src/experimental/Security/CWE-078/CommandInjectionBad.swift diff --git a/swift/ql/src/queries/Security/CWE-078/CommandInjectionGood.swift b/swift/ql/src/experimental/Security/CWE-078/CommandInjectionGood.swift similarity index 100% rename from swift/ql/src/queries/Security/CWE-078/CommandInjectionGood.swift rename to swift/ql/src/experimental/Security/CWE-078/CommandInjectionGood.swift From 90ac5b905b89aa92f8b14a97945a3ad0e902ed40 Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Fri, 28 Jul 2023 00:21:02 +0200 Subject: [PATCH 28/32] --- swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql b/swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql index 148676e1ac3..98d68d0a101 100644 --- a/swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql +++ b/swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql @@ -19,4 +19,4 @@ import CommandInjectionFlow::PathGraph from CommandInjectionFlow::PathNode sourceNode, CommandInjectionFlow::PathNode sinkNode where CommandInjectionFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "This command depends on a $@.", - sourceNode.getNode(), "user-provided value" + sourceNode.getNode(), "user-provided value" \ No newline at end of file From 0bc75ea9b79c26be985c4a162932b1ccb020cb88 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Sat, 29 Jul 2023 18:44:28 +0200 Subject: [PATCH 29/32] C++: Add forgotten parentheses in ternary IR test Without the parentheses, the expressions are parsed as `a ? x : (y = val)`. --- .../library-tests/ir/ir/PrintAST.expected | 125 ++++++------ cpp/ql/test/library-tests/ir/ir/ir.cpp | 6 +- .../ir/ir/operand_locations.expected | 185 +++++++++--------- .../test/library-tests/ir/ir/raw_ir.expected | 158 +++++++-------- 4 files changed, 242 insertions(+), 232 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 3f4a29c59c6..1e79068390e 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -15030,25 +15030,28 @@ ir.cpp: # 1999| Value = [Literal] 5 # 1999| ValueCategory = prvalue # 2000| getStmt(3): [ExprStmt] ExprStmt -# 2000| getExpr(): [ConditionalExpr] ... ? ... : ... +# 2000| getExpr(): [AssignExpr] ... = ... # 2000| Type = [IntType] int # 2000| ValueCategory = lvalue -# 2000| getCondition(): [VariableAccess] a -# 2000| Type = [BoolType] bool -# 2000| ValueCategory = prvalue(load) -# 2000| getThen(): [VariableAccess] x +# 2000| getLValue(): [ConditionalExpr] ... ? ... : ... # 2000| Type = [IntType] int # 2000| ValueCategory = lvalue -# 2000| getElse(): [AssignExpr] ... = ... -# 2000| Type = [IntType] int -# 2000| ValueCategory = lvalue -# 2000| getLValue(): [VariableAccess] y +# 2000| getCondition(): [VariableAccess] a +# 2000| Type = [BoolType] bool +# 2000| ValueCategory = prvalue(load) +# 2000| getThen(): [VariableAccess] x # 2000| Type = [IntType] int # 2000| ValueCategory = lvalue -# 2000| getRValue(): [Literal] 7 +# 2000| getElse(): [VariableAccess] y # 2000| Type = [IntType] int -# 2000| Value = [Literal] 7 -# 2000| ValueCategory = prvalue +# 2000| ValueCategory = lvalue +# 2000| getRValue(): [Literal] 7 +# 2000| Type = [IntType] int +# 2000| Value = [Literal] 7 +# 2000| ValueCategory = prvalue +# 2000| getLValue().getFullyConverted(): [ParenthesisExpr] (...) +# 2000| Type = [IntType] int +# 2000| ValueCategory = lvalue # 2001| getStmt(4): [ReturnStmt] return ... # 2003| [CopyAssignmentOperator] TernaryPodObj& TernaryPodObj::operator=(TernaryPodObj const&) # 2003| : @@ -15151,31 +15154,34 @@ ir.cpp: # 2010| getExpr(): [AssignExpr] ... = ... # 2010| Type = [Struct] TernaryPodObj # 2010| ValueCategory = lvalue -# 2010| getLValue(): [VariableAccess] z +# 2010| getLValue(): [AssignExpr] ... = ... # 2010| Type = [Struct] TernaryPodObj # 2010| ValueCategory = lvalue -# 2010| getRValue(): [ConditionalExpr] ... ? ... : ... -# 2010| Type = [Struct] TernaryPodObj -# 2010| ValueCategory = prvalue -# 2010| getCondition(): [VariableAccess] a -# 2010| Type = [BoolType] bool -# 2010| ValueCategory = prvalue(load) -# 2010| getThen(): [VariableAccess] x +# 2010| getLValue(): [VariableAccess] z # 2010| Type = [Struct] TernaryPodObj -# 2010| ValueCategory = prvalue(load) -# 2010| getElse(): [AssignExpr] ... = ... +# 2010| ValueCategory = lvalue +# 2010| getRValue(): [ConditionalExpr] ... ? ... : ... # 2010| Type = [Struct] TernaryPodObj # 2010| ValueCategory = prvalue -# 2010| getLValue(): [VariableAccess] y -# 2010| Type = [Struct] TernaryPodObj -# 2010| ValueCategory = lvalue -# 2010| getRValue(): [Literal] 0 -# 2010| Type = [Struct] TernaryPodObj -# 2010| Value = [Literal] 0 -# 2010| ValueCategory = prvalue -# 2010| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object +# 2010| getCondition(): [VariableAccess] a +# 2010| Type = [BoolType] bool +# 2010| ValueCategory = prvalue(load) +# 2010| getThen(): [VariableAccess] x # 2010| Type = [Struct] TernaryPodObj # 2010| ValueCategory = prvalue(load) +# 2010| getElse(): [VariableAccess] y +# 2010| Type = [Struct] TernaryPodObj +# 2010| ValueCategory = prvalue(load) +# 2010| getRValue(): [Literal] 0 +# 2010| Type = [Struct] TernaryPodObj +# 2010| Value = [Literal] 0 +# 2010| ValueCategory = prvalue +# 2010| getLValue().getFullyConverted(): [ParenthesisExpr] (...) +# 2010| Type = [Struct] TernaryPodObj +# 2010| ValueCategory = lvalue +# 2010| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object +# 2010| Type = [Struct] TernaryPodObj +# 2010| ValueCategory = prvalue(load) # 2011| getStmt(4): [ReturnStmt] return ... # 2013| [CopyAssignmentOperator] TernaryNonPodObj& TernaryNonPodObj::operator=(TernaryNonPodObj const&) # 2013| : @@ -15339,38 +15345,38 @@ ir.cpp: # 2021| getExpr(): [FunctionCall] call to operator= # 2021| Type = [LValueReferenceType] TernaryNonPodObj & # 2021| ValueCategory = prvalue -# 2021| getQualifier(): [VariableAccess] z -# 2021| Type = [Struct] TernaryNonPodObj -# 2021| ValueCategory = lvalue -# 2021| getArgument(0): [ConditionalExpr] ... ? ... : ... -# 2021| Type = [Struct] TernaryNonPodObj -# 2021| ValueCategory = lvalue -# 2021| getCondition(): [VariableAccess] a -# 2021| Type = [BoolType] bool -# 2021| ValueCategory = prvalue(load) -# 2021| getThen(): [VariableAccess] x +# 2021| getQualifier(): [FunctionCall] call to operator= +# 2021| Type = [LValueReferenceType] TernaryNonPodObj & +# 2021| ValueCategory = prvalue +# 2021| getQualifier(): [VariableAccess] z # 2021| Type = [Struct] TernaryNonPodObj # 2021| ValueCategory = lvalue -# 2021| getElse(): [FunctionCall] call to operator= -# 2021| Type = [LValueReferenceType] TernaryNonPodObj & -# 2021| ValueCategory = prvalue -# 2021| getQualifier(): [VariableAccess] y +# 2021| getArgument(0): [ConditionalExpr] ... ? ... : ... +# 2021| Type = [Struct] TernaryNonPodObj +# 2021| ValueCategory = lvalue +# 2021| getCondition(): [VariableAccess] a +# 2021| Type = [BoolType] bool +# 2021| ValueCategory = prvalue(load) +# 2021| getThen(): [VariableAccess] x # 2021| Type = [Struct] TernaryNonPodObj # 2021| ValueCategory = lvalue -# 2021| getArgument(0): [ConstructorCall] call to TernaryNonPodObj -# 2021| Type = [VoidType] void -# 2021| ValueCategory = prvalue -# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) -# 2021| Type = [LValueReferenceType] const TernaryNonPodObj & -# 2021| ValueCategory = prvalue -# 2021| getExpr(): [CStyleCast] (const TernaryNonPodObj)... -# 2021| Conversion = [GlvalueConversion] glvalue conversion -# 2021| Type = [SpecifiedType] const TernaryNonPodObj -# 2021| ValueCategory = lvalue -# 2021| getExpr(): [TemporaryObjectExpr] temporary object -# 2021| Type = [Struct] TernaryNonPodObj -# 2021| ValueCategory = lvalue -# 2021| getElse().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) +# 2021| getElse(): [VariableAccess] y +# 2021| Type = [Struct] TernaryNonPodObj +# 2021| ValueCategory = lvalue +# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) +# 2021| Type = [LValueReferenceType] const TernaryNonPodObj & +# 2021| ValueCategory = prvalue +# 2021| getExpr(): [CStyleCast] (const TernaryNonPodObj)... +# 2021| Conversion = [GlvalueConversion] glvalue conversion +# 2021| Type = [SpecifiedType] const TernaryNonPodObj +# 2021| ValueCategory = lvalue +# 2021| getArgument(0): [ConstructorCall] call to TernaryNonPodObj +# 2021| Type = [VoidType] void +# 2021| ValueCategory = prvalue +# 2021| getQualifier().getFullyConverted(): [ParenthesisExpr] (...) +# 2021| Type = [Struct] TernaryNonPodObj +# 2021| ValueCategory = lvalue +# 2021| getExpr(): [ReferenceDereferenceExpr] (reference dereference) # 2021| Type = [Struct] TernaryNonPodObj # 2021| ValueCategory = lvalue # 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) @@ -15380,6 +15386,9 @@ ir.cpp: # 2021| Conversion = [GlvalueConversion] glvalue conversion # 2021| Type = [SpecifiedType] const TernaryNonPodObj # 2021| ValueCategory = lvalue +# 2021| getExpr(): [TemporaryObjectExpr] temporary object +# 2021| Type = [Struct] TernaryNonPodObj +# 2021| ValueCategory = lvalue # 2021| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 2021| Type = [Struct] TernaryNonPodObj # 2021| ValueCategory = lvalue diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index 2f78d82a48e..4568026c7f4 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -1997,7 +1997,7 @@ void TernaryTestInt(bool a, int x, int y, int z) { z = a ? x : y; z = a ? x : 5; z = a ? 3 : 5; - a ? x : y = 7; + (a ? x : y) = 7; } struct TernaryPodObj { @@ -2007,7 +2007,7 @@ void TernaryTestPodObj(bool a, TernaryPodObj x, TernaryPodObj y, TernaryPodObj z z = a ? x : y; z = a ? x : TernaryPodObj(); z = a ? TernaryPodObj() : TernaryPodObj(); - z = a ? x : y = TernaryPodObj(); + (z = a ? x : y) = TernaryPodObj(); } struct TernaryNonPodObj { @@ -2018,7 +2018,7 @@ void TernaryTestNonPodObj(bool a, TernaryNonPodObj x, TernaryNonPodObj y, Ternar z = a ? x : y; z = a ? x : TernaryNonPodObj(); z = a ? TernaryNonPodObj() : TernaryNonPodObj(); - z = a ? x : y = TernaryNonPodObj(); + (z = a ? x : y) = TernaryNonPodObj(); } // semmle-extractor-options: -std=c++17 --clang diff --git a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected index 8ef33ff286d..f06eceb9965 100644 --- a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected +++ b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected @@ -9078,7 +9078,7 @@ | ir.cpp:1993:13:1993:32 | StoreValue | r1993_2 | | ir.cpp:1996:6:1996:19 | ChiPartial | partial:m1996_3 | | ir.cpp:1996:6:1996:19 | ChiTotal | total:m1996_2 | -| ir.cpp:1996:6:1996:19 | SideEffect | m1996_3 | +| ir.cpp:1996:6:1996:19 | SideEffect | ~m2000_9 | | ir.cpp:1996:26:1996:26 | Address | &:r1996_5 | | ir.cpp:1996:33:1996:33 | Address | &:r1996_7 | | ir.cpp:1996:40:1996:40 | Address | &:r1996_9 | @@ -9128,20 +9128,21 @@ | ir.cpp:1999:9:1999:17 | StoreValue | r1999_6 | | ir.cpp:1999:13:1999:13 | StoreValue | r1999_9 | | ir.cpp:1999:17:1999:17 | StoreValue | r1999_12 | -| ir.cpp:2000:5:2000:5 | Address | &:r2000_1 | -| ir.cpp:2000:5:2000:5 | Condition | r2000_2 | -| ir.cpp:2000:5:2000:5 | Load | m1996_6 | -| ir.cpp:2000:5:2000:17 | Address | &:r2000_5 | -| ir.cpp:2000:5:2000:17 | Address | &:r2000_8 | -| ir.cpp:2000:5:2000:17 | Address | &:r2000_14 | -| ir.cpp:2000:5:2000:17 | Load | m2000_4 | -| ir.cpp:2000:5:2000:17 | Phi | from 11:m2000_9 | -| ir.cpp:2000:5:2000:17 | Phi | from 12:m2000_15 | -| ir.cpp:2000:9:2000:9 | StoreValue | r2000_7 | -| ir.cpp:2000:13:2000:13 | Address | &:r2000_11 | -| ir.cpp:2000:13:2000:13 | Unary | r2000_11 | -| ir.cpp:2000:13:2000:17 | StoreValue | r2000_13 | -| ir.cpp:2000:17:2000:17 | StoreValue | r2000_10 | +| ir.cpp:2000:5:2000:19 | ChiPartial | partial:m2000_8 | +| ir.cpp:2000:5:2000:19 | ChiTotal | total:m1996_4 | +| ir.cpp:2000:6:2000:6 | Address | &:r2000_2 | +| ir.cpp:2000:6:2000:6 | Condition | r2000_3 | +| ir.cpp:2000:6:2000:6 | Load | m1996_6 | +| ir.cpp:2000:6:2000:14 | Address | &:r2000_6 | +| ir.cpp:2000:6:2000:14 | Address | &:r2000_7 | +| ir.cpp:2000:6:2000:14 | Address | &:r2000_11 | +| ir.cpp:2000:6:2000:14 | Address | &:r2000_14 | +| ir.cpp:2000:6:2000:14 | Load | m2000_5 | +| ir.cpp:2000:6:2000:14 | Phi | from 11:m2000_12 | +| ir.cpp:2000:6:2000:14 | Phi | from 12:m2000_15 | +| ir.cpp:2000:10:2000:10 | StoreValue | r2000_10 | +| ir.cpp:2000:14:2000:14 | StoreValue | r2000_13 | +| ir.cpp:2000:19:2000:19 | StoreValue | r2000_1 | | ir.cpp:2006:6:2006:22 | ChiPartial | partial:m2006_3 | | ir.cpp:2006:6:2006:22 | ChiTotal | total:m2006_2 | | ir.cpp:2006:6:2006:22 | SideEffect | m2006_3 | @@ -9218,28 +9219,30 @@ | ir.cpp:2009:31:2009:45 | Load | m2009_20 | | ir.cpp:2009:31:2009:45 | StoreValue | r2009_19 | | ir.cpp:2009:31:2009:45 | StoreValue | r2009_21 | -| ir.cpp:2010:5:2010:5 | Address | &:r2010_7 | -| ir.cpp:2010:9:2010:9 | Address | &:r2010_1 | -| ir.cpp:2010:9:2010:9 | Condition | r2010_2 | -| ir.cpp:2010:9:2010:9 | Load | m2006_6 | -| ir.cpp:2010:9:2010:35 | Address | &:r2010_5 | -| ir.cpp:2010:9:2010:35 | Address | &:r2010_11 | -| ir.cpp:2010:9:2010:35 | Address | &:r2010_20 | -| ir.cpp:2010:9:2010:35 | Load | m2010_4 | -| ir.cpp:2010:9:2010:35 | Phi | from 11:m2010_12 | -| ir.cpp:2010:9:2010:35 | Phi | from 12:m2010_21 | -| ir.cpp:2010:9:2010:35 | StoreValue | r2010_6 | -| ir.cpp:2010:13:2010:13 | Address | &:r2010_9 | -| ir.cpp:2010:13:2010:13 | Load | m2006_8 | -| ir.cpp:2010:13:2010:13 | StoreValue | r2010_10 | -| ir.cpp:2010:17:2010:17 | Address | &:r2010_17 | -| ir.cpp:2010:17:2010:35 | StoreValue | r2010_19 | -| ir.cpp:2010:21:2010:35 | Address | &:r2010_13 | -| ir.cpp:2010:21:2010:35 | Address | &:r2010_13 | -| ir.cpp:2010:21:2010:35 | Load | m2010_15 | -| ir.cpp:2010:21:2010:35 | StoreValue | r2010_14 | -| ir.cpp:2010:21:2010:35 | StoreValue | r2010_16 | -| ir.cpp:2010:21:2010:35 | Unary | r2010_16 | +| ir.cpp:2010:6:2010:6 | Address | &:r2010_11 | +| ir.cpp:2010:6:2010:6 | Unary | r2010_11 | +| ir.cpp:2010:6:2010:18 | Address | &:r2010_13 | +| ir.cpp:2010:10:2010:10 | Address | &:r2010_5 | +| ir.cpp:2010:10:2010:10 | Condition | r2010_6 | +| ir.cpp:2010:10:2010:10 | Load | m2006_6 | +| ir.cpp:2010:10:2010:18 | Address | &:r2010_9 | +| ir.cpp:2010:10:2010:18 | Address | &:r2010_17 | +| ir.cpp:2010:10:2010:18 | Address | &:r2010_21 | +| ir.cpp:2010:10:2010:18 | Load | m2010_8 | +| ir.cpp:2010:10:2010:18 | Phi | from 11:m2010_18 | +| ir.cpp:2010:10:2010:18 | Phi | from 12:m2010_22 | +| ir.cpp:2010:10:2010:18 | StoreValue | r2010_10 | +| ir.cpp:2010:14:2010:14 | Address | &:r2010_15 | +| ir.cpp:2010:14:2010:14 | Load | m2006_8 | +| ir.cpp:2010:14:2010:14 | StoreValue | r2010_16 | +| ir.cpp:2010:18:2010:18 | Address | &:r2010_19 | +| ir.cpp:2010:18:2010:18 | Load | m2006_10 | +| ir.cpp:2010:18:2010:18 | StoreValue | r2010_20 | +| ir.cpp:2010:23:2010:37 | Address | &:r2010_1 | +| ir.cpp:2010:23:2010:37 | Address | &:r2010_1 | +| ir.cpp:2010:23:2010:37 | Load | m2010_3 | +| ir.cpp:2010:23:2010:37 | StoreValue | r2010_2 | +| ir.cpp:2010:23:2010:37 | StoreValue | r2010_4 | | ir.cpp:2013:8:2013:8 | Address | &:r2013_5 | | ir.cpp:2013:8:2013:8 | Address | &:r2013_5 | | ir.cpp:2013:8:2013:8 | Address | &:r2013_5 | @@ -9280,7 +9283,7 @@ | ir.cpp:2014:13:2014:29 | SideEffect | m2014_8 | | ir.cpp:2017:6:2017:25 | ChiPartial | partial:m2017_3 | | ir.cpp:2017:6:2017:25 | ChiTotal | total:m2017_2 | -| ir.cpp:2017:6:2017:25 | SideEffect | ~m2021_14 | +| ir.cpp:2017:6:2017:25 | SideEffect | ~m2021_32 | | ir.cpp:2017:32:2017:32 | Address | &:r2017_5 | | ir.cpp:2017:52:2017:52 | Address | &:r2017_7 | | ir.cpp:2017:72:2017:72 | Address | &:r2017_9 | @@ -9423,60 +9426,58 @@ | ir.cpp:2020:34:2020:51 | Load | m2020_40 | | ir.cpp:2020:34:2020:51 | SideEffect | ~m2019_16 | | ir.cpp:2020:34:2020:51 | StoreValue | r2020_41 | -| ir.cpp:2021:5:2021:5 | Address | &:r2021_1 | -| ir.cpp:2021:5:2021:5 | Address | &:r2021_1 | -| ir.cpp:2021:5:2021:5 | Arg(this) | this:r2021_1 | -| ir.cpp:2021:5:2021:5 | ChiPartial | partial:m2021_17 | -| ir.cpp:2021:5:2021:5 | ChiTotal | total:m2020_20 | -| ir.cpp:2021:5:2021:5 | SideEffect | m2020_20 | -| ir.cpp:2021:7:2021:7 | CallTarget | func:r2021_2 | -| ir.cpp:2021:7:2021:7 | ChiPartial | partial:m2021_13 | -| ir.cpp:2021:7:2021:7 | ChiTotal | total:m2021_6 | -| ir.cpp:2021:7:2021:7 | SideEffect | ~m2021_6 | -| ir.cpp:2021:7:2021:7 | Unary | r2021_12 | -| ir.cpp:2021:9:2021:9 | Address | &:r2021_3 | -| ir.cpp:2021:9:2021:9 | Condition | r2021_4 | -| ir.cpp:2021:9:2021:9 | Load | m2017_6 | -| ir.cpp:2021:9:2021:38 | Address | &:r2021_8 | -| ir.cpp:2021:9:2021:38 | Address | &:r2021_11 | -| ir.cpp:2021:9:2021:38 | Address | &:r2021_21 | -| ir.cpp:2021:9:2021:38 | Address | &:r2021_43 | -| ir.cpp:2021:9:2021:38 | Arg(0) | 0:r2021_11 | -| ir.cpp:2021:9:2021:38 | Load | m2021_7 | -| ir.cpp:2021:9:2021:38 | Phi | from 11:m2021_22 | -| ir.cpp:2021:9:2021:38 | Phi | from 11:~m2020_16 | -| ir.cpp:2021:9:2021:38 | Phi | from 12:m2021_44 | -| ir.cpp:2021:9:2021:38 | Phi | from 12:~m2021_37 | -| ir.cpp:2021:9:2021:38 | SideEffect | ~m2021_14 | -| ir.cpp:2021:9:2021:38 | Unary | r2021_9 | -| ir.cpp:2021:9:2021:38 | Unary | r2021_10 | -| ir.cpp:2021:13:2021:13 | StoreValue | r2021_20 | -| ir.cpp:2021:17:2021:17 | Address | &:r2021_23 | -| ir.cpp:2021:17:2021:17 | Address | &:r2021_23 | -| ir.cpp:2021:17:2021:17 | Arg(this) | this:r2021_23 | -| ir.cpp:2021:17:2021:17 | ChiPartial | partial:m2021_40 | -| ir.cpp:2021:17:2021:17 | ChiTotal | total:m2017_10 | -| ir.cpp:2021:17:2021:17 | SideEffect | m2017_10 | -| ir.cpp:2021:19:2021:19 | CallTarget | func:r2021_24 | -| ir.cpp:2021:19:2021:19 | ChiPartial | partial:m2021_36 | -| ir.cpp:2021:19:2021:19 | ChiTotal | total:m2021_30 | -| ir.cpp:2021:19:2021:19 | SideEffect | ~m2021_30 | -| ir.cpp:2021:19:2021:19 | Unary | r2021_35 | -| ir.cpp:2021:19:2021:39 | StoreValue | r2021_42 | -| ir.cpp:2021:21:2021:38 | Address | &:r2021_25 | -| ir.cpp:2021:21:2021:38 | Address | &:r2021_25 | -| ir.cpp:2021:21:2021:38 | Address | &:r2021_34 | -| ir.cpp:2021:21:2021:38 | Arg(0) | 0:r2021_34 | -| ir.cpp:2021:21:2021:38 | Arg(this) | this:r2021_25 | -| ir.cpp:2021:21:2021:38 | CallTarget | func:r2021_27 | -| ir.cpp:2021:21:2021:38 | ChiPartial | partial:m2021_29 | -| ir.cpp:2021:21:2021:38 | ChiPartial | partial:m2021_31 | -| ir.cpp:2021:21:2021:38 | ChiTotal | total:m2020_16 | -| ir.cpp:2021:21:2021:38 | ChiTotal | total:m2021_26 | -| ir.cpp:2021:21:2021:38 | SideEffect | ~m2020_16 | -| ir.cpp:2021:21:2021:38 | SideEffect | ~m2021_32 | -| ir.cpp:2021:21:2021:38 | Unary | r2021_25 | -| ir.cpp:2021:21:2021:38 | Unary | r2021_33 | +| ir.cpp:2021:5:2021:19 | ChiPartial | partial:m2021_35 | +| ir.cpp:2021:5:2021:19 | ChiTotal | total:m2021_17 | +| ir.cpp:2021:5:2021:19 | SideEffect | m2021_17 | +| ir.cpp:2021:6:2021:6 | Address | &:r2021_1 | +| ir.cpp:2021:6:2021:6 | Address | &:r2021_1 | +| ir.cpp:2021:6:2021:6 | Arg(this) | this:r2021_1 | +| ir.cpp:2021:6:2021:6 | ChiPartial | partial:m2021_16 | +| ir.cpp:2021:6:2021:6 | ChiTotal | total:m2020_20 | +| ir.cpp:2021:6:2021:6 | SideEffect | m2020_20 | +| ir.cpp:2021:8:2021:8 | CallTarget | func:r2021_2 | +| ir.cpp:2021:8:2021:8 | ChiPartial | partial:m2021_12 | +| ir.cpp:2021:8:2021:8 | ChiTotal | total:m2020_16 | +| ir.cpp:2021:8:2021:8 | SideEffect | ~m2020_16 | +| ir.cpp:2021:8:2021:8 | Unary | r2021_11 | +| ir.cpp:2021:8:2021:19 | Address | &:r2021_18 | +| ir.cpp:2021:8:2021:19 | Address | &:r2021_18 | +| ir.cpp:2021:8:2021:19 | Arg(this) | this:r2021_18 | +| ir.cpp:2021:10:2021:10 | Address | &:r2021_3 | +| ir.cpp:2021:10:2021:10 | Condition | r2021_4 | +| ir.cpp:2021:10:2021:10 | Load | m2017_6 | +| ir.cpp:2021:10:2021:18 | Address | &:r2021_7 | +| ir.cpp:2021:10:2021:18 | Address | &:r2021_10 | +| ir.cpp:2021:10:2021:18 | Address | &:r2021_39 | +| ir.cpp:2021:10:2021:18 | Address | &:r2021_42 | +| ir.cpp:2021:10:2021:18 | Arg(0) | 0:r2021_10 | +| ir.cpp:2021:10:2021:18 | Load | m2021_6 | +| ir.cpp:2021:10:2021:18 | Phi | from 11:m2021_40 | +| ir.cpp:2021:10:2021:18 | Phi | from 12:m2021_43 | +| ir.cpp:2021:10:2021:18 | SideEffect | ~m2021_13 | +| ir.cpp:2021:10:2021:18 | Unary | r2021_8 | +| ir.cpp:2021:10:2021:18 | Unary | r2021_9 | +| ir.cpp:2021:14:2021:14 | StoreValue | r2021_38 | +| ir.cpp:2021:18:2021:18 | StoreValue | r2021_41 | +| ir.cpp:2021:21:2021:21 | CallTarget | func:r2021_19 | +| ir.cpp:2021:21:2021:21 | ChiPartial | partial:m2021_31 | +| ir.cpp:2021:21:2021:21 | ChiTotal | total:m2021_25 | +| ir.cpp:2021:21:2021:21 | SideEffect | ~m2021_25 | +| ir.cpp:2021:21:2021:21 | Unary | r2021_30 | +| ir.cpp:2021:23:2021:40 | Address | &:r2021_20 | +| ir.cpp:2021:23:2021:40 | Address | &:r2021_20 | +| ir.cpp:2021:23:2021:40 | Address | &:r2021_29 | +| ir.cpp:2021:23:2021:40 | Arg(0) | 0:r2021_29 | +| ir.cpp:2021:23:2021:40 | Arg(this) | this:r2021_20 | +| ir.cpp:2021:23:2021:40 | CallTarget | func:r2021_22 | +| ir.cpp:2021:23:2021:40 | ChiPartial | partial:m2021_24 | +| ir.cpp:2021:23:2021:40 | ChiPartial | partial:m2021_26 | +| ir.cpp:2021:23:2021:40 | ChiTotal | total:m2021_13 | +| ir.cpp:2021:23:2021:40 | ChiTotal | total:m2021_21 | +| ir.cpp:2021:23:2021:40 | SideEffect | ~m2021_13 | +| ir.cpp:2021:23:2021:40 | SideEffect | ~m2021_27 | +| ir.cpp:2021:23:2021:40 | Unary | r2021_20 | +| ir.cpp:2021:23:2021:40 | Unary | r2021_28 | | perf-regression.cpp:6:3:6:5 | Address | &:r6_5 | | perf-regression.cpp:6:3:6:5 | Address | &:r6_5 | | perf-regression.cpp:6:3:6:5 | Address | &:r6_7 | diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index bd3d387c5bb..a6b527b95b6 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -10529,9 +10529,10 @@ ir.cpp: # 1999| r1999_5(int) = Load[#temp1999:9] : &:r1999_4, ~m? # 1999| r1999_6(glval) = VariableAddress[z] : # 1999| mu1999_7(int) = Store[z] : &:r1999_6, r1999_5 -# 2000| r2000_1(glval) = VariableAddress[a] : -# 2000| r2000_2(bool) = Load[a] : &:r2000_1, ~m? -# 2000| v2000_3(void) = ConditionalBranch : r2000_2 +# 2000| r2000_1(int) = Constant[7] : +# 2000| r2000_2(glval) = VariableAddress[a] : +# 2000| r2000_3(bool) = Load[a] : &:r2000_2, ~m? +# 2000| v2000_4(void) = ConditionalBranch : r2000_3 #-----| False -> Block 12 #-----| True -> Block 11 @@ -10548,26 +10549,24 @@ ir.cpp: #-----| Goto -> Block 7 # 2000| Block 10 -# 2000| r2000_4(glval) = VariableAddress[#temp2000:5] : -# 2000| r2000_5(glval) = Load[#temp2000:5] : &:r2000_4, ~m? +# 2000| r2000_5(glval) = VariableAddress[#temp2000:6] : +# 2000| r2000_6(glval) = Load[#temp2000:6] : &:r2000_5, ~m? +# 2000| mu2000_7(int) = Store[?] : &:r2000_6, r2000_1 # 2001| v2001_1(void) = NoOp : # 1996| v1996_12(void) = ReturnVoid : # 1996| v1996_13(void) = AliasedUse : ~m? # 1996| v1996_14(void) = ExitFunction : # 2000| Block 11 -# 2000| r2000_6(glval) = VariableAddress[x] : -# 2000| r2000_7(glval) = VariableAddress[#temp2000:5] : -# 2000| mu2000_8(glval) = Store[#temp2000:5] : &:r2000_7, r2000_6 +# 2000| r2000_8(glval) = VariableAddress[x] : +# 2000| r2000_9(glval) = VariableAddress[#temp2000:6] : +# 2000| mu2000_10(glval) = Store[#temp2000:6] : &:r2000_9, r2000_8 #-----| Goto -> Block 10 # 2000| Block 12 -# 2000| r2000_9(int) = Constant[7] : -# 2000| r2000_10(glval) = VariableAddress[y] : -# 2000| mu2000_11(int) = Store[y] : &:r2000_10, r2000_9 -# 2000| r2000_12(glval) = CopyValue : r2000_10 -# 2000| r2000_13(glval) = VariableAddress[#temp2000:5] : -# 2000| mu2000_14(glval) = Store[#temp2000:5] : &:r2000_13, r2000_12 +# 2000| r2000_11(glval) = VariableAddress[y] : +# 2000| r2000_12(glval) = VariableAddress[#temp2000:6] : +# 2000| mu2000_13(glval) = Store[#temp2000:6] : &:r2000_12, r2000_11 #-----| Goto -> Block 10 # 2006| void TernaryTestPodObj(bool, TernaryPodObj, TernaryPodObj, TernaryPodObj) @@ -10649,15 +10648,19 @@ ir.cpp: #-----| Goto -> Block 4 # 2009| Block 7 -# 2009| r2009_5(glval) = VariableAddress[#temp2009:9] : -# 2009| r2009_6(TernaryPodObj) = Load[#temp2009:9] : &:r2009_5, ~m? -# 2009| mu2009_7(TernaryPodObj) = Store[#temp2009:9] : &:r2009_1, r2009_6 -# 2009| r2009_8(TernaryPodObj) = Load[#temp2009:9] : &:r2009_1, ~m? -# 2009| r2009_9(glval) = VariableAddress[z] : -# 2009| mu2009_10(TernaryPodObj) = Store[z] : &:r2009_9, r2009_8 -# 2010| r2010_1(glval) = VariableAddress[a] : -# 2010| r2010_2(bool) = Load[a] : &:r2010_1, ~m? -# 2010| v2010_3(void) = ConditionalBranch : r2010_2 +# 2009| r2009_5(glval) = VariableAddress[#temp2009:9] : +# 2009| r2009_6(TernaryPodObj) = Load[#temp2009:9] : &:r2009_5, ~m? +# 2009| mu2009_7(TernaryPodObj) = Store[#temp2009:9] : &:r2009_1, r2009_6 +# 2009| r2009_8(TernaryPodObj) = Load[#temp2009:9] : &:r2009_1, ~m? +# 2009| r2009_9(glval) = VariableAddress[z] : +# 2009| mu2009_10(TernaryPodObj) = Store[z] : &:r2009_9, r2009_8 +# 2010| r2010_1(glval) = VariableAddress[#temp2010:23] : +# 2010| r2010_2(TernaryPodObj) = Constant[0] : +# 2010| mu2010_3(TernaryPodObj) = Store[#temp2010:23] : &:r2010_1, r2010_2 +# 2010| r2010_4(TernaryPodObj) = Load[#temp2010:23] : &:r2010_1, ~m? +# 2010| r2010_5(glval) = VariableAddress[a] : +# 2010| r2010_6(bool) = Load[a] : &:r2010_5, ~m? +# 2010| v2010_7(void) = ConditionalBranch : r2010_6 #-----| False -> Block 12 #-----| True -> Block 11 @@ -10680,32 +10683,29 @@ ir.cpp: #-----| Goto -> Block 7 # 2010| Block 10 -# 2010| r2010_4(glval) = VariableAddress[#temp2010:9] : -# 2010| r2010_5(TernaryPodObj) = Load[#temp2010:9] : &:r2010_4, ~m? -# 2010| r2010_6(glval) = VariableAddress[z] : -# 2010| mu2010_7(TernaryPodObj) = Store[z] : &:r2010_6, r2010_5 -# 2011| v2011_1(void) = NoOp : -# 2006| v2006_12(void) = ReturnVoid : -# 2006| v2006_13(void) = AliasedUse : ~m? -# 2006| v2006_14(void) = ExitFunction : +# 2010| r2010_8(glval) = VariableAddress[#temp2010:10] : +# 2010| r2010_9(TernaryPodObj) = Load[#temp2010:10] : &:r2010_8, ~m? +# 2010| r2010_10(glval) = VariableAddress[z] : +# 2010| mu2010_11(TernaryPodObj) = Store[z] : &:r2010_10, r2010_9 +# 2010| r2010_12(glval) = CopyValue : r2010_10 +# 2010| mu2010_13(TernaryPodObj) = Store[?] : &:r2010_12, r2010_4 +# 2011| v2011_1(void) = NoOp : +# 2006| v2006_12(void) = ReturnVoid : +# 2006| v2006_13(void) = AliasedUse : ~m? +# 2006| v2006_14(void) = ExitFunction : # 2010| Block 11 -# 2010| r2010_8(glval) = VariableAddress[x] : -# 2010| r2010_9(TernaryPodObj) = Load[x] : &:r2010_8, ~m? -# 2010| r2010_10(glval) = VariableAddress[#temp2010:9] : -# 2010| mu2010_11(TernaryPodObj) = Store[#temp2010:9] : &:r2010_10, r2010_9 +# 2010| r2010_14(glval) = VariableAddress[x] : +# 2010| r2010_15(TernaryPodObj) = Load[x] : &:r2010_14, ~m? +# 2010| r2010_16(glval) = VariableAddress[#temp2010:10] : +# 2010| mu2010_17(TernaryPodObj) = Store[#temp2010:10] : &:r2010_16, r2010_15 #-----| Goto -> Block 10 # 2010| Block 12 -# 2010| r2010_12(glval) = VariableAddress[#temp2010:21] : -# 2010| r2010_13(TernaryPodObj) = Constant[0] : -# 2010| mu2010_14(TernaryPodObj) = Store[#temp2010:21] : &:r2010_12, r2010_13 -# 2010| r2010_15(TernaryPodObj) = Load[#temp2010:21] : &:r2010_12, ~m? -# 2010| r2010_16(glval) = VariableAddress[y] : -# 2010| mu2010_17(TernaryPodObj) = Store[y] : &:r2010_16, r2010_15 -# 2010| r2010_18(TernaryPodObj) = CopyValue : r2010_15 -# 2010| r2010_19(glval) = VariableAddress[#temp2010:9] : -# 2010| mu2010_20(TernaryPodObj) = Store[#temp2010:9] : &:r2010_19, r2010_18 +# 2010| r2010_18(glval) = VariableAddress[y] : +# 2010| r2010_19(TernaryPodObj) = Load[y] : &:r2010_18, ~m? +# 2010| r2010_20(glval) = VariableAddress[#temp2010:10] : +# 2010| mu2010_21(TernaryPodObj) = Store[#temp2010:10] : &:r2010_20, r2010_19 #-----| Goto -> Block 10 # 2013| TernaryNonPodObj& TernaryNonPodObj::operator=(TernaryNonPodObj const&) @@ -10931,46 +10931,46 @@ ir.cpp: #-----| Goto -> Block 7 # 2021| Block 10 -# 2021| r2021_6(glval) = VariableAddress[#temp2021:9] : -# 2021| r2021_7(glval) = Load[#temp2021:9] : &:r2021_6, ~m? -# 2021| r2021_8(glval) = Convert : r2021_7 -# 2021| r2021_9(TernaryNonPodObj &) = CopyValue : r2021_8 -# 2021| r2021_10(TernaryNonPodObj &) = Call[operator=] : func:r2021_2, this:r2021_1, 0:r2021_9 -# 2021| mu2021_11(unknown) = ^CallSideEffect : ~m? -# 2021| v2021_12(void) = ^IndirectReadSideEffect[-1] : &:r2021_1, ~m? -# 2021| v2021_13(void) = ^BufferReadSideEffect[0] : &:r2021_9, ~m? -# 2021| mu2021_14(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_1 -# 2021| r2021_15(glval) = CopyValue : r2021_10 -# 2022| v2022_1(void) = NoOp : -# 2017| v2017_12(void) = ReturnVoid : -# 2017| v2017_13(void) = AliasedUse : ~m? -# 2017| v2017_14(void) = ExitFunction : +# 2021| r2021_6(glval) = VariableAddress[#temp2021:10] : +# 2021| r2021_7(glval) = Load[#temp2021:10] : &:r2021_6, ~m? +# 2021| r2021_8(glval) = Convert : r2021_7 +# 2021| r2021_9(TernaryNonPodObj &) = CopyValue : r2021_8 +# 2021| r2021_10(TernaryNonPodObj &) = Call[operator=] : func:r2021_2, this:r2021_1, 0:r2021_9 +# 2021| mu2021_11(unknown) = ^CallSideEffect : ~m? +# 2021| v2021_12(void) = ^IndirectReadSideEffect[-1] : &:r2021_1, ~m? +# 2021| v2021_13(void) = ^BufferReadSideEffect[0] : &:r2021_9, ~m? +# 2021| mu2021_14(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_1 +# 2021| r2021_15(glval) = CopyValue : r2021_10 +# 2021| r2021_16(glval) = FunctionAddress[operator=] : +# 2021| r2021_17(glval) = VariableAddress[#temp2021:23] : +# 2021| mu2021_18(TernaryNonPodObj) = Uninitialized[#temp2021:23] : &:r2021_17 +# 2021| r2021_19(glval) = FunctionAddress[TernaryNonPodObj] : +# 2021| v2021_20(void) = Call[TernaryNonPodObj] : func:r2021_19, this:r2021_17 +# 2021| mu2021_21(unknown) = ^CallSideEffect : ~m? +# 2021| mu2021_22(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_17 +# 2021| r2021_23(glval) = Convert : r2021_17 +# 2021| r2021_24(TernaryNonPodObj &) = CopyValue : r2021_23 +# 2021| r2021_25(TernaryNonPodObj &) = Call[operator=] : func:r2021_16, this:r2021_15, 0:r2021_24 +# 2021| mu2021_26(unknown) = ^CallSideEffect : ~m? +# 2021| v2021_27(void) = ^IndirectReadSideEffect[-1] : &:r2021_15, ~m? +# 2021| v2021_28(void) = ^BufferReadSideEffect[0] : &:r2021_24, ~m? +# 2021| mu2021_29(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_15 +# 2021| r2021_30(glval) = CopyValue : r2021_25 +# 2022| v2022_1(void) = NoOp : +# 2017| v2017_12(void) = ReturnVoid : +# 2017| v2017_13(void) = AliasedUse : ~m? +# 2017| v2017_14(void) = ExitFunction : # 2021| Block 11 -# 2021| r2021_16(glval) = VariableAddress[x] : -# 2021| r2021_17(glval) = VariableAddress[#temp2021:9] : -# 2021| mu2021_18(glval) = Store[#temp2021:9] : &:r2021_17, r2021_16 +# 2021| r2021_31(glval) = VariableAddress[x] : +# 2021| r2021_32(glval) = VariableAddress[#temp2021:10] : +# 2021| mu2021_33(glval) = Store[#temp2021:10] : &:r2021_32, r2021_31 #-----| Goto -> Block 10 # 2021| Block 12 -# 2021| r2021_19(glval) = VariableAddress[y] : -# 2021| r2021_20(glval) = FunctionAddress[operator=] : -# 2021| r2021_21(glval) = VariableAddress[#temp2021:21] : -# 2021| mu2021_22(TernaryNonPodObj) = Uninitialized[#temp2021:21] : &:r2021_21 -# 2021| r2021_23(glval) = FunctionAddress[TernaryNonPodObj] : -# 2021| v2021_24(void) = Call[TernaryNonPodObj] : func:r2021_23, this:r2021_21 -# 2021| mu2021_25(unknown) = ^CallSideEffect : ~m? -# 2021| mu2021_26(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_21 -# 2021| r2021_27(glval) = Convert : r2021_21 -# 2021| r2021_28(TernaryNonPodObj &) = CopyValue : r2021_27 -# 2021| r2021_29(TernaryNonPodObj &) = Call[operator=] : func:r2021_20, this:r2021_19, 0:r2021_28 -# 2021| mu2021_30(unknown) = ^CallSideEffect : ~m? -# 2021| v2021_31(void) = ^IndirectReadSideEffect[-1] : &:r2021_19, ~m? -# 2021| v2021_32(void) = ^BufferReadSideEffect[0] : &:r2021_28, ~m? -# 2021| mu2021_33(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_19 -# 2021| r2021_34(glval) = CopyValue : r2021_29 -# 2021| r2021_35(glval) = VariableAddress[#temp2021:9] : -# 2021| mu2021_36(glval) = Store[#temp2021:9] : &:r2021_35, r2021_34 +# 2021| r2021_34(glval) = VariableAddress[y] : +# 2021| r2021_35(glval) = VariableAddress[#temp2021:10] : +# 2021| mu2021_36(glval) = Store[#temp2021:10] : &:r2021_35, r2021_34 #-----| Goto -> Block 10 perf-regression.cpp: From 3bd4d34a4783e08c25bc01e2d8ae003b9817eb78 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 31 Jul 2023 09:48:03 +0200 Subject: [PATCH 30/32] Java: Remove superfluous generated models --- java/ql/lib/ext/generated/struts2.model.yml | 23 --------------------- 1 file changed, 23 deletions(-) diff --git a/java/ql/lib/ext/generated/struts2.model.yml b/java/ql/lib/ext/generated/struts2.model.yml index f157c44806e..74e1101a960 100644 --- a/java/ql/lib/ext/generated/struts2.model.yml +++ b/java/ql/lib/ext/generated/struts2.model.yml @@ -4849,15 +4849,6 @@ extensions: - ["org.apache.struts2", "StrutsException", true, "StrutsException", "(Throwable,Object)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"] - ["org.apache.struts2", "StrutsException", true, "StrutsException", "(Throwable,Object)", "", "Argument[1]", "Argument[this]", "taint", "df-generated"] - ["org.apache.struts2", "StrutsException", true, "toString", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"] - - ["org.demo.rest.example", "Order", true, "Order", "(String,String,int)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"] - - ["org.demo.rest.example", "Order", true, "Order", "(String,String,int)", "", "Argument[1]", "Argument[this]", "taint", "df-generated"] - - ["org.demo.rest.example", "Order", true, "getClientName", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"] - - ["org.demo.rest.example", "Order", true, "getId", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"] - - ["org.demo.rest.example", "Order", true, "setClientName", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"] - - ["org.demo.rest.example", "Order", true, "setId", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"] - - ["org.demo.rest.example", "Order", true, "toString", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"] - - ["org.demo.rest.example", "OrdersController", true, "create", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"] - - ["org.demo.rest.example", "OrdersController", true, "setId", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"] - addsTo: pack: codeql/java-all extensible: neutralModel @@ -6886,19 +6877,5 @@ extensions: - ["org.apache.struts2", "ServletActionContext", "setResponse", "(HttpServletResponse)", "summary", "df-generated"] - ["org.apache.struts2", "ServletActionContext", "setServletContext", "(ServletContext)", "summary", "df-generated"] - ["org.apache.struts2", "ServletCache", "clear", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "IndexController", "index", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "Order", "getAmount", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "Order", "setAmount", "(int)", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersController", "deleteConfirm", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersController", "destroy", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersController", "edit", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersController", "editNew", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersController", "index", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersController", "show", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersController", "update", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersService", "get", "(String)", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersService", "getAll", "()", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersService", "remove", "(String)", "summary", "df-generated"] - - ["org.demo.rest.example", "OrdersService", "save", "(Order)", "summary", "df-generated"] - ["org.w3c.dom", "Document", "getElementsByTagName", "(String)", "summary", "df-generated"] - ["org.w3c.dom", "Document", "getElementsByTagNameNS", "(String,String)", "summary", "df-generated"] From 12f2539d1d1878560b5c41e7403d873da8d59003 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:03:25 +0100 Subject: [PATCH 31/32] Swift: Use flowTo. --- .../library-tests/dataflow/flowsources/FlowSourcesInline.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql index 25b3b327a70..e4ea2e0e56e 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql +++ b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql @@ -38,7 +38,7 @@ module FlowSourcesTest implements TestSig { exists(DataFlow::Node sink | // this is not really what the "flowsources" test is about, but sometimes it's helpful to // have sinks and confirm that taint reaches obvious points in the flow source test code. - TestFlow::flow(_, sink) and + TestFlow::flowTo(sink) and location = sink.getLocation() and element = sink.toString() and tag = "tainted" and From f921076fca7ef5b57c9388cec7d878309c6c1b90 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:25:25 +0100 Subject: [PATCH 32/32] Swift: Autoformat. --- swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql b/swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql index 98d68d0a101..148676e1ac3 100644 --- a/swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql +++ b/swift/ql/src/experimental/Security/CWE-078/CommandInjection.ql @@ -19,4 +19,4 @@ import CommandInjectionFlow::PathGraph from CommandInjectionFlow::PathNode sourceNode, CommandInjectionFlow::PathNode sinkNode where CommandInjectionFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "This command depends on a $@.", - sourceNode.getNode(), "user-provided value" \ No newline at end of file + sourceNode.getNode(), "user-provided value"