diff --git a/MODULE.bazel b/MODULE.bazel index 7fb06f3074f..2b37719584c 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -30,7 +30,7 @@ bazel_dep(name = "rules_kotlin", version = "2.2.2-codeql.1") bazel_dep(name = "gazelle", version = "0.47.0") bazel_dep(name = "rules_dotnet", version = "0.21.5-codeql.1") bazel_dep(name = "googletest", version = "1.14.0.bcr.1") -bazel_dep(name = "rules_rust", version = "0.66.0") +bazel_dep(name = "rules_rust", version = "0.68.1.codeql.1") bazel_dep(name = "zstd", version = "1.5.5.bcr.1") bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True) @@ -43,7 +43,7 @@ RUST_EDITION = "2024" # a nightly toolchain is required to enable experimental_use_cc_common_link, which we require internally # we prefer to run the same version as internally, even if experimental_use_cc_common_link is not really # required in this repo -RUST_VERSION = "nightly/2025-08-01" +RUST_VERSION = "nightly/2026-01-22" rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") rust.toolchain( @@ -55,26 +55,26 @@ rust.toolchain( ], # generated by buildutils-internal/scripts/fill-rust-sha256s.py (internal repo) sha256s = { - "2025-08-01/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "9bbeaf5d3fc7247d31463a9083aa251c995cc50662c8219e7a2254d76a72a9a4", - "2025-08-01/rustc-nightly-x86_64-apple-darwin.tar.xz": "c9ea539a8eff0d5d162701f99f9e1aabe14dd0dfb420d62362817a5d09219de7", - "2025-08-01/rustc-nightly-aarch64-apple-darwin.tar.xz": "ae83feebbc39cfd982e4ecc8297731fe79c185173aee138467b334c5404b3773", - "2025-08-01/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "9f170c30d802a349be60cf52ec46260802093cb1013ad667fc0d528b7b10152f", - "2025-08-01/clippy-nightly-x86_64-unknown-linux-gnu.tar.xz": "9ae5f3cd8f557c4f6df522597c69d14398cf604cfaed2b83e767c4b77a7eaaf6", - "2025-08-01/clippy-nightly-x86_64-apple-darwin.tar.xz": "983cb9ee0b6b968188e04ab2d33743d54764b2681ce565e1b3f2b9135c696a3e", - "2025-08-01/clippy-nightly-aarch64-apple-darwin.tar.xz": "ed2219dbc49d088225e1b7c5c4390fa295066e071fddaa2714018f6bb39ddbf0", - "2025-08-01/clippy-nightly-x86_64-pc-windows-msvc.tar.xz": "911f40ab5cbdd686f40e00965271fe47c4805513a308ed01f30eafb25b448a50", - "2025-08-01/cargo-nightly-x86_64-unknown-linux-gnu.tar.xz": "106463c284e48e4904c717471eeec2be5cc83a9d2cae8d6e948b52438cad2e69", - "2025-08-01/cargo-nightly-x86_64-apple-darwin.tar.xz": "6ad35c40efc41a8c531ea43235058347b6902d98a9693bf0aed7fc16d5590cef", - "2025-08-01/cargo-nightly-aarch64-apple-darwin.tar.xz": "dd28c365e9d298abc3154c797720ad36a0058f131265c9978b4c8e4e37012c8a", - "2025-08-01/cargo-nightly-x86_64-pc-windows-msvc.tar.xz": "7b431286e12d6b3834b038f078389a00cac73f351e8c3152b2504a3c06420b3b", - "2025-08-01/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.xz": "e342e305d7927cc288d386983b2bc253cfad3776b113386e903d0b302648ef47", - "2025-08-01/llvm-tools-nightly-x86_64-apple-darwin.tar.xz": "e44dd3506524d85c37b3a54bcc91d01378fd2c590b2db5c5974d12f05c1b84d1", - "2025-08-01/llvm-tools-nightly-aarch64-apple-darwin.tar.xz": "0c1b5f46dd81be4a9227b10283a0fcaa39c14fea7e81aea6fd6d9887ff6cdc41", - "2025-08-01/llvm-tools-nightly-x86_64-pc-windows-msvc.tar.xz": "423e5fd11406adccbc31b8456ceb7375ce055cdf45e90d2c3babeb2d7f58383f", - "2025-08-01/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz": "3c0ceb46a252647a1d4c7116d9ccae684fa5e42aaf3296419febd2c962c3b41d", - "2025-08-01/rust-std-nightly-x86_64-apple-darwin.tar.xz": "3be416003cab10f767390a753d1d16ae4d26c7421c03c98992cf1943e5b0efe8", - "2025-08-01/rust-std-nightly-aarch64-apple-darwin.tar.xz": "4046ac0ef951cb056b5028a399124f60999fa37792eab69d008d8d7965f389b4", - "2025-08-01/rust-std-nightly-x86_64-pc-windows-msvc.tar.xz": "191ed9d8603c3a4fe5a7bbbc2feb72049078dae2df3d3b7d5dedf3abbf823e6e", + "2026-01-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "88db619323cc1321630d124efa51ed02fabc5e020f08cfa0eda2c0ac1afbe69a", + "2026-01-22/rustc-nightly-x86_64-apple-darwin.tar.xz": "08484da3fa38db56f93629aeabdc0ae9ff8ed9704c0792d35259cbc849b3f54c", + "2026-01-22/rustc-nightly-aarch64-apple-darwin.tar.xz": "a39c0b21b7058e364ea1bd43144e42e4bf1efade036b2e82455f2afce194ee81", + "2026-01-22/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "d00248ee9850dbb6932b2578e32ff74fc7c429854c1aa071066ca31b65385a3b", + "2026-01-22/clippy-nightly-x86_64-unknown-linux-gnu.tar.xz": "70656a0ce994ffff16d5a35a7b170a0acd41e9bb54a589c96ed45bf97b094a4d", + "2026-01-22/clippy-nightly-x86_64-apple-darwin.tar.xz": "fe242519fa961522734733009705aec3c2d9a20cc57291f2aa614e5e6262c88f", + "2026-01-22/clippy-nightly-aarch64-apple-darwin.tar.xz": "38bb226363ec97c9722edf966cd58774a683e19fd2ff2a6030094445d51e06f9", + "2026-01-22/clippy-nightly-x86_64-pc-windows-msvc.tar.xz": "6da9b4470beea67abfebf046f141eee0d2a8db7c7a9e4e2294478734fd477228", + "2026-01-22/cargo-nightly-x86_64-unknown-linux-gnu.tar.xz": "99004e9d10c43a01499642f53bb3184d41137a95d65bfb217098840a9e79e892", + "2026-01-22/cargo-nightly-x86_64-apple-darwin.tar.xz": "6e021394cf8d8400ac6cfdfcef24e4d74f988e91eb8028b36de3a64ce3502990", + "2026-01-22/cargo-nightly-aarch64-apple-darwin.tar.xz": "4b2494cb69ab64132cddbc411a38ea9f1105e54d6f986e43168d54f79510c673", + "2026-01-22/cargo-nightly-x86_64-pc-windows-msvc.tar.xz": "c36613cf57407212d10d37b76e49a60ff42336e953cdff9e177283f530a83fc1", + "2026-01-22/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.xz": "0b123c5027dbd833aae6845ffe9bd07d309bf798746a7176aadaea68fbcbd05d", + "2026-01-22/llvm-tools-nightly-x86_64-apple-darwin.tar.xz": "a47864491ad5619158c950ab7570fb6e487d5117338585c27334d45824b406d8", + "2026-01-22/llvm-tools-nightly-aarch64-apple-darwin.tar.xz": "db9bc826d6e2e7e914505d50157682e516ceb90357e83d77abddc32c2d962f41", + "2026-01-22/llvm-tools-nightly-x86_64-pc-windows-msvc.tar.xz": "ffaa406932b2fe62e01dad61cf4ed34860a5d2a6f9306ca340d79e630d930039", + "2026-01-22/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz": "e9c0d5e06e18a4b509391b3088f29293e310cdc8ccc865be8fa3f09733326925", + "2026-01-22/rust-std-nightly-x86_64-apple-darwin.tar.xz": "25d75995cee679a4828ca9fe48c5a31a67c3b0846018440ef912e5a6208f53f6", + "2026-01-22/rust-std-nightly-aarch64-apple-darwin.tar.xz": "e4132bf3f2eed4684c86756a02315bcf481c23e675e3e25630fc604c9cb4594c", + "2026-01-22/rust-std-nightly-x86_64-pc-windows-msvc.tar.xz": "961bb535ef95ae8a5fa4e224cb94aff190f155c45a9bcf7a53e184b024aa41b1", }, versions = [RUST_VERSION], ) diff --git a/actions/ql/lib/CHANGELOG.md b/actions/ql/lib/CHANGELOG.md index d2e85ddb6a2..1b41f2f2f5e 100644 --- a/actions/ql/lib/CHANGELOG.md +++ b/actions/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.28 + +No user-facing changes. + ## 0.4.27 ### Bug Fixes diff --git a/actions/ql/lib/change-notes/released/0.4.28.md b/actions/ql/lib/change-notes/released/0.4.28.md new file mode 100644 index 00000000000..af10bae2ab5 --- /dev/null +++ b/actions/ql/lib/change-notes/released/0.4.28.md @@ -0,0 +1,3 @@ +## 0.4.28 + +No user-facing changes. diff --git a/actions/ql/lib/codeql-pack.release.yml b/actions/ql/lib/codeql-pack.release.yml index 5e24b634389..ff6beb81526 100644 --- a/actions/ql/lib/codeql-pack.release.yml +++ b/actions/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.27 +lastReleaseVersion: 0.4.28 diff --git a/actions/ql/lib/qlpack.yml b/actions/ql/lib/qlpack.yml index d700f90710a..a9d5b7e61f6 100644 --- a/actions/ql/lib/qlpack.yml +++ b/actions/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/actions-all -version: 0.4.28-dev +version: 0.4.29-dev library: true warnOnImplicitThis: true dependencies: diff --git a/actions/ql/src/CHANGELOG.md b/actions/ql/src/CHANGELOG.md index ebf6b7214c9..c92b28841fa 100644 --- a/actions/ql/src/CHANGELOG.md +++ b/actions/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.20 + +No user-facing changes. + ## 0.6.19 No user-facing changes. diff --git a/actions/ql/src/change-notes/released/0.6.20.md b/actions/ql/src/change-notes/released/0.6.20.md new file mode 100644 index 00000000000..35c1118ff45 --- /dev/null +++ b/actions/ql/src/change-notes/released/0.6.20.md @@ -0,0 +1,3 @@ +## 0.6.20 + +No user-facing changes. diff --git a/actions/ql/src/codeql-pack.release.yml b/actions/ql/src/codeql-pack.release.yml index 2baec50a823..e30c5c64b1b 100644 --- a/actions/ql/src/codeql-pack.release.yml +++ b/actions/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.6.19 +lastReleaseVersion: 0.6.20 diff --git a/actions/ql/src/qlpack.yml b/actions/ql/src/qlpack.yml index 7c19f90be06..f4e731dc26d 100644 --- a/actions/ql/src/qlpack.yml +++ b/actions/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/actions-queries -version: 0.6.20-dev +version: 0.6.21-dev library: false warnOnImplicitThis: true groups: [actions, queries] diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md index 6f256c9499b..91f4b009b2b 100644 --- a/cpp/ql/lib/CHANGELOG.md +++ b/cpp/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 7.1.1 + +### Minor Analysis Improvements + +* Added remote flow source models for the `winhttp.h` windows header and the Azure SDK core library for C/C++. + ## 7.1.0 ### New Features diff --git a/cpp/ql/lib/change-notes/2026-02-03-windows-remote-flow-sources.md b/cpp/ql/lib/change-notes/2026-02-03-windows-remote-flow-sources.md deleted file mode 100644 index 0a884df065a..00000000000 --- a/cpp/ql/lib/change-notes/2026-02-03-windows-remote-flow-sources.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Added remote flow source models for the `winhttp.h` windows header and the Azure SDK core library for C/C++. \ No newline at end of file diff --git a/cpp/ql/lib/change-notes/2026-02-14-must-flow-fix.md b/cpp/ql/lib/change-notes/2026-02-14-must-flow-fix.md new file mode 100644 index 00000000000..fc838f51c06 --- /dev/null +++ b/cpp/ql/lib/change-notes/2026-02-14-must-flow-fix.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* The `allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion. diff --git a/cpp/ql/lib/change-notes/2026-02-14-must-flow.md b/cpp/ql/lib/change-notes/2026-02-14-must-flow.md new file mode 100644 index 00000000000..3d1afaa6344 --- /dev/null +++ b/cpp/ql/lib/change-notes/2026-02-14-must-flow.md @@ -0,0 +1,4 @@ +--- +category: breaking +--- +* `MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the `MustFlowConfiguration` class, the user should now implement a module with the `MustFlow::ConfigSig` signature, and instantiate the `MustFlow::Global` parameterized module with the implemented module. diff --git a/cpp/ql/lib/change-notes/released/7.1.1.md b/cpp/ql/lib/change-notes/released/7.1.1.md new file mode 100644 index 00000000000..16bba7ca508 --- /dev/null +++ b/cpp/ql/lib/change-notes/released/7.1.1.md @@ -0,0 +1,5 @@ +## 7.1.1 + +### Minor Analysis Improvements + +* Added remote flow source models for the `winhttp.h` windows header and the Azure SDK core library for C/C++. diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml index dcaaa76112a..8e970df6cae 100644 --- a/cpp/ql/lib/codeql-pack.release.yml +++ b/cpp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 7.1.0 +lastReleaseVersion: 7.1.1 diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index eeb5d0adf08..31ce003aadc 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 7.1.1-dev +version: 7.1.2-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll b/cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll index 7e98177f323..3dea144bbf6 100644 --- a/cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll +++ b/cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll @@ -34,6 +34,38 @@ private string getSingleLocationFilePath(@element e) { macroinvocations(e, _, loc, _) or preprocdirects(e, _, loc) + or + diagnostics(e, _, _, _, _, loc) + or + usings(e, _, loc, _) + or + static_asserts(e, _, _, loc, _) + or + derivations(e, _, _, _, loc) + or + frienddecls(e, _, _, loc) + or + comments(e, _, loc) + or + exprs(e, _, loc) + or + stmts(e, _, loc) + or + initialisers(e, _, _, loc) + or + attributes(e, _, _, _, loc) + or + attribute_args(e, _, _, _, loc) + or + namequalifiers(e, _, _, loc) + or + enumconstants(e, _, _, _, _, loc) + or + type_mentions(e, _, loc, _) + or + lambda_capture(e, _, _, _, _, _, loc) + or + concept_templates(e, _, loc) | result = getLocationFilePath(loc) ) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/MustFlow.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/MustFlow.qll index b085440f6bc..2b61190fb71 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/MustFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/MustFlow.qll @@ -8,81 +8,143 @@ private import cpp private import semmle.code.cpp.ir.IR /** - * A configuration of a data flow analysis that performs must-flow analysis. This is different - * from `DataFlow.qll` which performs may-flow analysis (i.e., it finds paths where the source _may_ - * flow to the sink). - * - * Like in `DataFlow.qll`, each use of the `MustFlow.qll` library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with a subclass whose - * characteristic predicate is a unique singleton string and override `isSource`, `isSink` (and - * `isAdditionalFlowStep` if additional steps are required). + * Provides an inter-procedural must-flow data flow analysis. */ -abstract class MustFlowConfiguration extends string { - bindingset[this] - MustFlowConfiguration() { any() } - +module MustFlow { /** - * Holds if `source` is a relevant data flow source. + * An input configuration of a data flow analysis that performs must-flow analysis. This is different + * from `DataFlow.qll` which performs may-flow analysis (i.e., it finds paths where the source _may_ + * flow to the sink). */ - abstract predicate isSource(Instruction source); + signature module ConfigSig { + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Instruction source); - /** - * Holds if `sink` is a relevant data flow sink. - */ - abstract predicate isSink(Operand sink); + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Operand sink); - /** - * Holds if data flow through `instr` is prohibited. - */ - predicate isBarrier(Instruction instr) { none() } + /** + * Holds if data flow through `instr` is prohibited. + */ + default predicate isBarrier(Instruction instr) { none() } - /** - * Holds if the additional flow step from `node1` to `node2` must be taken - * into account in the analysis. - */ - predicate isAdditionalFlowStep(Operand node1, Instruction node2) { none() } + /** + * Holds if the additional flow step from `node1` to `node2` must be taken + * into account in the analysis. + */ + default predicate isAdditionalFlowStep(Operand node1, Instruction node2) { none() } - /** Holds if this configuration allows flow from arguments to parameters. */ - predicate allowInterproceduralFlow() { any() } - - /** - * Holds if data must flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - final predicate hasFlowPath(MustFlowPathNode source, MustFlowPathSink sink) { - this.isSource(source.getInstruction()) and - source.getASuccessor*() = sink + /** Holds if this configuration allows flow from arguments to parameters. */ + default predicate allowInterproceduralFlow() { any() } } -} -/** Holds if `node` flows from a source. */ -pragma[nomagic] -private predicate flowsFromSource(Instruction node, MustFlowConfiguration config) { - not config.isBarrier(node) and - ( - config.isSource(node) - or - exists(Instruction mid | - step(mid, node, config) and - flowsFromSource(mid, pragma[only_bind_into](config)) - ) - ) -} + /** + * Constructs a global must-flow computation. + */ + module Global { + import Config -/** Holds if `node` flows to a sink. */ -pragma[nomagic] -private predicate flowsToSink(Instruction node, MustFlowConfiguration config) { - flowsFromSource(node, pragma[only_bind_into](config)) and - ( - config.isSink(node.getAUse()) - or - exists(Instruction mid | - step(node, mid, config) and - flowsToSink(mid, pragma[only_bind_into](config)) - ) - ) + /** + * Holds if data must flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate flowPath(PathNode source, PathSink sink) { + isSource(source.getInstruction()) and + source.getASuccessor*() = sink + } + + /** Holds if `node` flows from a source. */ + pragma[nomagic] + private predicate flowsFromSource(Instruction node) { + not isBarrier(node) and + ( + isSource(node) + or + exists(Instruction mid | + step(mid, node) and + flowsFromSource(mid) + ) + ) + } + + /** Holds if `node` flows to a sink. */ + pragma[nomagic] + private predicate flowsToSink(Instruction node) { + flowsFromSource(node) and + ( + isSink(node.getAUse()) + or + exists(Instruction mid | + step(node, mid) and + flowsToSink(mid) + ) + ) + } + + /** Holds if `nodeFrom` flows to `nodeTo`. */ + private predicate step(Instruction nodeFrom, Instruction nodeTo) { + Cached::localStep(nodeFrom, nodeTo) + or + allowInterproceduralFlow() and + Cached::flowThroughCallable(nodeFrom, nodeTo) + or + isAdditionalFlowStep(nodeFrom.getAUse(), nodeTo) + } + + private newtype TLocalPathNode = + MkLocalPathNode(Instruction n) { + flowsToSink(n) and + ( + isSource(n) + or + exists(PathNode mid | step(mid.getInstruction(), n)) + ) + } + + /** A `Node` that is in a path from a source to a sink. */ + class PathNode extends TLocalPathNode { + Instruction n; + + PathNode() { this = MkLocalPathNode(n) } + + /** Gets the underlying node. */ + Instruction getInstruction() { result = n } + + /** Gets a textual representation of this node. */ + string toString() { result = n.getAst().toString() } + + /** Gets the location of this element. */ + Location getLocation() { result = n.getLocation() } + + /** Gets a successor node, if any. */ + PathNode getASuccessor() { step(this.getInstruction(), result.getInstruction()) } + } + + private class PathSink extends PathNode { + PathSink() { isSink(this.getInstruction().getAUse()) } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PathGraph { + private predicate reach(PathNode n) { n instanceof PathSink or reach(n.getASuccessor()) } + + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + reach(n) and key = "semmle.label" and val = n.toString() + } + } + } } cached @@ -102,7 +164,7 @@ private module Cached { not f.isVirtual() and call.getPositionalArgument(n) = instr and f = call.getStaticCallTarget() and - getEnclosingNonVirtualFunctionInitializeParameter(init, f) and + isEnclosingNonVirtualFunctionInitializeParameter(init, f) and init.getParameter().getIndex() = pragma[only_bind_into](pragma[only_bind_out](n)) } @@ -111,7 +173,7 @@ private module Cached { * corresponding initialization instruction that receives the value of `instr` in `f`. */ pragma[noinline] - private predicate getPositionalArgumentInitParam( + private predicate isPositionalArgumentInitParam( CallInstruction call, Instruction instr, InitializeParameterInstruction init, Function f ) { exists(int n | @@ -126,18 +188,18 @@ private module Cached { * `instr` in `f`. */ pragma[noinline] - private predicate getThisArgumentInitParam( + private predicate isThisArgumentInitParam( CallInstruction call, Instruction instr, InitializeParameterInstruction init, Function f ) { not f.isVirtual() and call.getStaticCallTarget() = f and - getEnclosingNonVirtualFunctionInitializeParameter(init, f) and + isEnclosingNonVirtualFunctionInitializeParameter(init, f) and call.getThisArgument() = instr and init.getIRVariable() instanceof IRThisVariable } /** Holds if `f` is the enclosing non-virtual function of `init`. */ - private predicate getEnclosingNonVirtualFunctionInitializeParameter( + private predicate isEnclosingNonVirtualFunctionInitializeParameter( InitializeParameterInstruction init, Function f ) { not f.isVirtual() and @@ -145,7 +207,7 @@ private module Cached { } /** Holds if `f` is the enclosing non-virtual function of `init`. */ - private predicate getEnclosingNonVirtualFunctionInitializeIndirection( + private predicate isEnclosingNonVirtualFunctionInitializeIndirection( InitializeIndirectionInstruction init, Function f ) { not f.isVirtual() and @@ -153,15 +215,16 @@ private module Cached { } /** - * Holds if `instr` is an argument (or argument indirection) to a call, and - * `succ` is the corresponding initialization instruction in the call target. + * Holds if `argument` is an argument (or argument indirection) to a call, and + * `parameter` is the corresponding initialization instruction in the call target. */ - private predicate flowThroughCallable(Instruction argument, Instruction parameter) { + cached + predicate flowThroughCallable(Instruction argument, Instruction parameter) { // Flow from an argument to a parameter exists(CallInstruction call, InitializeParameterInstruction init | init = parameter | - getPositionalArgumentInitParam(call, argument, init, call.getStaticCallTarget()) + isPositionalArgumentInitParam(call, argument, init, call.getStaticCallTarget()) or - getThisArgumentInitParam(call, argument, init, call.getStaticCallTarget()) + isThisArgumentInitParam(call, argument, init, call.getStaticCallTarget()) ) or // Flow from argument indirection to parameter indirection @@ -170,7 +233,7 @@ private module Cached { | init = parameter and read.getPrimaryInstruction() = call and - getEnclosingNonVirtualFunctionInitializeIndirection(init, call.getStaticCallTarget()) + isEnclosingNonVirtualFunctionInitializeIndirection(init, call.getStaticCallTarget()) | exists(int n | read.getSideEffectOperand().getAnyDef() = argument and @@ -205,92 +268,10 @@ private module Cached { } cached - predicate step(Instruction nodeFrom, Instruction nodeTo) { + predicate localStep(Instruction nodeFrom, Instruction nodeTo) { exists(Operand mid | instructionToOperandStep(nodeFrom, mid) and operandToInstructionStep(mid, nodeTo) ) - or - flowThroughCallable(nodeFrom, nodeTo) - } -} - -/** - * Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this - * predicate ensures that joins go from `n` to the result instead of the other - * way around. - */ -pragma[inline] -private IRFunction getEnclosingCallable(Instruction n) { - pragma[only_bind_into](result) = pragma[only_bind_out](n).getEnclosingIRFunction() -} - -/** Holds if `nodeFrom` flows to `nodeTo`. */ -private predicate step(Instruction nodeFrom, Instruction nodeTo, MustFlowConfiguration config) { - exists(config) and - Cached::step(pragma[only_bind_into](nodeFrom), pragma[only_bind_into](nodeTo)) and - ( - config.allowInterproceduralFlow() - or - getEnclosingCallable(nodeFrom) = getEnclosingCallable(nodeTo) - ) - or - config.isAdditionalFlowStep(nodeFrom.getAUse(), nodeTo) -} - -private newtype TLocalPathNode = - MkLocalPathNode(Instruction n, MustFlowConfiguration config) { - flowsToSink(n, config) and - ( - config.isSource(n) - or - exists(MustFlowPathNode mid | step(mid.getInstruction(), n, config)) - ) - } - -/** A `Node` that is in a path from a source to a sink. */ -class MustFlowPathNode extends TLocalPathNode { - Instruction n; - - MustFlowPathNode() { this = MkLocalPathNode(n, _) } - - /** Gets the underlying node. */ - Instruction getInstruction() { result = n } - - /** Gets a textual representation of this node. */ - string toString() { result = n.getAst().toString() } - - /** Gets the location of this element. */ - Location getLocation() { result = n.getLocation() } - - /** Gets a successor node, if any. */ - MustFlowPathNode getASuccessor() { - step(this.getInstruction(), result.getInstruction(), this.getConfiguration()) - } - - /** Gets the associated configuration. */ - MustFlowConfiguration getConfiguration() { this = MkLocalPathNode(_, result) } -} - -private class MustFlowPathSink extends MustFlowPathNode { - MustFlowPathSink() { this.getConfiguration().isSink(this.getInstruction().getAUse()) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - private predicate reach(MustFlowPathNode n) { - n instanceof MustFlowPathSink or reach(n.getASuccessor()) - } - - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(MustFlowPathNode a, MustFlowPathNode b) { - a.getASuccessor() = b and reach(b) - } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(MustFlowPathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() } } diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeAnalysisUtils.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeAnalysisUtils.qll index 2423a3a71a0..03dbc56dc99 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeAnalysisUtils.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeAnalysisUtils.qll @@ -404,7 +404,7 @@ predicate cmpWithLinearBound( * For example, if `t` is a signed 32-bit type then holds if `lb` is * `-2^31` and `ub` is `2^31 - 1`. */ -private predicate typeBounds(ArithmeticType t, float lb, float ub) { +private predicate typeBounds0(ArithmeticType t, float lb, float ub) { exists(IntegralType integralType, float limit | integralType = t and limit = 2.pow(8 * integralType.getSize()) | @@ -423,6 +423,42 @@ private predicate typeBounds(ArithmeticType t, float lb, float ub) { t instanceof FloatingPointType and lb = -(1.0 / 0.0) and ub = 1.0 / 0.0 } +/** + * Gets the underlying type for an enumeration `e`. + * + * If the enumeration does not have an explicit type we approximate it using + * the following rules: + * - The result type is always `signed`, and + * - if the largest value fits in an `int` the result is `int`. Otherwise, the + * result is `long`. + */ +private IntegralType getUnderlyingTypeForEnum(Enum e) { + result = e.getExplicitUnderlyingType() + or + not e.hasExplicitUnderlyingType() and + result.isSigned() and + exists(IntType intType | + if max(e.getAnEnumConstant().getValue().toFloat()) >= 2.pow(8 * intType.getSize() - 1) + then result instanceof LongType + else result = intType + ) +} + +/** + * Holds if `lb` and `ub` are the lower and upper bounds of the unspecified + * type `t`. + * + * For example, if `t` is a signed 32-bit type then holds if `lb` is + * `-2^31` and `ub` is `2^31 - 1`. + * + * Unlike `typeBounds0`, this predicate also handles `Enum` types. + */ +private predicate typeBounds(Type t, float lb, float ub) { + typeBounds0(t, lb, ub) + or + typeBounds0(getUnderlyingTypeForEnum(t), lb, ub) +} + private Type stripReference(Type t) { if t instanceof ReferenceType then result = t.(ReferenceType).getBaseType() else result = t } diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index c3c3c2dd3e7..90f6a827255 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -512,8 +512,8 @@ private module BoundsEstimate { */ float getBoundsLimit() { // This limit is arbitrary, but low enough that it prevents timeouts on - // specific observed customer databases (and the in the tests). - result = 2.0.pow(40) + // specific observed customer databases (and in the tests). + result = 2.0.pow(29) } /** Gets the maximum number of bounds possible for `t` when widening is used. */ diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md index 61792c6a700..640b66a910d 100644 --- a/cpp/ql/src/CHANGELOG.md +++ b/cpp/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.5.11 + +No user-facing changes. + ## 1.5.10 No user-facing changes. diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql index b8788910332..efd136bcd2d 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql @@ -16,17 +16,15 @@ import cpp import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.dataflow.MustFlow -import PathGraph +import ReturnStackAllocatedMemory::PathGraph /** Holds if `f` has a name that we interpret as evidence of intentionally returning the value of the stack pointer. */ predicate intentionallyReturnsStackPointer(Function f) { f.getName().toLowerCase().matches(["%stack%", "%sp%"]) } -class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration { - ReturnStackAllocatedMemoryConfig() { this = "ReturnStackAllocatedMemoryConfig" } - - override predicate isSource(Instruction source) { +module ReturnStackAllocatedMemoryConfig implements MustFlow::ConfigSig { + predicate isSource(Instruction source) { exists(Function func | // Rule out FPs caused by extraction errors. not func.hasErrors() and @@ -50,7 +48,7 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration { ) } - override predicate isSink(Operand sink) { + predicate isSink(Operand sink) { // Holds if `sink` is a node that represents the `StoreInstruction` that is subsequently used in // a `ReturnValueInstruction`. // We use the `StoreInstruction` instead of the instruction that defines the @@ -72,7 +70,7 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration { // int* px = id(&x); // } // ``` - override predicate allowInterproceduralFlow() { none() } + predicate allowInterproceduralFlow() { none() } /** * This configuration intentionally conflates addresses of fields and their object, and pointer offsets @@ -87,20 +85,22 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration { * } * ``` */ - override predicate isAdditionalFlowStep(Operand node1, Instruction node2) { + predicate isAdditionalFlowStep(Operand node1, Instruction node2) { node2.(FieldAddressInstruction).getObjectAddressOperand() = node1 or node2.(PointerOffsetInstruction).getLeftOperand() = node1 } - override predicate isBarrier(Instruction n) { n.getResultType() instanceof ErroneousType } + predicate isBarrier(Instruction n) { n.getResultType() instanceof ErroneousType } } +module ReturnStackAllocatedMemory = MustFlow::Global; + from - MustFlowPathNode source, MustFlowPathNode sink, Instruction instr, - ReturnStackAllocatedMemoryConfig conf + ReturnStackAllocatedMemory::PathNode source, ReturnStackAllocatedMemory::PathNode sink, + Instruction instr where - conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and + ReturnStackAllocatedMemory::flowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and source.getInstruction() = instr select sink.getInstruction(), source, sink, "May return stack-allocated memory from $@.", instr.getAst(), instr.getAst().toString() diff --git a/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql b/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql index 763a142f1b9..1697ad31810 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql @@ -15,7 +15,7 @@ import cpp import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.dataflow.MustFlow -import PathGraph +import UninitializedLocal::PathGraph /** * Auxiliary predicate: Types that don't require initialization @@ -70,25 +70,26 @@ predicate isSinkImpl(Instruction sink, VariableAccess va) { ) } -class MustFlow extends MustFlowConfiguration { - MustFlow() { this = "MustFlow" } - - override predicate isSource(Instruction source) { +module UninitializedLocalConfig implements MustFlow::ConfigSig { + predicate isSource(Instruction source) { source instanceof UninitializedInstruction and exists(Type t | t = source.getResultType() | not allocatedType(t)) } - override predicate isSink(Operand sink) { isSinkImpl(sink.getDef(), _) } + predicate isSink(Operand sink) { isSinkImpl(sink.getDef(), _) } - override predicate allowInterproceduralFlow() { none() } + predicate allowInterproceduralFlow() { none() } - override predicate isBarrier(Instruction instr) { instr instanceof ChiInstruction } + predicate isBarrier(Instruction instr) { instr instanceof ChiInstruction } } +module UninitializedLocal = MustFlow::Global; + from - VariableAccess va, LocalVariable v, MustFlow conf, MustFlowPathNode source, MustFlowPathNode sink + VariableAccess va, LocalVariable v, UninitializedLocal::PathNode source, + UninitializedLocal::PathNode sink where - conf.hasFlowPath(source, sink) and + UninitializedLocal::flowPath(source, sink) and isSinkImpl(sink.getInstruction(), va) and v = va.getTarget() select va, source, sink, "The variable $@ may not be initialized at this access.", v, v.getName() diff --git a/cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql b/cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql index bb62cfc1755..63b56d470e2 100644 --- a/cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql +++ b/cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql @@ -17,16 +17,16 @@ import cpp import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.dataflow.MustFlow -import PathGraph +import UnsafeUseOfThis::PathGraph -class UnsafeUseOfThisConfig extends MustFlowConfiguration { - UnsafeUseOfThisConfig() { this = "UnsafeUseOfThisConfig" } +module UnsafeUseOfThisConfig implements MustFlow::ConfigSig { + predicate isSource(Instruction source) { isSource(source, _, _) } - override predicate isSource(Instruction source) { isSource(source, _, _) } - - override predicate isSink(Operand sink) { isSink(sink, _) } + predicate isSink(Operand sink) { isSink(sink, _) } } +module UnsafeUseOfThis = MustFlow::Global; + /** Holds if `sink` is a `this` pointer used by the call instruction `call`. */ predicate isSink(Operand sink, CallInstruction call) { exists(PureVirtualFunction func | @@ -66,19 +66,17 @@ predicate isSource(InitializeParameterInstruction source, string msg, Class c) { * - `msg` is a string describing whether `source` is from a constructor or destructor. */ predicate flows( - MustFlowPathNode source, string msg, Class sourceClass, MustFlowPathNode sink, + UnsafeUseOfThis::PathNode source, string msg, Class sourceClass, UnsafeUseOfThis::PathNode sink, CallInstruction call ) { - exists(UnsafeUseOfThisConfig conf | - conf.hasFlowPath(source, sink) and - isSource(source.getInstruction(), msg, sourceClass) and - isSink(sink.getInstruction().getAUse(), call) - ) + UnsafeUseOfThis::flowPath(source, sink) and + isSource(source.getInstruction(), msg, sourceClass) and + isSink(sink.getInstruction().getAUse(), call) } from - MustFlowPathNode source, MustFlowPathNode sink, CallInstruction call, string msg, - Class sourceClass + UnsafeUseOfThis::PathNode source, UnsafeUseOfThis::PathNode sink, CallInstruction call, + string msg, Class sourceClass where flows(source, msg, sourceClass, sink, call) and // Only raise an alert if there is no override of the pure virtual function in any base class. diff --git a/cpp/ql/src/change-notes/released/1.5.11.md b/cpp/ql/src/change-notes/released/1.5.11.md new file mode 100644 index 00000000000..5f42fc9133d --- /dev/null +++ b/cpp/ql/src/change-notes/released/1.5.11.md @@ -0,0 +1,3 @@ +## 1.5.11 + +No user-facing changes. diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml index fda54b31bff..7e8e8103d99 100644 --- a/cpp/ql/src/codeql-pack.release.yml +++ b/cpp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.5.10 +lastReleaseVersion: 1.5.11 diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index b374fb51f75..d8620439fe6 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 1.5.11-dev +version: 1.5.12-dev groups: - cpp - queries diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index 0c520190c8b..6bb1f192e1d 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -1025,6 +1025,7 @@ | test.c:970:12:970:12 | y | 256 | | test.c:971:9:971:9 | x | 2147483647 | | test.c:972:9:972:9 | y | 256 | +| test.c:985:7:985:7 | e | -2147483648 | | test.cpp:10:7:10:7 | b | -2147483648 | | test.cpp:11:5:11:5 | x | -2147483648 | | test.cpp:13:10:13:10 | x | -2147483648 | @@ -1093,3 +1094,64 @@ | test.cpp:122:4:122:4 | n | 0 | | test.cpp:122:8:122:8 | n | 0 | | test.cpp:122:12:122:12 | n | 1 | +| test_nr_of_bounds.cpp:40:5:40:20 | x | 0 | +| test_nr_of_bounds.cpp:40:5:40:20 | x | 0 | +| test_nr_of_bounds.cpp:41:5:41:20 | x | 0 | +| test_nr_of_bounds.cpp:41:5:41:20 | x | 0 | +| test_nr_of_bounds.cpp:42:5:42:20 | x | 0 | +| test_nr_of_bounds.cpp:42:5:42:20 | x | 0 | +| test_nr_of_bounds.cpp:43:5:43:20 | x | 0 | +| test_nr_of_bounds.cpp:43:5:43:20 | x | 0 | +| test_nr_of_bounds.cpp:44:5:44:20 | x | 0 | +| test_nr_of_bounds.cpp:44:5:44:20 | x | 0 | +| test_nr_of_bounds.cpp:45:5:45:20 | x | 0 | +| test_nr_of_bounds.cpp:45:5:45:20 | x | 0 | +| test_nr_of_bounds.cpp:46:5:46:20 | x | 0 | +| test_nr_of_bounds.cpp:46:5:46:20 | x | 0 | +| test_nr_of_bounds.cpp:47:5:47:20 | x | 0 | +| test_nr_of_bounds.cpp:47:5:47:20 | x | 0 | +| test_nr_of_bounds.cpp:48:5:48:20 | x | 0 | +| test_nr_of_bounds.cpp:48:5:48:20 | x | 0 | +| test_nr_of_bounds.cpp:49:5:49:20 | x | 0 | +| test_nr_of_bounds.cpp:49:5:49:20 | x | 0 | +| test_nr_of_bounds.cpp:50:5:50:20 | x | 0 | +| test_nr_of_bounds.cpp:50:5:50:20 | x | 0 | +| test_nr_of_bounds.cpp:51:5:51:20 | x | 0 | +| test_nr_of_bounds.cpp:51:5:51:20 | x | 0 | +| test_nr_of_bounds.cpp:52:5:52:20 | x | 0 | +| test_nr_of_bounds.cpp:52:5:52:20 | x | 0 | +| test_nr_of_bounds.cpp:53:5:53:20 | x | 0 | +| test_nr_of_bounds.cpp:53:5:53:20 | x | 0 | +| test_nr_of_bounds.cpp:54:5:54:20 | x | 0 | +| test_nr_of_bounds.cpp:54:5:54:20 | x | 0 | +| test_nr_of_bounds.cpp:55:5:55:20 | x | 0 | +| test_nr_of_bounds.cpp:55:5:55:20 | x | 0 | +| test_nr_of_bounds.cpp:56:5:56:20 | x | 0 | +| test_nr_of_bounds.cpp:56:5:56:20 | x | 0 | +| test_nr_of_bounds.cpp:57:5:57:20 | x | 0 | +| test_nr_of_bounds.cpp:57:5:57:20 | x | 0 | +| test_nr_of_bounds.cpp:58:5:58:20 | x | 0 | +| test_nr_of_bounds.cpp:58:5:58:20 | x | 0 | +| test_nr_of_bounds.cpp:59:5:59:20 | x | 0 | +| test_nr_of_bounds.cpp:59:5:59:20 | x | 0 | +| test_nr_of_bounds.cpp:60:5:60:20 | x | 0 | +| test_nr_of_bounds.cpp:60:5:60:20 | x | 0 | +| test_nr_of_bounds.cpp:61:5:61:20 | x | 0 | +| test_nr_of_bounds.cpp:61:5:61:20 | x | 0 | +| test_nr_of_bounds.cpp:62:5:62:20 | x | 0 | +| test_nr_of_bounds.cpp:62:5:62:20 | x | 0 | +| test_nr_of_bounds.cpp:63:5:63:20 | x | 0 | +| test_nr_of_bounds.cpp:63:5:63:20 | x | 0 | +| test_nr_of_bounds.cpp:64:5:64:20 | x | 0 | +| test_nr_of_bounds.cpp:64:5:64:20 | x | 0 | +| test_nr_of_bounds.cpp:65:5:65:21 | x | 0 | +| test_nr_of_bounds.cpp:65:5:65:21 | x | 0 | +| test_nr_of_bounds.cpp:66:5:66:21 | x | 0 | +| test_nr_of_bounds.cpp:66:5:66:21 | x | 0 | +| test_nr_of_bounds.cpp:67:5:67:21 | x | 0 | +| test_nr_of_bounds.cpp:67:5:67:21 | x | 0 | +| test_nr_of_bounds.cpp:68:5:68:21 | x | 0 | +| test_nr_of_bounds.cpp:68:5:68:21 | x | 0 | +| test_nr_of_bounds.cpp:69:5:69:21 | x | 0 | +| test_nr_of_bounds.cpp:69:5:69:21 | x | 0 | +| test_nr_of_bounds.cpp:72:12:72:12 | x | 0 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/nrOfBounds.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/nrOfBounds.expected index 7d583e47f5b..b46aebbbf64 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/nrOfBounds.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/nrOfBounds.expected @@ -4546,6 +4546,13 @@ estimateNrOfBounds | test.c:970:18:970:20 | 512 | 1.0 | | test.c:971:9:971:9 | x | 1.0 | | test.c:972:9:972:9 | y | 1.0 | +| test.c:977:9:977:11 | 1 | 1.0 | +| test.c:978:9:978:11 | 2 | 1.0 | +| test.c:979:9:979:11 | 4 | 1.0 | +| test.c:980:9:980:11 | 8 | 1.0 | +| test.c:981:9:981:12 | 16 | 1.0 | +| test.c:985:7:985:7 | (int)... | 1.0 | +| test.c:985:7:985:7 | e | 1.0 | | test.cpp:9:11:9:12 | - ... | 1.0 | | test.cpp:9:12:9:12 | 1 | 1.0 | | test.cpp:10:7:10:7 | (bool)... | 1.0 | @@ -4721,3 +4728,394 @@ estimateNrOfBounds | test.cpp:122:4:122:4 | n | 8.0 | | test.cpp:122:8:122:8 | n | 8.0 | | test.cpp:122:12:122:12 | n | 8.0 | +| test_nr_of_bounds.cpp:2:9:2:11 | 1 | 1.0 | +| test_nr_of_bounds.cpp:3:9:3:11 | 2 | 1.0 | +| test_nr_of_bounds.cpp:4:9:4:11 | 4 | 1.0 | +| test_nr_of_bounds.cpp:5:9:5:11 | 8 | 1.0 | +| test_nr_of_bounds.cpp:6:9:6:12 | 16 | 1.0 | +| test_nr_of_bounds.cpp:7:9:7:12 | 32 | 1.0 | +| test_nr_of_bounds.cpp:8:9:8:12 | 64 | 1.0 | +| test_nr_of_bounds.cpp:9:9:9:12 | 128 | 1.0 | +| test_nr_of_bounds.cpp:10:9:10:13 | 256 | 1.0 | +| test_nr_of_bounds.cpp:11:9:11:13 | 512 | 1.0 | +| test_nr_of_bounds.cpp:12:9:12:13 | 1024 | 1.0 | +| test_nr_of_bounds.cpp:13:9:13:13 | 2048 | 1.0 | +| test_nr_of_bounds.cpp:14:9:14:14 | 4096 | 1.0 | +| test_nr_of_bounds.cpp:15:9:15:14 | 8192 | 1.0 | +| test_nr_of_bounds.cpp:16:9:16:14 | 16384 | 1.0 | +| test_nr_of_bounds.cpp:17:9:17:14 | 32768 | 1.0 | +| test_nr_of_bounds.cpp:18:9:18:15 | 65536 | 1.0 | +| test_nr_of_bounds.cpp:19:9:19:15 | 131072 | 1.0 | +| test_nr_of_bounds.cpp:20:9:20:15 | 262144 | 1.0 | +| test_nr_of_bounds.cpp:21:9:21:15 | 524288 | 1.0 | +| test_nr_of_bounds.cpp:22:9:22:16 | 1048576 | 1.0 | +| test_nr_of_bounds.cpp:23:9:23:16 | 2097152 | 1.0 | +| test_nr_of_bounds.cpp:24:9:24:16 | 4194304 | 1.0 | +| test_nr_of_bounds.cpp:25:9:25:16 | 8388608 | 1.0 | +| test_nr_of_bounds.cpp:26:9:26:17 | 16777216 | 1.0 | +| test_nr_of_bounds.cpp:27:10:27:18 | 33554432 | 1.0 | +| test_nr_of_bounds.cpp:28:10:28:18 | 67108864 | 1.0 | +| test_nr_of_bounds.cpp:29:10:29:18 | 134217728 | 1.0 | +| test_nr_of_bounds.cpp:30:10:30:19 | 268435456 | 1.0 | +| test_nr_of_bounds.cpp:31:10:31:19 | 536870912 | 1.0 | +| test_nr_of_bounds.cpp:40:5:40:19 | ... & ... | 1.0 | +| test_nr_of_bounds.cpp:40:5:40:19 | ... -= ... | 1.0 | +| test_nr_of_bounds.cpp:40:5:40:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:40:5:40:20 | (...) | 1.0 | +| test_nr_of_bounds.cpp:40:5:40:20 | x | 1.0 | +| test_nr_of_bounds.cpp:40:5:40:20 | x | 1.0 | +| test_nr_of_bounds.cpp:40:19:40:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:40:19:40:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:40:19:40:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:40:19:40:19 | A | 1.0 | +| test_nr_of_bounds.cpp:40:19:40:19 | A | 1.0 | +| test_nr_of_bounds.cpp:40:19:40:19 | A | 1.0 | +| test_nr_of_bounds.cpp:41:5:41:19 | ... & ... | 2.0 | +| test_nr_of_bounds.cpp:41:5:41:19 | ... -= ... | 2.0 | +| test_nr_of_bounds.cpp:41:5:41:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:41:5:41:20 | (...) | 2.0 | +| test_nr_of_bounds.cpp:41:5:41:20 | x | 2.0 | +| test_nr_of_bounds.cpp:41:5:41:20 | x | 2.0 | +| test_nr_of_bounds.cpp:41:19:41:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:41:19:41:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:41:19:41:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:41:19:41:19 | B | 1.0 | +| test_nr_of_bounds.cpp:41:19:41:19 | B | 1.0 | +| test_nr_of_bounds.cpp:41:19:41:19 | B | 1.0 | +| test_nr_of_bounds.cpp:42:5:42:19 | ... & ... | 4.0 | +| test_nr_of_bounds.cpp:42:5:42:19 | ... -= ... | 4.0 | +| test_nr_of_bounds.cpp:42:5:42:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:42:5:42:20 | (...) | 4.0 | +| test_nr_of_bounds.cpp:42:5:42:20 | x | 4.0 | +| test_nr_of_bounds.cpp:42:5:42:20 | x | 4.0 | +| test_nr_of_bounds.cpp:42:19:42:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:42:19:42:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:42:19:42:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:42:19:42:19 | C | 1.0 | +| test_nr_of_bounds.cpp:42:19:42:19 | C | 1.0 | +| test_nr_of_bounds.cpp:42:19:42:19 | C | 1.0 | +| test_nr_of_bounds.cpp:43:5:43:19 | ... & ... | 8.0 | +| test_nr_of_bounds.cpp:43:5:43:19 | ... -= ... | 8.0 | +| test_nr_of_bounds.cpp:43:5:43:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:43:5:43:20 | (...) | 8.0 | +| test_nr_of_bounds.cpp:43:5:43:20 | x | 8.0 | +| test_nr_of_bounds.cpp:43:5:43:20 | x | 8.0 | +| test_nr_of_bounds.cpp:43:19:43:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:43:19:43:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:43:19:43:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:43:19:43:19 | D | 1.0 | +| test_nr_of_bounds.cpp:43:19:43:19 | D | 1.0 | +| test_nr_of_bounds.cpp:43:19:43:19 | D | 1.0 | +| test_nr_of_bounds.cpp:44:5:44:19 | ... & ... | 16.0 | +| test_nr_of_bounds.cpp:44:5:44:19 | ... -= ... | 16.0 | +| test_nr_of_bounds.cpp:44:5:44:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:44:5:44:20 | (...) | 16.0 | +| test_nr_of_bounds.cpp:44:5:44:20 | x | 16.0 | +| test_nr_of_bounds.cpp:44:5:44:20 | x | 16.0 | +| test_nr_of_bounds.cpp:44:19:44:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:44:19:44:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:44:19:44:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:44:19:44:19 | E | 1.0 | +| test_nr_of_bounds.cpp:44:19:44:19 | E | 1.0 | +| test_nr_of_bounds.cpp:44:19:44:19 | E | 1.0 | +| test_nr_of_bounds.cpp:45:5:45:19 | ... & ... | 32.0 | +| test_nr_of_bounds.cpp:45:5:45:19 | ... -= ... | 32.0 | +| test_nr_of_bounds.cpp:45:5:45:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:45:5:45:20 | (...) | 32.0 | +| test_nr_of_bounds.cpp:45:5:45:20 | x | 32.0 | +| test_nr_of_bounds.cpp:45:5:45:20 | x | 32.0 | +| test_nr_of_bounds.cpp:45:19:45:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:45:19:45:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:45:19:45:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:45:19:45:19 | F | 1.0 | +| test_nr_of_bounds.cpp:45:19:45:19 | F | 1.0 | +| test_nr_of_bounds.cpp:45:19:45:19 | F | 1.0 | +| test_nr_of_bounds.cpp:46:5:46:19 | ... & ... | 64.0 | +| test_nr_of_bounds.cpp:46:5:46:19 | ... -= ... | 64.0 | +| test_nr_of_bounds.cpp:46:5:46:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:46:5:46:20 | (...) | 64.0 | +| test_nr_of_bounds.cpp:46:5:46:20 | x | 64.0 | +| test_nr_of_bounds.cpp:46:5:46:20 | x | 64.0 | +| test_nr_of_bounds.cpp:46:19:46:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:46:19:46:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:46:19:46:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:46:19:46:19 | G | 1.0 | +| test_nr_of_bounds.cpp:46:19:46:19 | G | 1.0 | +| test_nr_of_bounds.cpp:46:19:46:19 | G | 1.0 | +| test_nr_of_bounds.cpp:47:5:47:19 | ... & ... | 128.0 | +| test_nr_of_bounds.cpp:47:5:47:19 | ... -= ... | 128.0 | +| test_nr_of_bounds.cpp:47:5:47:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:47:5:47:20 | (...) | 128.0 | +| test_nr_of_bounds.cpp:47:5:47:20 | x | 128.0 | +| test_nr_of_bounds.cpp:47:5:47:20 | x | 128.0 | +| test_nr_of_bounds.cpp:47:19:47:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:47:19:47:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:47:19:47:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:47:19:47:19 | H | 1.0 | +| test_nr_of_bounds.cpp:47:19:47:19 | H | 1.0 | +| test_nr_of_bounds.cpp:47:19:47:19 | H | 1.0 | +| test_nr_of_bounds.cpp:48:5:48:19 | ... & ... | 256.0 | +| test_nr_of_bounds.cpp:48:5:48:19 | ... -= ... | 256.0 | +| test_nr_of_bounds.cpp:48:5:48:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:48:5:48:20 | (...) | 256.0 | +| test_nr_of_bounds.cpp:48:5:48:20 | x | 256.0 | +| test_nr_of_bounds.cpp:48:5:48:20 | x | 256.0 | +| test_nr_of_bounds.cpp:48:19:48:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:48:19:48:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:48:19:48:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:48:19:48:19 | I | 1.0 | +| test_nr_of_bounds.cpp:48:19:48:19 | I | 1.0 | +| test_nr_of_bounds.cpp:48:19:48:19 | I | 1.0 | +| test_nr_of_bounds.cpp:49:5:49:19 | ... & ... | 512.0 | +| test_nr_of_bounds.cpp:49:5:49:19 | ... -= ... | 512.0 | +| test_nr_of_bounds.cpp:49:5:49:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:49:5:49:20 | (...) | 512.0 | +| test_nr_of_bounds.cpp:49:5:49:20 | x | 512.0 | +| test_nr_of_bounds.cpp:49:5:49:20 | x | 512.0 | +| test_nr_of_bounds.cpp:49:19:49:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:49:19:49:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:49:19:49:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:49:19:49:19 | J | 1.0 | +| test_nr_of_bounds.cpp:49:19:49:19 | J | 1.0 | +| test_nr_of_bounds.cpp:49:19:49:19 | J | 1.0 | +| test_nr_of_bounds.cpp:50:5:50:19 | ... & ... | 1024.0 | +| test_nr_of_bounds.cpp:50:5:50:19 | ... -= ... | 1024.0 | +| test_nr_of_bounds.cpp:50:5:50:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:50:5:50:20 | (...) | 1024.0 | +| test_nr_of_bounds.cpp:50:5:50:20 | x | 1024.0 | +| test_nr_of_bounds.cpp:50:5:50:20 | x | 1024.0 | +| test_nr_of_bounds.cpp:50:19:50:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:50:19:50:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:50:19:50:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:50:19:50:19 | L | 1.0 | +| test_nr_of_bounds.cpp:50:19:50:19 | L | 1.0 | +| test_nr_of_bounds.cpp:50:19:50:19 | L | 1.0 | +| test_nr_of_bounds.cpp:51:5:51:19 | ... & ... | 2048.0 | +| test_nr_of_bounds.cpp:51:5:51:19 | ... -= ... | 2048.0 | +| test_nr_of_bounds.cpp:51:5:51:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:51:5:51:20 | (...) | 2048.0 | +| test_nr_of_bounds.cpp:51:5:51:20 | x | 2048.0 | +| test_nr_of_bounds.cpp:51:5:51:20 | x | 2048.0 | +| test_nr_of_bounds.cpp:51:19:51:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:51:19:51:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:51:19:51:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:51:19:51:19 | M | 1.0 | +| test_nr_of_bounds.cpp:51:19:51:19 | M | 1.0 | +| test_nr_of_bounds.cpp:51:19:51:19 | M | 1.0 | +| test_nr_of_bounds.cpp:52:5:52:19 | ... & ... | 4096.0 | +| test_nr_of_bounds.cpp:52:5:52:19 | ... -= ... | 4096.0 | +| test_nr_of_bounds.cpp:52:5:52:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:52:5:52:20 | (...) | 4096.0 | +| test_nr_of_bounds.cpp:52:5:52:20 | x | 4096.0 | +| test_nr_of_bounds.cpp:52:5:52:20 | x | 4096.0 | +| test_nr_of_bounds.cpp:52:19:52:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:52:19:52:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:52:19:52:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:52:19:52:19 | N | 1.0 | +| test_nr_of_bounds.cpp:52:19:52:19 | N | 1.0 | +| test_nr_of_bounds.cpp:52:19:52:19 | N | 1.0 | +| test_nr_of_bounds.cpp:53:5:53:19 | ... & ... | 8192.0 | +| test_nr_of_bounds.cpp:53:5:53:19 | ... -= ... | 8192.0 | +| test_nr_of_bounds.cpp:53:5:53:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:53:5:53:20 | (...) | 8192.0 | +| test_nr_of_bounds.cpp:53:5:53:20 | x | 8192.0 | +| test_nr_of_bounds.cpp:53:5:53:20 | x | 8192.0 | +| test_nr_of_bounds.cpp:53:19:53:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:53:19:53:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:53:19:53:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:53:19:53:19 | O | 1.0 | +| test_nr_of_bounds.cpp:53:19:53:19 | O | 1.0 | +| test_nr_of_bounds.cpp:53:19:53:19 | O | 1.0 | +| test_nr_of_bounds.cpp:54:5:54:19 | ... & ... | 16384.0 | +| test_nr_of_bounds.cpp:54:5:54:19 | ... -= ... | 16384.0 | +| test_nr_of_bounds.cpp:54:5:54:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:54:5:54:20 | (...) | 16384.0 | +| test_nr_of_bounds.cpp:54:5:54:20 | x | 16384.0 | +| test_nr_of_bounds.cpp:54:5:54:20 | x | 16384.0 | +| test_nr_of_bounds.cpp:54:19:54:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:54:19:54:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:54:19:54:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:54:19:54:19 | P | 1.0 | +| test_nr_of_bounds.cpp:54:19:54:19 | P | 1.0 | +| test_nr_of_bounds.cpp:54:19:54:19 | P | 1.0 | +| test_nr_of_bounds.cpp:55:5:55:19 | ... & ... | 32768.0 | +| test_nr_of_bounds.cpp:55:5:55:19 | ... -= ... | 32768.0 | +| test_nr_of_bounds.cpp:55:5:55:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:55:5:55:20 | (...) | 32768.0 | +| test_nr_of_bounds.cpp:55:5:55:20 | x | 32768.0 | +| test_nr_of_bounds.cpp:55:5:55:20 | x | 32768.0 | +| test_nr_of_bounds.cpp:55:19:55:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:55:19:55:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:55:19:55:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:55:19:55:19 | Q | 1.0 | +| test_nr_of_bounds.cpp:55:19:55:19 | Q | 1.0 | +| test_nr_of_bounds.cpp:55:19:55:19 | Q | 1.0 | +| test_nr_of_bounds.cpp:56:5:56:19 | ... & ... | 65536.0 | +| test_nr_of_bounds.cpp:56:5:56:19 | ... -= ... | 65536.0 | +| test_nr_of_bounds.cpp:56:5:56:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:56:5:56:20 | (...) | 65536.0 | +| test_nr_of_bounds.cpp:56:5:56:20 | x | 65536.0 | +| test_nr_of_bounds.cpp:56:5:56:20 | x | 65536.0 | +| test_nr_of_bounds.cpp:56:19:56:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:56:19:56:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:56:19:56:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:56:19:56:19 | R | 1.0 | +| test_nr_of_bounds.cpp:56:19:56:19 | R | 1.0 | +| test_nr_of_bounds.cpp:56:19:56:19 | R | 1.0 | +| test_nr_of_bounds.cpp:57:5:57:19 | ... & ... | 131072.0 | +| test_nr_of_bounds.cpp:57:5:57:19 | ... -= ... | 131072.0 | +| test_nr_of_bounds.cpp:57:5:57:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:57:5:57:20 | (...) | 131072.0 | +| test_nr_of_bounds.cpp:57:5:57:20 | x | 131072.0 | +| test_nr_of_bounds.cpp:57:5:57:20 | x | 131072.0 | +| test_nr_of_bounds.cpp:57:19:57:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:57:19:57:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:57:19:57:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:57:19:57:19 | S | 1.0 | +| test_nr_of_bounds.cpp:57:19:57:19 | S | 1.0 | +| test_nr_of_bounds.cpp:57:19:57:19 | S | 1.0 | +| test_nr_of_bounds.cpp:58:5:58:19 | ... & ... | 262144.0 | +| test_nr_of_bounds.cpp:58:5:58:19 | ... -= ... | 262144.0 | +| test_nr_of_bounds.cpp:58:5:58:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:58:5:58:20 | (...) | 262144.0 | +| test_nr_of_bounds.cpp:58:5:58:20 | x | 262144.0 | +| test_nr_of_bounds.cpp:58:5:58:20 | x | 262144.0 | +| test_nr_of_bounds.cpp:58:19:58:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:58:19:58:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:58:19:58:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:58:19:58:19 | T | 1.0 | +| test_nr_of_bounds.cpp:58:19:58:19 | T | 1.0 | +| test_nr_of_bounds.cpp:58:19:58:19 | T | 1.0 | +| test_nr_of_bounds.cpp:59:5:59:19 | ... & ... | 524288.0 | +| test_nr_of_bounds.cpp:59:5:59:19 | ... -= ... | 524288.0 | +| test_nr_of_bounds.cpp:59:5:59:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:59:5:59:20 | (...) | 524288.0 | +| test_nr_of_bounds.cpp:59:5:59:20 | x | 524288.0 | +| test_nr_of_bounds.cpp:59:5:59:20 | x | 524288.0 | +| test_nr_of_bounds.cpp:59:19:59:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:59:19:59:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:59:19:59:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:59:19:59:19 | U | 1.0 | +| test_nr_of_bounds.cpp:59:19:59:19 | U | 1.0 | +| test_nr_of_bounds.cpp:59:19:59:19 | U | 1.0 | +| test_nr_of_bounds.cpp:60:5:60:19 | ... & ... | 1048576.0 | +| test_nr_of_bounds.cpp:60:5:60:19 | ... -= ... | 1048576.0 | +| test_nr_of_bounds.cpp:60:5:60:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:60:5:60:20 | (...) | 1048576.0 | +| test_nr_of_bounds.cpp:60:5:60:20 | x | 1048576.0 | +| test_nr_of_bounds.cpp:60:5:60:20 | x | 1048576.0 | +| test_nr_of_bounds.cpp:60:19:60:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:60:19:60:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:60:19:60:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:60:19:60:19 | V | 1.0 | +| test_nr_of_bounds.cpp:60:19:60:19 | V | 1.0 | +| test_nr_of_bounds.cpp:60:19:60:19 | V | 1.0 | +| test_nr_of_bounds.cpp:61:5:61:19 | ... & ... | 2097152.0 | +| test_nr_of_bounds.cpp:61:5:61:19 | ... -= ... | 2097152.0 | +| test_nr_of_bounds.cpp:61:5:61:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:61:5:61:20 | (...) | 2097152.0 | +| test_nr_of_bounds.cpp:61:5:61:20 | x | 2097152.0 | +| test_nr_of_bounds.cpp:61:5:61:20 | x | 2097152.0 | +| test_nr_of_bounds.cpp:61:19:61:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:61:19:61:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:61:19:61:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:61:19:61:19 | W | 1.0 | +| test_nr_of_bounds.cpp:61:19:61:19 | W | 1.0 | +| test_nr_of_bounds.cpp:61:19:61:19 | W | 1.0 | +| test_nr_of_bounds.cpp:62:5:62:19 | ... & ... | 4194304.0 | +| test_nr_of_bounds.cpp:62:5:62:19 | ... -= ... | 4194304.0 | +| test_nr_of_bounds.cpp:62:5:62:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:62:5:62:20 | (...) | 4194304.0 | +| test_nr_of_bounds.cpp:62:5:62:20 | x | 4194304.0 | +| test_nr_of_bounds.cpp:62:5:62:20 | x | 4194304.0 | +| test_nr_of_bounds.cpp:62:19:62:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:62:19:62:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:62:19:62:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:62:19:62:19 | X | 1.0 | +| test_nr_of_bounds.cpp:62:19:62:19 | X | 1.0 | +| test_nr_of_bounds.cpp:62:19:62:19 | X | 1.0 | +| test_nr_of_bounds.cpp:63:5:63:19 | ... & ... | 8388608.0 | +| test_nr_of_bounds.cpp:63:5:63:19 | ... -= ... | 8388608.0 | +| test_nr_of_bounds.cpp:63:5:63:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:63:5:63:20 | (...) | 8388608.0 | +| test_nr_of_bounds.cpp:63:5:63:20 | x | 8388608.0 | +| test_nr_of_bounds.cpp:63:5:63:20 | x | 8388608.0 | +| test_nr_of_bounds.cpp:63:19:63:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:63:19:63:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:63:19:63:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:63:19:63:19 | Y | 1.0 | +| test_nr_of_bounds.cpp:63:19:63:19 | Y | 1.0 | +| test_nr_of_bounds.cpp:63:19:63:19 | Y | 1.0 | +| test_nr_of_bounds.cpp:64:5:64:19 | ... & ... | 1.6777216E7 | +| test_nr_of_bounds.cpp:64:5:64:19 | ... -= ... | 1.6777216E7 | +| test_nr_of_bounds.cpp:64:5:64:19 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:64:5:64:20 | (...) | 1.6777216E7 | +| test_nr_of_bounds.cpp:64:5:64:20 | x | 1.6777216E7 | +| test_nr_of_bounds.cpp:64:5:64:20 | x | 1.6777216E7 | +| test_nr_of_bounds.cpp:64:19:64:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:64:19:64:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:64:19:64:19 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:64:19:64:19 | Z | 1.0 | +| test_nr_of_bounds.cpp:64:19:64:19 | Z | 1.0 | +| test_nr_of_bounds.cpp:64:19:64:19 | Z | 1.0 | +| test_nr_of_bounds.cpp:65:5:65:20 | ... & ... | 3.3554432E7 | +| test_nr_of_bounds.cpp:65:5:65:20 | ... -= ... | 3.3554432E7 | +| test_nr_of_bounds.cpp:65:5:65:20 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:65:5:65:21 | (...) | 3.3554432E7 | +| test_nr_of_bounds.cpp:65:5:65:21 | x | 3.3554432E7 | +| test_nr_of_bounds.cpp:65:5:65:21 | x | 3.3554432E7 | +| test_nr_of_bounds.cpp:65:19:65:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:65:19:65:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:65:19:65:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:65:19:65:20 | AA | 1.0 | +| test_nr_of_bounds.cpp:65:19:65:20 | AA | 1.0 | +| test_nr_of_bounds.cpp:65:19:65:20 | AA | 1.0 | +| test_nr_of_bounds.cpp:66:5:66:20 | ... & ... | 6.7108864E7 | +| test_nr_of_bounds.cpp:66:5:66:20 | ... -= ... | 6.7108864E7 | +| test_nr_of_bounds.cpp:66:5:66:20 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:66:5:66:21 | (...) | 6.7108864E7 | +| test_nr_of_bounds.cpp:66:5:66:21 | x | 6.7108864E7 | +| test_nr_of_bounds.cpp:66:5:66:21 | x | 6.7108864E7 | +| test_nr_of_bounds.cpp:66:19:66:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:66:19:66:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:66:19:66:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:66:19:66:20 | AB | 1.0 | +| test_nr_of_bounds.cpp:66:19:66:20 | AB | 1.0 | +| test_nr_of_bounds.cpp:66:19:66:20 | AB | 1.0 | +| test_nr_of_bounds.cpp:67:5:67:20 | ... & ... | 1.34217728E8 | +| test_nr_of_bounds.cpp:67:5:67:20 | ... -= ... | 1.34217728E8 | +| test_nr_of_bounds.cpp:67:5:67:20 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:67:5:67:21 | (...) | 1.34217728E8 | +| test_nr_of_bounds.cpp:67:5:67:21 | x | 1.34217728E8 | +| test_nr_of_bounds.cpp:67:5:67:21 | x | 1.34217728E8 | +| test_nr_of_bounds.cpp:67:19:67:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:67:19:67:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:67:19:67:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:67:19:67:20 | AC | 1.0 | +| test_nr_of_bounds.cpp:67:19:67:20 | AC | 1.0 | +| test_nr_of_bounds.cpp:67:19:67:20 | AC | 1.0 | +| test_nr_of_bounds.cpp:68:5:68:20 | ... & ... | 2.68435456E8 | +| test_nr_of_bounds.cpp:68:5:68:20 | ... -= ... | 2.68435456E8 | +| test_nr_of_bounds.cpp:68:5:68:20 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:68:5:68:21 | (...) | 2.68435456E8 | +| test_nr_of_bounds.cpp:68:5:68:21 | x | 2.68435456E8 | +| test_nr_of_bounds.cpp:68:5:68:21 | x | 2.68435456E8 | +| test_nr_of_bounds.cpp:68:19:68:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:68:19:68:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:68:19:68:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:68:19:68:20 | AD | 1.0 | +| test_nr_of_bounds.cpp:68:19:68:20 | AD | 1.0 | +| test_nr_of_bounds.cpp:68:19:68:20 | AD | 1.0 | +| test_nr_of_bounds.cpp:69:5:69:20 | ... & ... | 5.36870912E8 | +| test_nr_of_bounds.cpp:69:5:69:20 | ... -= ... | 5.36870912E8 | +| test_nr_of_bounds.cpp:69:5:69:20 | ... == ... | 1.0 | +| test_nr_of_bounds.cpp:69:5:69:21 | (...) | 5.36870912E8 | +| test_nr_of_bounds.cpp:69:5:69:21 | x | 5.36870912E8 | +| test_nr_of_bounds.cpp:69:5:69:21 | x | 5.36870912E8 | +| test_nr_of_bounds.cpp:69:19:69:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:69:19:69:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:69:19:69:20 | (unsigned int)... | 1.0 | +| test_nr_of_bounds.cpp:69:19:69:20 | AE | 1.0 | +| test_nr_of_bounds.cpp:69:19:69:20 | AE | 1.0 | +| test_nr_of_bounds.cpp:69:19:69:20 | AE | 1.0 | +| test_nr_of_bounds.cpp:72:12:72:12 | x | 1.073741824E9 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/nrOfBounds.ql b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/nrOfBounds.ql index efafcf6e684..5539dc0720b 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/nrOfBounds.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/nrOfBounds.ql @@ -14,8 +14,14 @@ private predicate nonFunctionalNrOfBounds(Expr e) { strictcount(SimpleRangeAnalysisInternal::estimateNrOfBounds(e)) > 1 } +private predicate nrOfBoundsNotEq1(Expr e, int n) { + e.getFile().getBaseName() = "test_nr_of_bounds.cpp" and + n = count(SimpleRangeAnalysisInternal::estimateNrOfBounds(e)) and + n != 1 +} + module FunctionalityTest implements TestSig { - string getARelevantTag() { result = "nonFunctionalNrOfBounds" } + string getARelevantTag() { result = ["nonFunctionalNrOfBounds", "bounds"] } predicate hasActualResult(Location location, string element, string tag, string value) { exists(Expr e | @@ -25,6 +31,14 @@ module FunctionalityTest implements TestSig { tag = "nonFunctionalNrOfBounds" and value = "" ) + or + exists(Expr e, int n | + nrOfBoundsNotEq1(e, n) and + location = e.getLocation() and + element = e.toString() and + tag = "bounds" and + value = n.toString() + ) } } diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c index d394eb637ab..71f28e8f605 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c @@ -972,3 +972,15 @@ void test_overflow() { out(y); } } + +enum MY_ENUM_2 { + A = 0x1, + B = 0x2, + C = 0x4, + D = 0x8, + E = 0x10 +}; + +void test_enum(enum MY_ENUM_2 e) { + out(e); +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test_nr_of_bounds.cpp b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test_nr_of_bounds.cpp new file mode 100644 index 00000000000..4c78d719053 --- /dev/null +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test_nr_of_bounds.cpp @@ -0,0 +1,73 @@ +enum MY_ENUM { + A = 0x1, + B = 0x2, + C = 0x4, + D = 0x8, + E = 0x10, + F = 0x20, + G = 0x40, + H = 0x80, + I = 0x100, + J = 0x200, + L = 0x400, + M = 0x800, + N = 0x1000, + O = 0x2000, + P = 0x4000, + Q = 0x8000, + R = 0x10000, + S = 0x20000, + T = 0x40000, + U = 0x80000, + V = 0x100000, + W = 0x200000, + X = 0x400000, + Y = 0x800000, + Z = 0x1000000, + AA = 0x2000000, + AB = 0x4000000, + AC = 0x8000000, + AD = 0x10000000, + AE = 0x20000000 +}; + +typedef unsigned int MY_ENUM_FLAGS; + +MY_ENUM_FLAGS check_and_subs(MY_ENUM_FLAGS x) +{ + + #define CHECK_AND_SUB(flag) if ((x & flag) == flag) { x -= flag; } + CHECK_AND_SUB(A); + CHECK_AND_SUB(B); + CHECK_AND_SUB(C); + CHECK_AND_SUB(D); + CHECK_AND_SUB(E); + CHECK_AND_SUB(F); + CHECK_AND_SUB(G); + CHECK_AND_SUB(H); + CHECK_AND_SUB(I); + CHECK_AND_SUB(J); + CHECK_AND_SUB(L); + CHECK_AND_SUB(M); + CHECK_AND_SUB(N); + CHECK_AND_SUB(O); + CHECK_AND_SUB(P); + CHECK_AND_SUB(Q); + CHECK_AND_SUB(R); + CHECK_AND_SUB(S); + CHECK_AND_SUB(T); + CHECK_AND_SUB(U); + CHECK_AND_SUB(V); + CHECK_AND_SUB(W); + CHECK_AND_SUB(X); + CHECK_AND_SUB(Y); + CHECK_AND_SUB(Z); + CHECK_AND_SUB(AA); + CHECK_AND_SUB(AB); + CHECK_AND_SUB(AC); + CHECK_AND_SUB(AD); + CHECK_AND_SUB(AE); + #undef CHECK_AND_SUB + + return x; +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index dd7fc398f0c..a4aee501a94 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -1025,6 +1025,7 @@ | test.c:970:12:970:12 | y | 256 | | test.c:971:9:971:9 | x | 2147483647 | | test.c:972:9:972:9 | y | 256 | +| test.c:985:7:985:7 | e | 2147483647 | | test.cpp:10:7:10:7 | b | 2147483647 | | test.cpp:11:5:11:5 | x | 2147483647 | | test.cpp:13:10:13:10 | x | 2147483647 | @@ -1093,3 +1094,64 @@ | test.cpp:122:4:122:4 | n | 32767 | | test.cpp:122:8:122:8 | n | 0 | | test.cpp:122:12:122:12 | n | 32767 | +| test_nr_of_bounds.cpp:40:5:40:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:40:5:40:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:41:5:41:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:41:5:41:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:42:5:42:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:42:5:42:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:43:5:43:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:43:5:43:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:44:5:44:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:44:5:44:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:45:5:45:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:45:5:45:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:46:5:46:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:46:5:46:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:47:5:47:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:47:5:47:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:48:5:48:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:48:5:48:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:49:5:49:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:49:5:49:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:50:5:50:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:50:5:50:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:51:5:51:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:51:5:51:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:52:5:52:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:52:5:52:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:53:5:53:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:53:5:53:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:54:5:54:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:54:5:54:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:55:5:55:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:55:5:55:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:56:5:56:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:56:5:56:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:57:5:57:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:57:5:57:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:58:5:58:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:58:5:58:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:59:5:59:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:59:5:59:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:60:5:60:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:60:5:60:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:61:5:61:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:61:5:61:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:62:5:62:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:62:5:62:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:63:5:63:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:63:5:63:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:64:5:64:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:64:5:64:20 | x | 4294967295 | +| test_nr_of_bounds.cpp:65:5:65:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:65:5:65:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:66:5:66:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:66:5:66:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:67:5:67:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:67:5:67:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:68:5:68:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:68:5:68:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:69:5:69:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:69:5:69:21 | x | 4294967295 | +| test_nr_of_bounds.cpp:72:12:72:12 | x | 4294967295 | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp index abc21aa74d8..07e3520fa81 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp @@ -250,3 +250,8 @@ void* test_strndupa(const char* s, size_t size) { return s2; // BAD } +int* f_rec(int *p) { + int x; + int* px = f_rec(&x); // GOOD + return p; +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs index bbd90989617..c93df9ccc4f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs @@ -11,6 +11,10 @@ namespace Semmle.Extraction.CSharp.Entities private Event(Context cx, IEventSymbol init) : base(cx, init) { } + protected override IEventSymbol BodyDeclaringSymbol => Symbol.PartialImplementationPart ?? Symbol; + + public override Microsoft.CodeAnalysis.Location? ReportingLocation => BodyDeclaringSymbol.Locations.BestOrDefault(); + public override void WriteId(EscapingTextWriter trapFile) { trapFile.WriteSubId(ContainingType!); @@ -27,13 +31,13 @@ namespace Semmle.Extraction.CSharp.Entities var type = Type.Create(Context, Symbol.Type); trapFile.events(this, Symbol.GetName(), ContainingType!, type.TypeRef, Create(Context, Symbol.OriginalDefinition)); - var adder = Symbol.AddMethod; - var remover = Symbol.RemoveMethod; + var adder = BodyDeclaringSymbol.AddMethod; + var remover = BodyDeclaringSymbol.RemoveMethod; - if (!(adder is null)) + if (adder is not null) Method.Create(Context, adder); - if (!(remover is null)) + if (remover is not null) Method.Create(Context, remover); PopulateModifiers(trapFile); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs index 254e7c76956..3e8ab9431be 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs @@ -13,6 +13,10 @@ namespace Semmle.Extraction.CSharp.Entities this.@event = @event; } + public override bool NeedsPopulation => + base.NeedsPopulation && + !Symbol.IsPartialDefinition; // Accessors always have an implementing declaration as well. + /// /// Gets the event symbol associated with accessor `symbol`, or `null` /// if there is no associated symbol. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs index 0da8de1e5d5..ed8dae3738f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs @@ -160,6 +160,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case SyntaxKind.ThisExpression: return This.CreateExplicit(info); + case SyntaxKind.FieldExpression: + return PropertyFieldAccess.Create(info); + case SyntaxKind.AddressOfExpression: return Unary.Create(info.SetKind(ExprKind.ADDRESS_OF)); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/PropertyFieldAccess.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/PropertyFieldAccess.cs new file mode 100644 index 00000000000..a9d2afa84c9 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/PropertyFieldAccess.cs @@ -0,0 +1,28 @@ +using System.IO; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal class PropertyFieldAccess : Expression + { + private PropertyFieldAccess(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.FIELD_ACCESS)) { } + + public static Expression Create(ExpressionNodeInfo info) => new PropertyFieldAccess(info).TryPopulate(); + + protected override void PopulateExpression(TextWriter trapFile) + { + var symbolInfo = Context.GetSymbolInfo(Syntax); + if (symbolInfo.Symbol is IFieldSymbol field) + { + var target = PropertyField.Create(Context, field); + trapFile.expr_access(this, target); + if (!field.IsStatic) + { + This.CreateImplicit(Context, field.ContainingType, Location, this, -1); + } + } + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs index 9a010aad376..329115f11c7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs @@ -10,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities { internal class Field : CachedSymbol, IExpressionParentEntity { - private Field(Context cx, IFieldSymbol init) + protected Field(Context cx, IFieldSymbol init) : base(cx, init) { type = new Lazy(() => Entities.Type.Create(cx, Symbol.Type)); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PropertyField.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PropertyField.cs new file mode 100644 index 00000000000..9e9b1f41fff --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PropertyField.cs @@ -0,0 +1,53 @@ +using System.IO; +using Microsoft.CodeAnalysis; +using Semmle.Extraction.CSharp.Util; +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities +{ + /// + /// Represents the autogenerated backing field `field` for a property. + /// It is only created for properties that use the `field` keyword in their getter or setter, and + /// is not created for auto-properties. + /// + internal class PropertyField : Field + { + protected PropertyField(Context cx, IFieldSymbol init) + : base(cx, init) + { + } + + public static new PropertyField Create(Context cx, IFieldSymbol field) => PropertyFieldFactory.Instance.CreateEntity(cx, (field, field.AssociatedSymbol), field); + + public override bool NeedsPopulation => true; + + public override void Populate(TextWriter trapFile) + { + PopulateNullability(trapFile, Symbol.GetAnnotatedType()); + + var unboundFieldKey = PropertyField.Create(Context, Symbol.OriginalDefinition); + var name = Symbol.AssociatedSymbol is not null ? $"{Symbol.AssociatedSymbol.GetName()}.field" : Symbol.Name; + trapFile.fields(this, VariableKind.None, name, ContainingType!, Type.TypeRef, unboundFieldKey); + trapFile.compiler_generated(this); + + PopulateModifiers(trapFile); + + if (Context.OnlyScaffold) + { + return; + } + + if (Context.ExtractLocation(Symbol)) + { + WriteLocationsToTrap(trapFile.field_location, this, Locations); + } + } + + private class PropertyFieldFactory : CachedEntityFactory + { + public static PropertyFieldFactory Instance { get; } = new PropertyFieldFactory(); + + public override PropertyField Create(Context cx, IFieldSymbol init) => new PropertyField(cx, init); + } + } +} diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md index 68238efa110..df4169a1174 100644 --- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.7.59 + +No user-facing changes. + ## 1.7.58 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.59.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.59.md new file mode 100644 index 00000000000..7f6b5bd0256 --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.59.md @@ -0,0 +1,3 @@ +## 1.7.59 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml index 422196097f2..45a32aec800 100644 --- a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.7.58 +lastReleaseVersion: 1.7.59 diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index bc1e19c5d11..2bf13d256c9 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.7.59-dev +version: 1.7.60-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md index 68238efa110..df4169a1174 100644 --- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.7.59 + +No user-facing changes. + ## 1.7.58 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.59.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.59.md new file mode 100644 index 00000000000..7f6b5bd0256 --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.59.md @@ -0,0 +1,3 @@ +## 1.7.59 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml index 422196097f2..45a32aec800 100644 --- a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.7.58 +lastReleaseVersion: 1.7.59 diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 87016f799ea..780301f353c 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.7.59-dev +version: 1.7.60-dev groups: - csharp - solorigate diff --git a/csharp/ql/integration-tests/posix/conftest.py b/csharp/ql/integration-tests/posix/conftest.py new file mode 100644 index 00000000000..543bc046c98 --- /dev/null +++ b/csharp/ql/integration-tests/posix/conftest.py @@ -0,0 +1,19 @@ +import runs_on + + +def _supports_mono_nuget(): + """ + Helper function to determine if the current platform supports Mono and nuget. + + Returns True if running on Linux or on macOS x86_64 (excluding macos-15 and macos-26). + macOS ARM runners (macos-15 and macos-26) are excluded due to issues with Mono and nuget. + """ + return ( + runs_on.linux + or ( + runs_on.macos + and runs_on.x86_64 + and not runs_on.macos_15 + and not runs_on.macos_26 + ) + ) diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_no_framework/test.py b/csharp/ql/integration-tests/posix/standalone_dependencies_no_framework/test.py index d1c1745d69b..725ded1899c 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_no_framework/test.py +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_no_framework/test.py @@ -1,13 +1,9 @@ -import runs_on import pytest import os +from ..conftest import _supports_mono_nuget -# Skipping the test on the ARM runners and macos-15, as we're running into trouble with Mono and nuget. -@pytest.mark.only_if( - runs_on.linux - or (runs_on.macos and runs_on.x86_64 and not runs_on.macos_15) -) +@pytest.mark.only_if(_supports_mono_nuget()) def test(codeql, csharp): os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_DOTNET_FRAMEWORK_REFERENCES"] = ( "/non-existent-path" diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget with_space/test.py b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget with_space/test.py index 6d2058c684c..662178aa3c0 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget with_space/test.py +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget with_space/test.py @@ -1,13 +1,9 @@ import os -import runs_on import pytest +from ..conftest import _supports_mono_nuget -# Skipping the test on the ARM runners and macos-15, as we're running into trouble with Mono and nuget. -@pytest.mark.only_if( - runs_on.linux - or (runs_on.macos and runs_on.x86_64 and not runs_on.macos_15) -) +@pytest.mark.only_if(_supports_mono_nuget()) def test(codeql, csharp): # making sure we're not doing any fallback restore: os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_FALLBACK_TIMEOUT"] = "1" diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget/test.py b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget/test.py index 7f88196097f..d8e8c8055ad 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget/test.py +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget/test.py @@ -1,11 +1,7 @@ -import runs_on import pytest +from ..conftest import _supports_mono_nuget -# Skipping the test on the ARM runners and macos-15, as we're running into trouble with Mono and nuget. -@pytest.mark.only_if( - runs_on.linux - or (runs_on.macos and runs_on.x86_64 and not runs_on.macos_15) -) +@pytest.mark.only_if(_supports_mono_nuget()) def test(codeql, csharp): codeql.database.create(build_mode="none") diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_no_sources/test.py b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_no_sources/test.py index 185fb5201f9..ccd8f61a384 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_no_sources/test.py +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_no_sources/test.py @@ -1,11 +1,7 @@ -import runs_on import pytest +from ..conftest import _supports_mono_nuget -# Skipping the test on the ARM runners, as we're running into trouble with Mono and nuget. -@pytest.mark.only_if( - runs_on.linux - or (runs_on.macos and runs_on.x86_64 and not runs_on.macos_15) -) +@pytest.mark.only_if(_supports_mono_nuget()) def test(codeql, csharp): codeql.database.create(source_root="proj", build_mode="none") diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md index 2910824c1b7..21b19c8a09a 100644 --- a/csharp/ql/lib/CHANGELOG.md +++ b/csharp/ql/lib/CHANGELOG.md @@ -1,3 +1,10 @@ +## 5.4.7 + +### Minor Analysis Improvements + +* The model for `System.Web.HttpUtility` has been modified to better model the flow of tainted URIs. +* C# 14: Added support for `extension` members in the extractor, QL library, data flow, and Models as Data, covering extension methods, properties, and operators. + ## 5.4.6 ### Minor Analysis Improvements diff --git a/csharp/ql/lib/change-notes/2026-02-09-update-system.web.httputility-model.md b/csharp/ql/lib/change-notes/2026-02-09-update-system.web.httputility-model.md deleted file mode 100644 index 750761fdf37..00000000000 --- a/csharp/ql/lib/change-notes/2026-02-09-update-system.web.httputility-model.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* The model for `System.Web.HttpUtility` has been modified to better model the flow of tainted URIs. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2026-02-12-field-keyword.md b/csharp/ql/lib/change-notes/2026-02-12-field-keyword.md new file mode 100644 index 00000000000..7ca6548b27f --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-02-12-field-keyword.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* C# 14: Added support for the `field` keyword in properties. diff --git a/csharp/ql/lib/change-notes/2026-02-16-partial-events.md b/csharp/ql/lib/change-notes/2026-02-16-partial-events.md new file mode 100644 index 00000000000..3bbc1ae829a --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-02-16-partial-events.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* C# 14: Added support for partial events. diff --git a/csharp/ql/lib/change-notes/2026-02-05-extension-types.md b/csharp/ql/lib/change-notes/released/5.4.7.md similarity index 53% rename from csharp/ql/lib/change-notes/2026-02-05-extension-types.md rename to csharp/ql/lib/change-notes/released/5.4.7.md index c3f1a21a5ed..b7d268470a2 100644 --- a/csharp/ql/lib/change-notes/2026-02-05-extension-types.md +++ b/csharp/ql/lib/change-notes/released/5.4.7.md @@ -1,4 +1,6 @@ ---- -category: minorAnalysis ---- +## 5.4.7 + +### Minor Analysis Improvements + +* The model for `System.Web.HttpUtility` has been modified to better model the flow of tainted URIs. * C# 14: Added support for `extension` members in the extractor, QL library, data flow, and Models as Data, covering extension methods, properties, and operators. diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml index 2f1d6ff78a8..4db516ab415 100644 --- a/csharp/ql/lib/codeql-pack.release.yml +++ b/csharp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 5.4.6 +lastReleaseVersion: 5.4.7 diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 31fb2ca6618..30f75e74304 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 5.4.7-dev +version: 5.4.8-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md index d532951fadc..8f2e918ca55 100644 --- a/csharp/ql/src/CHANGELOG.md +++ b/csharp/ql/src/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.6.2 + +### Bug Fixes + +* The `cs/web/missing-token-validation` ("Missing cross-site request forgery token validation") query now recognizes antiforgery attributes on base controller classes, fixing false positives when `[ValidateAntiForgeryToken]` or `[AutoValidateAntiforgeryToken]` is applied to a parent class. + ## 1.6.1 No user-facing changes. diff --git a/csharp/ql/src/change-notes/2026-02-04-csrf-inherited-attribute.md b/csharp/ql/src/change-notes/released/1.6.2.md similarity index 92% rename from csharp/ql/src/change-notes/2026-02-04-csrf-inherited-attribute.md rename to csharp/ql/src/change-notes/released/1.6.2.md index 7c9875fcdfd..696f2d0d859 100644 --- a/csharp/ql/src/change-notes/2026-02-04-csrf-inherited-attribute.md +++ b/csharp/ql/src/change-notes/released/1.6.2.md @@ -1,4 +1,5 @@ ---- -category: fix ---- +## 1.6.2 + +### Bug Fixes + * The `cs/web/missing-token-validation` ("Missing cross-site request forgery token validation") query now recognizes antiforgery attributes on base controller classes, fixing false positives when `[ValidateAntiForgeryToken]` or `[AutoValidateAntiforgeryToken]` is applied to a parent class. diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml index ef7a789e0cf..5f5beb68311 100644 --- a/csharp/ql/src/codeql-pack.release.yml +++ b/csharp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.6.1 +lastReleaseVersion: 1.6.2 diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index 492445c2374..d43afd632c1 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 1.6.2-dev +version: 1.6.3-dev groups: - csharp - queries diff --git a/csharp/ql/test/library-tests/dataflow/fields/D.cs b/csharp/ql/test/library-tests/dataflow/fields/D.cs index 7f07cf5ca0b..45dfbffc801 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/D.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/D.cs @@ -89,3 +89,65 @@ public partial class DPartial static T Source(object source) => throw null; } + +public class DFieldProps +{ + object FieldProp0 + { + get { return field; } + set { field = value; } + } = Source(0); + + object FieldProp1 + { + get { return field; } + set { field = value; } + } + + object FieldProp2 + { + get { return field; } + set + { + var x = value; + field = x; + } + } + + static object StaticFieldProp + { + get { return field; } + set { field = value; } + } + + private void M() + { + var d0 = new DFieldProps(); + Sink(d0.FieldProp0); // $ hasValueFlow=0 + Sink(d0.FieldProp1); // no flow + Sink(d0.FieldProp2); // no flow + + var d1 = new DFieldProps(); + var o1 = Source(1); + d1.FieldProp1 = o1; + Sink(d1.FieldProp0); // $ hasValueFlow=0 + Sink(d1.FieldProp1); // $ hasValueFlow=1 + Sink(d1.FieldProp2); // no flow + + var d2 = new DFieldProps(); + var o2 = Source(2); + d2.FieldProp2 = o2; + Sink(d2.FieldProp0); // $ hasValueFlow=0 + Sink(d2.FieldProp1); // no flow + Sink(d2.FieldProp2); // $ hasValueFlow=2 + + var o3 = Source(3); + DFieldProps.StaticFieldProp = o3; + Sink(DFieldProps.StaticFieldProp); // $ hasValueFlow=3 + } + + public static void Sink(object o) { } + + static T Source(object source) => throw null; + +} diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index 4e469e11887..44789d1f847 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -532,6 +532,118 @@ edges | D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | provenance | | | D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:84:14:84:27 | access to property PartialProp1 | provenance | | | D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:84:14:84:27 | access to property PartialProp1 | provenance | | +| D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:125:18:125:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:125:18:125:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:130:18:130:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:130:18:130:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:137:18:137:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:137:18:137:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:95:12:95:21 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:95:12:95:21 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | this access : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | this access : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:97:22:97:26 | this access : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | access to field FieldProp0.field : Object | provenance | | +| D.cs:97:22:97:26 | this access : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | access to field FieldProp0.field : Object | provenance | | +| D.cs:98:9:98:11 | value : Object | D.cs:98:23:98:27 | access to parameter value : Object | provenance | | +| D.cs:98:9:98:11 | value : Object | D.cs:98:23:98:27 | access to parameter value : Object | provenance | | +| D.cs:98:15:98:19 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:98:9:98:11 | this [Return] : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:98:15:98:19 | [post] this access : DFieldProps [field FieldProp0.field] : Object | D.cs:98:9:98:11 | this [Return] : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:98:23:98:27 | access to parameter value : Object | D.cs:98:15:98:19 | [post] this access : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:98:23:98:27 | access to parameter value : Object | D.cs:98:15:98:19 | [post] this access : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:99:9:99:25 | call to method Source : Object | D.cs:95:12:95:21 | [post] this access : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:99:9:99:25 | call to method Source : Object | D.cs:95:12:95:21 | [post] this access : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:99:9:99:25 | call to method Source : Object | D.cs:98:9:98:11 | value : Object | provenance | | +| D.cs:99:9:99:25 | call to method Source : Object | D.cs:98:9:98:11 | value : Object | provenance | | +| D.cs:103:9:103:11 | this : DFieldProps [field FieldProp1.field] : Object | D.cs:103:22:103:26 | this access : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:103:9:103:11 | this : DFieldProps [field FieldProp1.field] : Object | D.cs:103:22:103:26 | this access : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:103:22:103:26 | this access : DFieldProps [field FieldProp1.field] : Object | D.cs:103:22:103:26 | access to field FieldProp1.field : Object | provenance | | +| D.cs:103:22:103:26 | this access : DFieldProps [field FieldProp1.field] : Object | D.cs:103:22:103:26 | access to field FieldProp1.field : Object | provenance | | +| D.cs:104:9:104:11 | value : Object | D.cs:104:23:104:27 | access to parameter value : Object | provenance | | +| D.cs:104:9:104:11 | value : Object | D.cs:104:23:104:27 | access to parameter value : Object | provenance | | +| D.cs:104:15:104:19 | [post] this access : DFieldProps [field FieldProp1.field] : Object | D.cs:104:9:104:11 | this [Return] : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:104:15:104:19 | [post] this access : DFieldProps [field FieldProp1.field] : Object | D.cs:104:9:104:11 | this [Return] : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:104:23:104:27 | access to parameter value : Object | D.cs:104:15:104:19 | [post] this access : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:104:23:104:27 | access to parameter value : Object | D.cs:104:15:104:19 | [post] this access : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:109:9:109:11 | this : DFieldProps [field FieldProp2.field] : Object | D.cs:109:22:109:26 | this access : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:109:9:109:11 | this : DFieldProps [field FieldProp2.field] : Object | D.cs:109:22:109:26 | this access : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:109:22:109:26 | this access : DFieldProps [field FieldProp2.field] : Object | D.cs:109:22:109:26 | access to field FieldProp2.field : Object | provenance | | +| D.cs:109:22:109:26 | this access : DFieldProps [field FieldProp2.field] : Object | D.cs:109:22:109:26 | access to field FieldProp2.field : Object | provenance | | +| D.cs:110:9:110:11 | value : Object | D.cs:112:17:112:17 | access to local variable x : Object | provenance | | +| D.cs:110:9:110:11 | value : Object | D.cs:112:17:112:17 | access to local variable x : Object | provenance | | +| D.cs:112:17:112:17 | access to local variable x : Object | D.cs:113:21:113:21 | access to local variable x : Object | provenance | | +| D.cs:112:17:112:17 | access to local variable x : Object | D.cs:113:21:113:21 | access to local variable x : Object | provenance | | +| D.cs:113:13:113:17 | [post] this access : DFieldProps [field FieldProp2.field] : Object | D.cs:110:9:110:11 | this [Return] : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:113:13:113:17 | [post] this access : DFieldProps [field FieldProp2.field] : Object | D.cs:110:9:110:11 | this [Return] : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:113:21:113:21 | access to local variable x : Object | D.cs:113:13:113:17 | [post] this access : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:113:21:113:21 | access to local variable x : Object | D.cs:113:13:113:17 | [post] this access : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:119:22:119:26 | access to field StaticFieldProp.field : Object | D.cs:146:14:146:40 | access to property StaticFieldProp | provenance | | +| D.cs:119:22:119:26 | access to field StaticFieldProp.field : Object | D.cs:146:14:146:40 | access to property StaticFieldProp | provenance | | +| D.cs:120:9:120:11 | value : Object | D.cs:120:23:120:27 | access to parameter value : Object | provenance | | +| D.cs:120:9:120:11 | value : Object | D.cs:120:23:120:27 | access to parameter value : Object | provenance | | +| D.cs:120:23:120:27 | access to parameter value : Object | D.cs:119:22:119:26 | access to field StaticFieldProp.field : Object | provenance | | +| D.cs:120:23:120:27 | access to parameter value : Object | D.cs:119:22:119:26 | access to field StaticFieldProp.field : Object | provenance | | +| D.cs:125:13:125:14 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:125:13:125:14 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:125:18:125:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | D.cs:125:13:125:14 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:125:18:125:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | D.cs:125:13:125:14 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | D.cs:126:14:126:26 | access to property FieldProp0 | provenance | | +| D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | D.cs:126:14:126:26 | access to property FieldProp0 | provenance | | +| D.cs:130:13:130:14 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:130:13:130:14 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:130:18:130:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | D.cs:130:13:130:14 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:130:18:130:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | D.cs:130:13:130:14 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:131:13:131:14 | access to local variable o1 : Object | D.cs:132:25:132:26 | access to local variable o1 : Object | provenance | | +| D.cs:131:13:131:14 | access to local variable o1 : Object | D.cs:132:25:132:26 | access to local variable o1 : Object | provenance | | +| D.cs:131:18:131:34 | call to method Source : Object | D.cs:131:13:131:14 | access to local variable o1 : Object | provenance | | +| D.cs:131:18:131:34 | call to method Source : Object | D.cs:131:13:131:14 | access to local variable o1 : Object | provenance | | +| D.cs:132:9:132:10 | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:132:9:132:10 | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:132:25:132:26 | access to local variable o1 : Object | D.cs:104:9:104:11 | value : Object | provenance | | +| D.cs:132:25:132:26 | access to local variable o1 : Object | D.cs:104:9:104:11 | value : Object | provenance | | +| D.cs:132:25:132:26 | access to local variable o1 : Object | D.cs:132:9:132:10 | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:132:25:132:26 | access to local variable o1 : Object | D.cs:132:9:132:10 | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | D.cs:133:14:133:26 | access to property FieldProp0 | provenance | | +| D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | D.cs:133:14:133:26 | access to property FieldProp0 | provenance | | +| D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | D.cs:103:9:103:11 | this : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | D.cs:103:9:103:11 | this : DFieldProps [field FieldProp1.field] : Object | provenance | | +| D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | D.cs:134:14:134:26 | access to property FieldProp1 | provenance | | +| D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | D.cs:134:14:134:26 | access to property FieldProp1 | provenance | | +| D.cs:137:13:137:14 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:137:13:137:14 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:137:18:137:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | D.cs:137:13:137:14 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:137:18:137:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | D.cs:137:13:137:14 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:138:13:138:14 | access to local variable o2 : Object | D.cs:139:25:139:26 | access to local variable o2 : Object | provenance | | +| D.cs:138:13:138:14 | access to local variable o2 : Object | D.cs:139:25:139:26 | access to local variable o2 : Object | provenance | | +| D.cs:138:18:138:34 | call to method Source : Object | D.cs:138:13:138:14 | access to local variable o2 : Object | provenance | | +| D.cs:138:18:138:34 | call to method Source : Object | D.cs:138:13:138:14 | access to local variable o2 : Object | provenance | | +| D.cs:139:9:139:10 | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:139:9:139:10 | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:139:25:139:26 | access to local variable o2 : Object | D.cs:110:9:110:11 | value : Object | provenance | | +| D.cs:139:25:139:26 | access to local variable o2 : Object | D.cs:110:9:110:11 | value : Object | provenance | | +| D.cs:139:25:139:26 | access to local variable o2 : Object | D.cs:139:9:139:10 | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:139:25:139:26 | access to local variable o2 : Object | D.cs:139:9:139:10 | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | provenance | | +| D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | D.cs:140:14:140:26 | access to property FieldProp0 | provenance | | +| D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | D.cs:140:14:140:26 | access to property FieldProp0 | provenance | | +| D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | D.cs:109:9:109:11 | this : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | D.cs:109:9:109:11 | this : DFieldProps [field FieldProp2.field] : Object | provenance | | +| D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | D.cs:142:14:142:26 | access to property FieldProp2 | provenance | | +| D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | D.cs:142:14:142:26 | access to property FieldProp2 | provenance | | +| D.cs:144:13:144:14 | access to local variable o3 : Object | D.cs:145:9:145:35 | access to property StaticFieldProp : Object | provenance | | +| D.cs:144:13:144:14 | access to local variable o3 : Object | D.cs:145:9:145:35 | access to property StaticFieldProp : Object | provenance | | +| D.cs:144:13:144:14 | access to local variable o3 : Object | D.cs:145:39:145:40 | access to local variable o3 : Object | provenance | | +| D.cs:144:13:144:14 | access to local variable o3 : Object | D.cs:145:39:145:40 | access to local variable o3 : Object | provenance | | +| D.cs:144:18:144:34 | call to method Source : Object | D.cs:144:13:144:14 | access to local variable o3 : Object | provenance | | +| D.cs:144:18:144:34 | call to method Source : Object | D.cs:144:13:144:14 | access to local variable o3 : Object | provenance | | +| D.cs:145:9:145:35 | access to property StaticFieldProp : Object | D.cs:146:14:146:40 | access to property StaticFieldProp | provenance | | +| D.cs:145:9:145:35 | access to property StaticFieldProp : Object | D.cs:146:14:146:40 | access to property StaticFieldProp | provenance | | +| D.cs:145:39:145:40 | access to local variable o3 : Object | D.cs:120:9:120:11 | value : Object | provenance | | +| D.cs:145:39:145:40 | access to local variable o3 : Object | D.cs:120:9:120:11 | value : Object | provenance | | | E.cs:8:29:8:29 | o : Object | E.cs:11:21:11:21 | access to parameter o : Object | provenance | | | E.cs:8:29:8:29 | o : Object | E.cs:11:21:11:21 | access to parameter o : Object | provenance | | | E.cs:11:9:11:11 | [post] access to local variable ret : S [field Field] : Object | E.cs:12:16:12:18 | access to local variable ret : S [field Field] : Object | provenance | | @@ -1807,6 +1919,120 @@ nodes | D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | semmle.label | access to local variable d : DPartial [field _backingField] : Object | | D.cs:84:14:84:27 | access to property PartialProp1 | semmle.label | access to property PartialProp1 | | D.cs:84:14:84:27 | access to property PartialProp1 | semmle.label | access to property PartialProp1 | +| D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:93:14:93:24 | [post] this access : DFieldProps [field FieldProp0.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:95:12:95:21 | [post] this access : DFieldProps [field FieldProp0.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:95:12:95:21 | [post] this access : DFieldProps [field FieldProp0.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | semmle.label | this : DFieldProps [field FieldProp0.field] : Object | +| D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | semmle.label | this : DFieldProps [field FieldProp0.field] : Object | +| D.cs:97:22:97:26 | access to field FieldProp0.field : Object | semmle.label | access to field FieldProp0.field : Object | +| D.cs:97:22:97:26 | access to field FieldProp0.field : Object | semmle.label | access to field FieldProp0.field : Object | +| D.cs:97:22:97:26 | this access : DFieldProps [field FieldProp0.field] : Object | semmle.label | this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:97:22:97:26 | this access : DFieldProps [field FieldProp0.field] : Object | semmle.label | this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:98:9:98:11 | this [Return] : DFieldProps [field FieldProp0.field] : Object | semmle.label | this [Return] : DFieldProps [field FieldProp0.field] : Object | +| D.cs:98:9:98:11 | this [Return] : DFieldProps [field FieldProp0.field] : Object | semmle.label | this [Return] : DFieldProps [field FieldProp0.field] : Object | +| D.cs:98:9:98:11 | value : Object | semmle.label | value : Object | +| D.cs:98:9:98:11 | value : Object | semmle.label | value : Object | +| D.cs:98:15:98:19 | [post] this access : DFieldProps [field FieldProp0.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:98:15:98:19 | [post] this access : DFieldProps [field FieldProp0.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:98:23:98:27 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:98:23:98:27 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:99:9:99:25 | call to method Source : Object | semmle.label | call to method Source : Object | +| D.cs:99:9:99:25 | call to method Source : Object | semmle.label | call to method Source : Object | +| D.cs:103:9:103:11 | this : DFieldProps [field FieldProp1.field] : Object | semmle.label | this : DFieldProps [field FieldProp1.field] : Object | +| D.cs:103:9:103:11 | this : DFieldProps [field FieldProp1.field] : Object | semmle.label | this : DFieldProps [field FieldProp1.field] : Object | +| D.cs:103:22:103:26 | access to field FieldProp1.field : Object | semmle.label | access to field FieldProp1.field : Object | +| D.cs:103:22:103:26 | access to field FieldProp1.field : Object | semmle.label | access to field FieldProp1.field : Object | +| D.cs:103:22:103:26 | this access : DFieldProps [field FieldProp1.field] : Object | semmle.label | this access : DFieldProps [field FieldProp1.field] : Object | +| D.cs:103:22:103:26 | this access : DFieldProps [field FieldProp1.field] : Object | semmle.label | this access : DFieldProps [field FieldProp1.field] : Object | +| D.cs:104:9:104:11 | this [Return] : DFieldProps [field FieldProp1.field] : Object | semmle.label | this [Return] : DFieldProps [field FieldProp1.field] : Object | +| D.cs:104:9:104:11 | this [Return] : DFieldProps [field FieldProp1.field] : Object | semmle.label | this [Return] : DFieldProps [field FieldProp1.field] : Object | +| D.cs:104:9:104:11 | value : Object | semmle.label | value : Object | +| D.cs:104:9:104:11 | value : Object | semmle.label | value : Object | +| D.cs:104:15:104:19 | [post] this access : DFieldProps [field FieldProp1.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp1.field] : Object | +| D.cs:104:15:104:19 | [post] this access : DFieldProps [field FieldProp1.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp1.field] : Object | +| D.cs:104:23:104:27 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:104:23:104:27 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:109:9:109:11 | this : DFieldProps [field FieldProp2.field] : Object | semmle.label | this : DFieldProps [field FieldProp2.field] : Object | +| D.cs:109:9:109:11 | this : DFieldProps [field FieldProp2.field] : Object | semmle.label | this : DFieldProps [field FieldProp2.field] : Object | +| D.cs:109:22:109:26 | access to field FieldProp2.field : Object | semmle.label | access to field FieldProp2.field : Object | +| D.cs:109:22:109:26 | access to field FieldProp2.field : Object | semmle.label | access to field FieldProp2.field : Object | +| D.cs:109:22:109:26 | this access : DFieldProps [field FieldProp2.field] : Object | semmle.label | this access : DFieldProps [field FieldProp2.field] : Object | +| D.cs:109:22:109:26 | this access : DFieldProps [field FieldProp2.field] : Object | semmle.label | this access : DFieldProps [field FieldProp2.field] : Object | +| D.cs:110:9:110:11 | this [Return] : DFieldProps [field FieldProp2.field] : Object | semmle.label | this [Return] : DFieldProps [field FieldProp2.field] : Object | +| D.cs:110:9:110:11 | this [Return] : DFieldProps [field FieldProp2.field] : Object | semmle.label | this [Return] : DFieldProps [field FieldProp2.field] : Object | +| D.cs:110:9:110:11 | value : Object | semmle.label | value : Object | +| D.cs:110:9:110:11 | value : Object | semmle.label | value : Object | +| D.cs:112:17:112:17 | access to local variable x : Object | semmle.label | access to local variable x : Object | +| D.cs:112:17:112:17 | access to local variable x : Object | semmle.label | access to local variable x : Object | +| D.cs:113:13:113:17 | [post] this access : DFieldProps [field FieldProp2.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp2.field] : Object | +| D.cs:113:13:113:17 | [post] this access : DFieldProps [field FieldProp2.field] : Object | semmle.label | [post] this access : DFieldProps [field FieldProp2.field] : Object | +| D.cs:113:21:113:21 | access to local variable x : Object | semmle.label | access to local variable x : Object | +| D.cs:113:21:113:21 | access to local variable x : Object | semmle.label | access to local variable x : Object | +| D.cs:119:22:119:26 | access to field StaticFieldProp.field : Object | semmle.label | access to field StaticFieldProp.field : Object | +| D.cs:119:22:119:26 | access to field StaticFieldProp.field : Object | semmle.label | access to field StaticFieldProp.field : Object | +| D.cs:120:9:120:11 | value : Object | semmle.label | value : Object | +| D.cs:120:9:120:11 | value : Object | semmle.label | value : Object | +| D.cs:120:23:120:27 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:120:23:120:27 | access to parameter value : Object | semmle.label | access to parameter value : Object | +| D.cs:125:13:125:14 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:125:13:125:14 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:125:18:125:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | semmle.label | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | +| D.cs:125:18:125:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | semmle.label | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | +| D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:126:14:126:26 | access to property FieldProp0 | semmle.label | access to property FieldProp0 | +| D.cs:126:14:126:26 | access to property FieldProp0 | semmle.label | access to property FieldProp0 | +| D.cs:130:13:130:14 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:130:13:130:14 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:130:18:130:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | semmle.label | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | +| D.cs:130:18:130:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | semmle.label | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | +| D.cs:131:13:131:14 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object | +| D.cs:131:13:131:14 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object | +| D.cs:131:18:131:34 | call to method Source : Object | semmle.label | call to method Source : Object | +| D.cs:131:18:131:34 | call to method Source : Object | semmle.label | call to method Source : Object | +| D.cs:132:9:132:10 | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | semmle.label | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | +| D.cs:132:9:132:10 | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | semmle.label | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | +| D.cs:132:25:132:26 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object | +| D.cs:132:25:132:26 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object | +| D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:133:14:133:26 | access to property FieldProp0 | semmle.label | access to property FieldProp0 | +| D.cs:133:14:133:26 | access to property FieldProp0 | semmle.label | access to property FieldProp0 | +| D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | semmle.label | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | +| D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | semmle.label | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | +| D.cs:134:14:134:26 | access to property FieldProp1 | semmle.label | access to property FieldProp1 | +| D.cs:134:14:134:26 | access to property FieldProp1 | semmle.label | access to property FieldProp1 | +| D.cs:137:13:137:14 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:137:13:137:14 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:137:18:137:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | semmle.label | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | +| D.cs:137:18:137:34 | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | semmle.label | object creation of type DFieldProps : DFieldProps [field FieldProp0.field] : Object | +| D.cs:138:13:138:14 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object | +| D.cs:138:13:138:14 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object | +| D.cs:138:18:138:34 | call to method Source : Object | semmle.label | call to method Source : Object | +| D.cs:138:18:138:34 | call to method Source : Object | semmle.label | call to method Source : Object | +| D.cs:139:9:139:10 | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | semmle.label | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | +| D.cs:139:9:139:10 | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | semmle.label | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | +| D.cs:139:25:139:26 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object | +| D.cs:139:25:139:26 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object | +| D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | semmle.label | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | +| D.cs:140:14:140:26 | access to property FieldProp0 | semmle.label | access to property FieldProp0 | +| D.cs:140:14:140:26 | access to property FieldProp0 | semmle.label | access to property FieldProp0 | +| D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | semmle.label | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | +| D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | semmle.label | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | +| D.cs:142:14:142:26 | access to property FieldProp2 | semmle.label | access to property FieldProp2 | +| D.cs:142:14:142:26 | access to property FieldProp2 | semmle.label | access to property FieldProp2 | +| D.cs:144:13:144:14 | access to local variable o3 : Object | semmle.label | access to local variable o3 : Object | +| D.cs:144:13:144:14 | access to local variable o3 : Object | semmle.label | access to local variable o3 : Object | +| D.cs:144:18:144:34 | call to method Source : Object | semmle.label | call to method Source : Object | +| D.cs:144:18:144:34 | call to method Source : Object | semmle.label | call to method Source : Object | +| D.cs:145:9:145:35 | access to property StaticFieldProp : Object | semmle.label | access to property StaticFieldProp : Object | +| D.cs:145:9:145:35 | access to property StaticFieldProp : Object | semmle.label | access to property StaticFieldProp : Object | +| D.cs:145:39:145:40 | access to local variable o3 : Object | semmle.label | access to local variable o3 : Object | +| D.cs:145:39:145:40 | access to local variable o3 : Object | semmle.label | access to local variable o3 : Object | +| D.cs:146:14:146:40 | access to property StaticFieldProp | semmle.label | access to property StaticFieldProp | +| D.cs:146:14:146:40 | access to property StaticFieldProp | semmle.label | access to property StaticFieldProp | | E.cs:8:29:8:29 | o : Object | semmle.label | o : Object | | E.cs:8:29:8:29 | o : Object | semmle.label | o : Object | | E.cs:11:9:11:11 | [post] access to local variable ret : S [field Field] : Object | semmle.label | [post] access to local variable ret : S [field Field] : Object | @@ -2648,6 +2874,22 @@ subpaths | D.cs:81:26:81:26 | access to local variable o : Object | D.cs:61:9:61:11 | value : Object | D.cs:61:9:61:11 | this [Return] : DPartial [field _backingField] : Object | D.cs:81:9:81:9 | [post] access to local variable d : DPartial [field _backingField] : Object | | D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | D.cs:60:22:60:34 | access to field _backingField : Object | D.cs:84:14:84:27 | access to property PartialProp1 | | D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | D.cs:60:22:60:34 | access to field _backingField : Object | D.cs:84:14:84:27 | access to property PartialProp1 | +| D.cs:99:9:99:25 | call to method Source : Object | D.cs:98:9:98:11 | value : Object | D.cs:98:9:98:11 | this [Return] : DFieldProps [field FieldProp0.field] : Object | D.cs:95:12:95:21 | [post] this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:99:9:99:25 | call to method Source : Object | D.cs:98:9:98:11 | value : Object | D.cs:98:9:98:11 | this [Return] : DFieldProps [field FieldProp0.field] : Object | D.cs:95:12:95:21 | [post] this access : DFieldProps [field FieldProp0.field] : Object | +| D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | access to field FieldProp0.field : Object | D.cs:126:14:126:26 | access to property FieldProp0 | +| D.cs:126:14:126:15 | access to local variable d0 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | access to field FieldProp0.field : Object | D.cs:126:14:126:26 | access to property FieldProp0 | +| D.cs:132:25:132:26 | access to local variable o1 : Object | D.cs:104:9:104:11 | value : Object | D.cs:104:9:104:11 | this [Return] : DFieldProps [field FieldProp1.field] : Object | D.cs:132:9:132:10 | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | +| D.cs:132:25:132:26 | access to local variable o1 : Object | D.cs:104:9:104:11 | value : Object | D.cs:104:9:104:11 | this [Return] : DFieldProps [field FieldProp1.field] : Object | D.cs:132:9:132:10 | [post] access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | +| D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | access to field FieldProp0.field : Object | D.cs:133:14:133:26 | access to property FieldProp0 | +| D.cs:133:14:133:15 | access to local variable d1 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | access to field FieldProp0.field : Object | D.cs:133:14:133:26 | access to property FieldProp0 | +| D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | D.cs:103:9:103:11 | this : DFieldProps [field FieldProp1.field] : Object | D.cs:103:22:103:26 | access to field FieldProp1.field : Object | D.cs:134:14:134:26 | access to property FieldProp1 | +| D.cs:134:14:134:15 | access to local variable d1 : DFieldProps [field FieldProp1.field] : Object | D.cs:103:9:103:11 | this : DFieldProps [field FieldProp1.field] : Object | D.cs:103:22:103:26 | access to field FieldProp1.field : Object | D.cs:134:14:134:26 | access to property FieldProp1 | +| D.cs:139:25:139:26 | access to local variable o2 : Object | D.cs:110:9:110:11 | value : Object | D.cs:110:9:110:11 | this [Return] : DFieldProps [field FieldProp2.field] : Object | D.cs:139:9:139:10 | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | +| D.cs:139:25:139:26 | access to local variable o2 : Object | D.cs:110:9:110:11 | value : Object | D.cs:110:9:110:11 | this [Return] : DFieldProps [field FieldProp2.field] : Object | D.cs:139:9:139:10 | [post] access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | +| D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | access to field FieldProp0.field : Object | D.cs:140:14:140:26 | access to property FieldProp0 | +| D.cs:140:14:140:15 | access to local variable d2 : DFieldProps [field FieldProp0.field] : Object | D.cs:97:9:97:11 | this : DFieldProps [field FieldProp0.field] : Object | D.cs:97:22:97:26 | access to field FieldProp0.field : Object | D.cs:140:14:140:26 | access to property FieldProp0 | +| D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | D.cs:109:9:109:11 | this : DFieldProps [field FieldProp2.field] : Object | D.cs:109:22:109:26 | access to field FieldProp2.field : Object | D.cs:142:14:142:26 | access to property FieldProp2 | +| D.cs:142:14:142:15 | access to local variable d2 : DFieldProps [field FieldProp2.field] : Object | D.cs:109:9:109:11 | this : DFieldProps [field FieldProp2.field] : Object | D.cs:109:22:109:26 | access to field FieldProp2.field : Object | D.cs:142:14:142:26 | access to property FieldProp2 | | E.cs:23:25:23:25 | access to local variable o : Object | E.cs:8:29:8:29 | o : Object | E.cs:12:16:12:18 | access to local variable ret : S [field Field] : Object | E.cs:23:17:23:26 | call to method CreateS : S [field Field] : Object | | E.cs:23:25:23:25 | access to local variable o : Object | E.cs:8:29:8:29 | o : Object | E.cs:12:16:12:18 | access to local variable ret : S [field Field] : Object | E.cs:23:17:23:26 | call to method CreateS : S [field Field] : Object | | E.cs:55:29:55:33 | access to local variable taint : Object | E.cs:43:46:43:46 | o : Object | E.cs:43:36:43:36 | s [Return] : RefS [field RefField] : Object | E.cs:55:23:55:26 | [post] access to local variable refs : RefS [field RefField] : Object | @@ -2758,6 +3000,18 @@ testFailures | D.cs:47:14:47:26 | access to property ComplexProp | D.cs:43:32:43:48 | call to method Source : Object | D.cs:47:14:47:26 | access to property ComplexProp | $@ | D.cs:43:32:43:48 | call to method Source : Object | call to method Source : Object | | D.cs:84:14:84:27 | access to property PartialProp1 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:84:14:84:27 | access to property PartialProp1 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | | D.cs:84:14:84:27 | access to property PartialProp1 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:84:14:84:27 | access to property PartialProp1 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | +| D.cs:126:14:126:26 | access to property FieldProp0 | D.cs:99:9:99:25 | call to method Source : Object | D.cs:126:14:126:26 | access to property FieldProp0 | $@ | D.cs:99:9:99:25 | call to method Source : Object | call to method Source : Object | +| D.cs:126:14:126:26 | access to property FieldProp0 | D.cs:99:9:99:25 | call to method Source : Object | D.cs:126:14:126:26 | access to property FieldProp0 | $@ | D.cs:99:9:99:25 | call to method Source : Object | call to method Source : Object | +| D.cs:133:14:133:26 | access to property FieldProp0 | D.cs:99:9:99:25 | call to method Source : Object | D.cs:133:14:133:26 | access to property FieldProp0 | $@ | D.cs:99:9:99:25 | call to method Source : Object | call to method Source : Object | +| D.cs:133:14:133:26 | access to property FieldProp0 | D.cs:99:9:99:25 | call to method Source : Object | D.cs:133:14:133:26 | access to property FieldProp0 | $@ | D.cs:99:9:99:25 | call to method Source : Object | call to method Source : Object | +| D.cs:134:14:134:26 | access to property FieldProp1 | D.cs:131:18:131:34 | call to method Source : Object | D.cs:134:14:134:26 | access to property FieldProp1 | $@ | D.cs:131:18:131:34 | call to method Source : Object | call to method Source : Object | +| D.cs:134:14:134:26 | access to property FieldProp1 | D.cs:131:18:131:34 | call to method Source : Object | D.cs:134:14:134:26 | access to property FieldProp1 | $@ | D.cs:131:18:131:34 | call to method Source : Object | call to method Source : Object | +| D.cs:140:14:140:26 | access to property FieldProp0 | D.cs:99:9:99:25 | call to method Source : Object | D.cs:140:14:140:26 | access to property FieldProp0 | $@ | D.cs:99:9:99:25 | call to method Source : Object | call to method Source : Object | +| D.cs:140:14:140:26 | access to property FieldProp0 | D.cs:99:9:99:25 | call to method Source : Object | D.cs:140:14:140:26 | access to property FieldProp0 | $@ | D.cs:99:9:99:25 | call to method Source : Object | call to method Source : Object | +| D.cs:142:14:142:26 | access to property FieldProp2 | D.cs:138:18:138:34 | call to method Source : Object | D.cs:142:14:142:26 | access to property FieldProp2 | $@ | D.cs:138:18:138:34 | call to method Source : Object | call to method Source : Object | +| D.cs:142:14:142:26 | access to property FieldProp2 | D.cs:138:18:138:34 | call to method Source : Object | D.cs:142:14:142:26 | access to property FieldProp2 | $@ | D.cs:138:18:138:34 | call to method Source : Object | call to method Source : Object | +| D.cs:146:14:146:40 | access to property StaticFieldProp | D.cs:144:18:144:34 | call to method Source : Object | D.cs:146:14:146:40 | access to property StaticFieldProp | $@ | D.cs:144:18:144:34 | call to method Source : Object | call to method Source : Object | +| D.cs:146:14:146:40 | access to property StaticFieldProp | D.cs:144:18:144:34 | call to method Source : Object | D.cs:146:14:146:40 | access to property StaticFieldProp | $@ | D.cs:144:18:144:34 | call to method Source : Object | call to method Source : Object | | E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:33 | call to method Source : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:33 | call to method Source : Object | call to method Source : Object | | E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:33 | call to method Source : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:33 | call to method Source : Object | call to method Source : Object | | E.cs:57:14:57:26 | access to field RefField | E.cs:54:21:54:37 | call to method Source : Object | E.cs:57:14:57:26 | access to field RefField | $@ | E.cs:54:21:54:37 | call to method Source : Object | call to method Source : Object | diff --git a/csharp/ql/test/library-tests/dispatch/CallGraph.expected b/csharp/ql/test/library-tests/dispatch/CallGraph.expected index 4eed880f0a3..2feb959dd86 100644 --- a/csharp/ql/test/library-tests/dispatch/CallGraph.expected +++ b/csharp/ql/test/library-tests/dispatch/CallGraph.expected @@ -270,7 +270,9 @@ | ViableCallable.cs:679:17:679:20 | Run3 | ViableCallable.cs:637:21:637:21 | M | | ViableCallable.cs:679:17:679:20 | Run3 | ViableCallable.cs:646:21:646:21 | M | | ViableCallable.cs:679:17:679:20 | Run3 | ViableCallable.cs:648:21:648:21 | M | -| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:702:42:702:44 | get_Property | -| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:702:63:702:65 | set_Property | -| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:704:49:704:51 | get_Item | -| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:704:70:704:72 | set_Item | +| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:703:42:703:44 | get_Property | +| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:703:63:703:65 | set_Property | +| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:705:49:705:51 | get_Item | +| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:705:70:705:72 | set_Item | +| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:706:51:706:53 | add_Event | +| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:706:59:706:64 | remove_Event | diff --git a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected index b38eed691b9..5d6b4be4f87 100644 --- a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected +++ b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected @@ -518,7 +518,9 @@ | ViableCallable.cs:683:9:683:16 | call to method M | C22+TestOverloadResolution2.M(Int32[]) | | ViableCallable.cs:687:9:687:16 | call to method M | C22+TestOverloadResolution1.M(List) | | ViableCallable.cs:687:9:687:16 | call to method M | C22+TestOverloadResolution2.M(List) | -| ViableCallable.cs:712:9:712:18 | access to property Property | C23+Partial1.set_Property(object) | -| ViableCallable.cs:715:13:715:22 | access to property Property | C23+Partial1.get_Property() | -| ViableCallable.cs:718:9:718:12 | access to indexer | C23+Partial1.set_Item(int, object) | -| ViableCallable.cs:721:13:721:16 | access to indexer | C23+Partial1.get_Item(int) | +| ViableCallable.cs:714:9:714:18 | access to property Property | C23+Partial1.set_Property(object) | +| ViableCallable.cs:717:13:717:22 | access to property Property | C23+Partial1.get_Property() | +| ViableCallable.cs:720:9:720:12 | access to indexer | C23+Partial1.set_Item(int, object) | +| ViableCallable.cs:723:13:723:16 | access to indexer | C23+Partial1.get_Item(int) | +| ViableCallable.cs:726:9:726:15 | access to event Event | C23+Partial1.add_Event(EventHandler) | +| ViableCallable.cs:729:9:729:15 | access to event Event | C23+Partial1.remove_Event(EventHandler) | diff --git a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs index 99b4ec54a99..e904eb01a86 100644 --- a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs +++ b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs @@ -695,6 +695,7 @@ public class C23 public partial object Property { get; set; } public partial object this[int index] { get; set; } + public partial event EventHandler Event; } public partial class Partial1 @@ -702,6 +703,7 @@ public class C23 public partial object Property { get { return null; } set { } } public partial object this[int index] { get { return null; } set { } } + public partial event EventHandler Event { add { } remove { } } } public void Run1(Partial1 p) @@ -719,5 +721,11 @@ public class C23 // Viable callable: Partial1.get_Item(int) o = p[0]; + + // Viable callable: Partial1.add_Event + p.Event += (sender, e) => { }; + + // Viable callable: Partial1.remove_Event + p.Event -= (sender, e) => { }; } } diff --git a/csharp/ql/test/library-tests/partial/MethodIsPartial.expected b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected index 4c0e905d8c5..a0f1f88fb98 100644 --- a/csharp/ql/test/library-tests/partial/MethodIsPartial.expected +++ b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected @@ -1,7 +1,7 @@ -| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | true | -| Partial.cs:5:17:5:23 | Method2 | false | -| Partial.cs:14:18:14:39 | PartialMethodWithBody1 | true | -| Partial.cs:15:17:15:23 | Method3 | false | -| Partial.cs:34:18:34:42 | PartialMethodWithoutBody2 | true | -| Partial.cs:35:17:35:23 | Method4 | false | -| Partial.cs:40:17:40:23 | Method5 | false | +| Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 | true | +| Partial.cs:7:17:7:23 | Method2 | false | +| Partial.cs:18:18:18:39 | PartialMethodWithBody1 | true | +| Partial.cs:19:17:19:23 | Method3 | false | +| Partial.cs:41:18:41:42 | PartialMethodWithoutBody2 | true | +| Partial.cs:42:17:42:23 | Method4 | false | +| Partial.cs:47:17:47:23 | Method5 | false | diff --git a/csharp/ql/test/library-tests/partial/Partial.cs b/csharp/ql/test/library-tests/partial/Partial.cs index 5a3e4af2e8c..8dd757fcd24 100644 --- a/csharp/ql/test/library-tests/partial/Partial.cs +++ b/csharp/ql/test/library-tests/partial/Partial.cs @@ -1,3 +1,5 @@ +using System; + partial class TwoPartClass { partial void PartialMethodWithBody1(); @@ -7,6 +9,8 @@ partial class TwoPartClass public partial object PartialProperty1 { get; set; } // Declaring declaration. public partial object this[int index] { get; set; } + // Declaring declaration. + public partial event EventHandler PartialEvent1; } partial class TwoPartClass @@ -27,6 +31,9 @@ partial class TwoPartClass get { return _backingArray[index]; } set { _backingArray[index] = value; } } + + // Implementation declaration. + public partial event EventHandler PartialEvent1 { add { } remove { } } } partial class OnePartPartialClass @@ -44,4 +51,5 @@ class NonPartialClass get { return null; } set { } } + public event EventHandler Event; } diff --git a/csharp/ql/test/library-tests/partial/Partial1.expected b/csharp/ql/test/library-tests/partial/Partial1.expected index 55dcaabcea7..fe8f5658f48 100644 --- a/csharp/ql/test/library-tests/partial/Partial1.expected +++ b/csharp/ql/test/library-tests/partial/Partial1.expected @@ -1,14 +1,17 @@ -| Partial.cs:1:15:1:26 | TwoPartClass | -| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | -| Partial.cs:12:15:12:26 | TwoPartClass | -| Partial.cs:14:18:14:39 | PartialMethodWithBody1 | -| Partial.cs:18:27:18:42 | PartialProperty1 | -| Partial.cs:20:9:20:11 | get_PartialProperty1 | -| Partial.cs:21:9:21:11 | set_PartialProperty1 | -| Partial.cs:25:27:25:30 | Item | -| Partial.cs:27:9:27:11 | get_Item | -| Partial.cs:28:9:28:11 | set_Item | -| Partial.cs:32:15:32:33 | OnePartPartialClass | -| Partial.cs:34:18:34:42 | PartialMethodWithoutBody2 | +| Partial.cs:3:15:3:26 | TwoPartClass | +| Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 | +| Partial.cs:16:15:16:26 | TwoPartClass | +| Partial.cs:18:18:18:39 | PartialMethodWithBody1 | +| Partial.cs:22:27:22:42 | PartialProperty1 | +| Partial.cs:24:9:24:11 | get_PartialProperty1 | +| Partial.cs:25:9:25:11 | set_PartialProperty1 | +| Partial.cs:29:27:29:30 | Item | +| Partial.cs:31:9:31:11 | get_Item | +| Partial.cs:32:9:32:11 | set_Item | +| Partial.cs:36:39:36:51 | PartialEvent1 | +| Partial.cs:36:55:36:57 | add_PartialEvent1 | +| Partial.cs:36:63:36:68 | remove_PartialEvent1 | +| Partial.cs:39:15:39:33 | OnePartPartialClass | +| Partial.cs:41:18:41:42 | PartialMethodWithoutBody2 | | PartialMultipleFiles1.cs:1:22:1:41 | PartialMultipleFiles | | PartialMultipleFiles2.cs:1:22:1:41 | PartialMultipleFiles | diff --git a/csharp/ql/test/library-tests/partial/Partial2.expected b/csharp/ql/test/library-tests/partial/Partial2.expected index 87194dd3f9e..8d608c26011 100644 --- a/csharp/ql/test/library-tests/partial/Partial2.expected +++ b/csharp/ql/test/library-tests/partial/Partial2.expected @@ -1,15 +1,15 @@ -| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:1:15:1:26 | | -| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | -| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 | -| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:14:18:14:39 | PartialMethodWithBody1 | -| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:15:17:15:23 | Method3 | -| Partial.cs:12:15:12:26 | TwoPartClass | Partial.cs:1:15:1:26 | | -| Partial.cs:12:15:12:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | -| Partial.cs:12:15:12:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 | -| Partial.cs:12:15:12:26 | TwoPartClass | Partial.cs:14:18:14:39 | PartialMethodWithBody1 | -| Partial.cs:12:15:12:26 | TwoPartClass | Partial.cs:15:17:15:23 | Method3 | -| Partial.cs:32:15:32:33 | OnePartPartialClass | Partial.cs:32:15:32:33 | | -| Partial.cs:32:15:32:33 | OnePartPartialClass | Partial.cs:34:18:34:42 | PartialMethodWithoutBody2 | -| Partial.cs:32:15:32:33 | OnePartPartialClass | Partial.cs:35:17:35:23 | Method4 | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:3:15:3:26 | | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:7:17:7:23 | Method2 | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:18:18:18:39 | PartialMethodWithBody1 | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:19:17:19:23 | Method3 | +| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:3:15:3:26 | | +| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 | +| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:7:17:7:23 | Method2 | +| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:18:18:18:39 | PartialMethodWithBody1 | +| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:19:17:19:23 | Method3 | +| Partial.cs:39:15:39:33 | OnePartPartialClass | Partial.cs:39:15:39:33 | | +| Partial.cs:39:15:39:33 | OnePartPartialClass | Partial.cs:41:18:41:42 | PartialMethodWithoutBody2 | +| Partial.cs:39:15:39:33 | OnePartPartialClass | Partial.cs:42:17:42:23 | Method4 | | PartialMultipleFiles1.cs:1:22:1:41 | PartialMultipleFiles | PartialMultipleFiles1.cs:1:22:1:41 | | | PartialMultipleFiles2.cs:1:22:1:41 | PartialMultipleFiles | PartialMultipleFiles1.cs:1:22:1:41 | | diff --git a/csharp/ql/test/library-tests/partial/PartialAccessors.expected b/csharp/ql/test/library-tests/partial/PartialAccessors.expected index 2c69ed620ae..a9d70645420 100644 --- a/csharp/ql/test/library-tests/partial/PartialAccessors.expected +++ b/csharp/ql/test/library-tests/partial/PartialAccessors.expected @@ -1,8 +1,12 @@ -| Partial.cs:20:9:20:11 | get_PartialProperty1 | true | -| Partial.cs:21:9:21:11 | set_PartialProperty1 | true | -| Partial.cs:27:9:27:11 | get_Item | true | -| Partial.cs:28:9:28:11 | set_Item | true | -| Partial.cs:41:30:41:32 | get_Property | false | -| Partial.cs:41:35:41:37 | set_Property | false | -| Partial.cs:44:9:44:11 | get_Item | false | -| Partial.cs:45:9:45:11 | set_Item | false | +| Partial.cs:24:9:24:11 | get_PartialProperty1 | true | +| Partial.cs:25:9:25:11 | set_PartialProperty1 | true | +| Partial.cs:31:9:31:11 | get_Item | true | +| Partial.cs:32:9:32:11 | set_Item | true | +| Partial.cs:36:55:36:57 | add_PartialEvent1 | true | +| Partial.cs:36:63:36:68 | remove_PartialEvent1 | true | +| Partial.cs:48:30:48:32 | get_Property | false | +| Partial.cs:48:35:48:37 | set_Property | false | +| Partial.cs:51:9:51:11 | get_Item | false | +| Partial.cs:52:9:52:11 | set_Item | false | +| Partial.cs:54:31:54:35 | add_Event | false | +| Partial.cs:54:31:54:35 | remove_Event | false | diff --git a/csharp/ql/test/library-tests/partial/PartialConstructors.expected b/csharp/ql/test/library-tests/partial/PartialConstructors.expected index 01779f1b81e..69cabb244f5 100644 --- a/csharp/ql/test/library-tests/partial/PartialConstructors.expected +++ b/csharp/ql/test/library-tests/partial/PartialConstructors.expected @@ -1,4 +1,4 @@ -| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:1:15:1:26 | {...} | -| Partial.cs:32:15:32:33 | OnePartPartialClass | Partial.cs:32:15:32:33 | {...} | -| Partial.cs:38:7:38:21 | NonPartialClass | Partial.cs:38:7:38:21 | {...} | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:3:15:3:26 | {...} | +| Partial.cs:39:15:39:33 | OnePartPartialClass | Partial.cs:39:15:39:33 | {...} | +| Partial.cs:45:7:45:21 | NonPartialClass | Partial.cs:45:7:45:21 | {...} | | PartialMultipleFiles1.cs:1:22:1:41 | PartialMultipleFiles | PartialMultipleFiles1.cs:1:22:1:41 | {...} | diff --git a/csharp/ql/test/library-tests/partial/PartialEvents.expected b/csharp/ql/test/library-tests/partial/PartialEvents.expected new file mode 100644 index 00000000000..b12f8a07a9d --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialEvents.expected @@ -0,0 +1,2 @@ +| Partial.cs:36:39:36:51 | PartialEvent1 | true | +| Partial.cs:54:31:54:35 | Event | false | diff --git a/csharp/ql/test/library-tests/partial/PartialEvents.ql b/csharp/ql/test/library-tests/partial/PartialEvents.ql new file mode 100644 index 00000000000..e9f45250266 --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialEvents.ql @@ -0,0 +1,7 @@ +import csharp + +private boolean isPartial(Event e) { if e.isPartial() then result = true else result = false } + +from Event e +where e.fromSource() +select e, isPartial(e) diff --git a/csharp/ql/test/library-tests/partial/PartialIndexers.expected b/csharp/ql/test/library-tests/partial/PartialIndexers.expected index 151ed5aad03..be625fc4ad5 100644 --- a/csharp/ql/test/library-tests/partial/PartialIndexers.expected +++ b/csharp/ql/test/library-tests/partial/PartialIndexers.expected @@ -1,2 +1,2 @@ -| Partial.cs:25:27:25:30 | Item | true | -| Partial.cs:42:19:42:22 | Item | false | +| Partial.cs:29:27:29:30 | Item | true | +| Partial.cs:49:19:49:22 | Item | false | diff --git a/csharp/ql/test/library-tests/partial/PartialMethodBody.expected b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected index b75a105bea0..a91a156cb62 100644 --- a/csharp/ql/test/library-tests/partial/PartialMethodBody.expected +++ b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected @@ -1,3 +1,3 @@ -| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | false | -| Partial.cs:14:18:14:39 | PartialMethodWithBody1 | true | -| Partial.cs:34:18:34:42 | PartialMethodWithoutBody2 | false | +| Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 | false | +| Partial.cs:18:18:18:39 | PartialMethodWithBody1 | true | +| Partial.cs:41:18:41:42 | PartialMethodWithoutBody2 | false | diff --git a/csharp/ql/test/library-tests/partial/PartialProperties.expected b/csharp/ql/test/library-tests/partial/PartialProperties.expected index 8d2dfc01e74..4686bbf087a 100644 --- a/csharp/ql/test/library-tests/partial/PartialProperties.expected +++ b/csharp/ql/test/library-tests/partial/PartialProperties.expected @@ -1,2 +1,2 @@ -| Partial.cs:18:27:18:42 | PartialProperty1 | true | -| Partial.cs:41:19:41:26 | Property | false | +| Partial.cs:22:27:22:42 | PartialProperty1 | true | +| Partial.cs:48:19:48:26 | Property | false | diff --git a/csharp/ql/test/library-tests/partial/PrintAst.expected b/csharp/ql/test/library-tests/partial/PrintAst.expected index 0729946b18b..315de869fb3 100644 --- a/csharp/ql/test/library-tests/partial/PrintAst.expected +++ b/csharp/ql/test/library-tests/partial/PrintAst.expected @@ -1,94 +1,112 @@ Partial.cs: -# 1| [Class] TwoPartClass -# 4| 6: [Method] PartialMethodWithoutBody1 -# 4| -1: [TypeMention] Void -# 5| 7: [Method] Method2 +# 3| [Class] TwoPartClass +# 6| 6: [Method] PartialMethodWithoutBody1 +# 6| -1: [TypeMention] Void +# 7| 7: [Method] Method2 +# 7| -1: [TypeMention] Void +# 7| 4: [BlockStmt] {...} +# 18| 8: [Method] PartialMethodWithBody1 # 5| -1: [TypeMention] Void -# 5| 4: [BlockStmt] {...} -# 14| 8: [Method] PartialMethodWithBody1 -# 3| -1: [TypeMention] Void -# 14| 4: [BlockStmt] {...} -# 15| 9: [Method] Method3 -# 15| -1: [TypeMention] Void -# 15| 4: [BlockStmt] {...} -# 16| 10: [Field] _backingField -# 16| -1: [TypeMention] object -# 18| 11: [Property] PartialProperty1 -# 7| -1: [TypeMention] object -# 18| -1: [TypeMention] object -# 20| 3: [Getter] get_PartialProperty1 -# 20| 4: [BlockStmt] {...} -# 20| 0: [ReturnStmt] return ...; -# 20| 0: [FieldAccess] access to field _backingField -# 21| 4: [Setter] set_PartialProperty1 -#-----| 2: (Parameters) -# 21| 0: [Parameter] value -# 21| 4: [BlockStmt] {...} -# 21| 0: [ExprStmt] ...; -# 21| 0: [AssignExpr] ... = ... -# 21| 0: [FieldAccess] access to field _backingField -# 21| 1: [ParameterAccess] access to parameter value -# 23| 12: [Field] _backingArray -# 23| -1: [TypeMention] Object[] -# 23| 1: [TypeMention] object -# 25| 13: [Indexer] Item +# 18| 4: [BlockStmt] {...} +# 19| 9: [Method] Method3 +# 19| -1: [TypeMention] Void +# 19| 4: [BlockStmt] {...} +# 20| 10: [Field] _backingField +# 20| -1: [TypeMention] object +# 22| 11: [Property] PartialProperty1 # 9| -1: [TypeMention] object -# 25| -1: [TypeMention] object +# 22| -1: [TypeMention] object +# 24| 3: [Getter] get_PartialProperty1 +# 24| 4: [BlockStmt] {...} +# 24| 0: [ReturnStmt] return ...; +# 24| 0: [FieldAccess] access to field _backingField +# 25| 4: [Setter] set_PartialProperty1 +#-----| 2: (Parameters) +# 25| 0: [Parameter] value +# 25| 4: [BlockStmt] {...} +# 25| 0: [ExprStmt] ...; +# 25| 0: [AssignExpr] ... = ... +# 25| 0: [FieldAccess] access to field _backingField +# 25| 1: [ParameterAccess] access to parameter value +# 27| 12: [Field] _backingArray +# 27| -1: [TypeMention] Object[] +# 27| 1: [TypeMention] object +# 29| 13: [Indexer] Item +# 11| -1: [TypeMention] object +# 29| -1: [TypeMention] object #-----| 1: (Parameters) -# 9| 0: [Parameter] index -# 9| -1: [TypeMention] int -# 25| -1: [TypeMention] int -# 27| 3: [Getter] get_Item +# 11| 0: [Parameter] index +# 11| -1: [TypeMention] int +# 29| -1: [TypeMention] int +# 31| 3: [Getter] get_Item #-----| 2: (Parameters) -# 25| 0: [Parameter] index -# 27| 4: [BlockStmt] {...} -# 27| 0: [ReturnStmt] return ...; -# 27| 0: [ArrayAccess] access to array element -# 27| -1: [FieldAccess] access to field _backingArray -# 27| 0: [ParameterAccess] access to parameter index -# 28| 4: [Setter] set_Item +# 29| 0: [Parameter] index +# 31| 4: [BlockStmt] {...} +# 31| 0: [ReturnStmt] return ...; +# 31| 0: [ArrayAccess] access to array element +# 31| -1: [FieldAccess] access to field _backingArray +# 31| 0: [ParameterAccess] access to parameter index +# 32| 4: [Setter] set_Item #-----| 2: (Parameters) -# 25| 0: [Parameter] index -# 28| 1: [Parameter] value -# 28| 4: [BlockStmt] {...} -# 28| 0: [ExprStmt] ...; -# 28| 0: [AssignExpr] ... = ... -# 28| 0: [ArrayAccess] access to array element -# 28| -1: [FieldAccess] access to field _backingArray -# 28| 0: [ParameterAccess] access to parameter index -# 28| 1: [ParameterAccess] access to parameter value -# 32| [Class] OnePartPartialClass -# 34| 6: [Method] PartialMethodWithoutBody2 -# 34| -1: [TypeMention] Void -# 35| 7: [Method] Method4 -# 35| -1: [TypeMention] Void -# 35| 4: [BlockStmt] {...} -# 38| [Class] NonPartialClass -# 40| 6: [Method] Method5 -# 40| -1: [TypeMention] Void -# 40| 4: [BlockStmt] {...} -# 41| 7: [Property] Property -# 41| -1: [TypeMention] object -# 41| 3: [Getter] get_Property -# 41| 4: [Setter] set_Property +# 29| 0: [Parameter] index +# 32| 1: [Parameter] value +# 32| 4: [BlockStmt] {...} +# 32| 0: [ExprStmt] ...; +# 32| 0: [AssignExpr] ... = ... +# 32| 0: [ArrayAccess] access to array element +# 32| -1: [FieldAccess] access to field _backingArray +# 32| 0: [ParameterAccess] access to parameter index +# 32| 1: [ParameterAccess] access to parameter value +# 36| 14: [Event] PartialEvent1 +# 13| -1: [TypeMention] EventHandler +# 36| 3: [AddEventAccessor] add_PartialEvent1 #-----| 2: (Parameters) -# 41| 0: [Parameter] value -# 42| 8: [Indexer] Item -# 42| -1: [TypeMention] object +# 36| 0: [Parameter] value +# 36| 4: [BlockStmt] {...} +# 36| 4: [RemoveEventAccessor] remove_PartialEvent1 +#-----| 2: (Parameters) +# 36| 0: [Parameter] value +# 36| 4: [BlockStmt] {...} +# 39| [Class] OnePartPartialClass +# 41| 6: [Method] PartialMethodWithoutBody2 +# 41| -1: [TypeMention] Void +# 42| 7: [Method] Method4 +# 42| -1: [TypeMention] Void +# 42| 4: [BlockStmt] {...} +# 45| [Class] NonPartialClass +# 47| 6: [Method] Method5 +# 47| -1: [TypeMention] Void +# 47| 4: [BlockStmt] {...} +# 48| 7: [Property] Property +# 48| -1: [TypeMention] object +# 48| 3: [Getter] get_Property +# 48| 4: [Setter] set_Property +#-----| 2: (Parameters) +# 48| 0: [Parameter] value +# 49| 8: [Indexer] Item +# 49| -1: [TypeMention] object #-----| 1: (Parameters) -# 42| 0: [Parameter] index -# 42| -1: [TypeMention] int -# 44| 3: [Getter] get_Item +# 49| 0: [Parameter] index +# 49| -1: [TypeMention] int +# 51| 3: [Getter] get_Item #-----| 2: (Parameters) -# 42| 0: [Parameter] index -# 44| 4: [BlockStmt] {...} -# 44| 0: [ReturnStmt] return ...; -# 44| 0: [NullLiteral] null -# 45| 4: [Setter] set_Item +# 49| 0: [Parameter] index +# 51| 4: [BlockStmt] {...} +# 51| 0: [ReturnStmt] return ...; +# 51| 0: [NullLiteral] null +# 52| 4: [Setter] set_Item #-----| 2: (Parameters) -# 42| 0: [Parameter] index -# 45| 1: [Parameter] value -# 45| 4: [BlockStmt] {...} +# 49| 0: [Parameter] index +# 52| 1: [Parameter] value +# 52| 4: [BlockStmt] {...} +# 54| 9: [Event] Event +# 54| -1: [TypeMention] EventHandler +# 54| 3: [AddEventAccessor] add_Event +#-----| 2: (Parameters) +# 54| 0: [Parameter] value +# 54| 4: [RemoveEventAccessor] remove_Event +#-----| 2: (Parameters) +# 54| 0: [Parameter] value PartialMultipleFiles1.cs: # 1| [Class] PartialMultipleFiles PartialMultipleFiles2.cs: diff --git a/csharp/ql/test/library-tests/properties/PrintAst.expected b/csharp/ql/test/library-tests/properties/PrintAst.expected index 2df3ee3f5e8..711e417558e 100644 --- a/csharp/ql/test/library-tests/properties/PrintAst.expected +++ b/csharp/ql/test/library-tests/properties/PrintAst.expected @@ -230,3 +230,19 @@ properties.cs: #-----| 2: (Parameters) # 124| 0: [Parameter] value # 124| 4: [BlockStmt] {...} +# 128| 10: [Class] UseFieldKeyword +# 130| 6: [Property] Prop +# 130| -1: [TypeMention] object +# 132| 3: [Getter] get_Prop +# 132| 4: [BlockStmt] {...} +# 132| 0: [ReturnStmt] return ...; +# 132| 0: [FieldAccess] access to field Prop.field +# 133| 4: [Setter] set_Prop +#-----| 2: (Parameters) +# 133| 0: [Parameter] value +# 133| 4: [BlockStmt] {...} +# 133| 0: [ExprStmt] ...; +# 133| 0: [AssignExpr] ... = ... +# 133| 0: [FieldAccess] access to field Prop.field +# 133| 1: [ParameterAccess] access to parameter value +# 130| 7: [Field] Prop.field diff --git a/csharp/ql/test/library-tests/properties/Properties17.expected b/csharp/ql/test/library-tests/properties/Properties17.expected index 47b563e2676..ee817a63df9 100644 --- a/csharp/ql/test/library-tests/properties/Properties17.expected +++ b/csharp/ql/test/library-tests/properties/Properties17.expected @@ -1,3 +1,4 @@ +| Prop.field | | caption | | next | | y | diff --git a/csharp/ql/test/library-tests/properties/Properties17.ql b/csharp/ql/test/library-tests/properties/Properties17.ql index ca53f5423aa..6bd668ec118 100644 --- a/csharp/ql/test/library-tests/properties/Properties17.ql +++ b/csharp/ql/test/library-tests/properties/Properties17.ql @@ -1,5 +1,5 @@ /** - * @name Test that there are no backing fields + * @name Test that there are no backing fields except for properties that use the `field` keyword in their getter or setter. */ import csharp diff --git a/csharp/ql/test/library-tests/properties/properties.cs b/csharp/ql/test/library-tests/properties/properties.cs index 57ffa7a31a5..2f88214ec75 100644 --- a/csharp/ql/test/library-tests/properties/properties.cs +++ b/csharp/ql/test/library-tests/properties/properties.cs @@ -124,4 +124,13 @@ namespace Properties set { } } } + + class UseFieldKeyword + { + public object Prop + { + get { return field; } + set { field = value; } + } + } } diff --git a/csharp/ql/test/query-tests/API Abuse/ClassDoesNotImplementEquals/NullableTest.cs b/csharp/ql/test/query-tests/API Abuse/ClassDoesNotImplementEquals/NullableTest.cs new file mode 100644 index 00000000000..a66ffbec9a0 --- /dev/null +++ b/csharp/ql/test/query-tests/API Abuse/ClassDoesNotImplementEquals/NullableTest.cs @@ -0,0 +1,86 @@ +using System; + +#nullable enable + +namespace Test +{ + class TestClass1 : IEquatable + { + private int field1; + + public bool Equals(TestClass1? param1) + { + return param1 != null && field1 == param1.field1; + } + + public override bool Equals(object? param2) + { + return param2 is TestClass1 tc && Equals(tc); + } + + public override int GetHashCode() + { + return field1; + } + } + + class TestClass2 : IEquatable + { + private int field1; + + public bool Equals(TestClass2 param1) + { + return param1 != null && field1 == param1.field1; + } + + public override bool Equals(object? param2) + { + return param2 is TestClass2 tc && Equals(tc); + } + + public override int GetHashCode() + { + return field1; + } + } + + class TestClass3 : IEquatable + { + private int field1; + + public bool Equals(TestClass3? param1) + { + return param1 != null && field1 == param1.field1; + } + + public override bool Equals(object param2) + { + return param2 is TestClass3 tc && Equals(tc); + } + + public override int GetHashCode() + { + return field1; + } + } + + class TestClass4 : IEquatable + { + private int field1; + + public bool Equals(TestClass4 param1) + { + return param1 != null && field1 == param1.field1; + } + + public override bool Equals(object param2) + { + return param2 is TestClass4 tc && Equals(tc); + } + + public override int GetHashCode() + { + return field1; + } + } +} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/API Abuse/IncorrectEqualsSignature/NullableTest.cs b/csharp/ql/test/query-tests/API Abuse/IncorrectEqualsSignature/NullableTest.cs new file mode 100644 index 00000000000..a66ffbec9a0 --- /dev/null +++ b/csharp/ql/test/query-tests/API Abuse/IncorrectEqualsSignature/NullableTest.cs @@ -0,0 +1,86 @@ +using System; + +#nullable enable + +namespace Test +{ + class TestClass1 : IEquatable + { + private int field1; + + public bool Equals(TestClass1? param1) + { + return param1 != null && field1 == param1.field1; + } + + public override bool Equals(object? param2) + { + return param2 is TestClass1 tc && Equals(tc); + } + + public override int GetHashCode() + { + return field1; + } + } + + class TestClass2 : IEquatable + { + private int field1; + + public bool Equals(TestClass2 param1) + { + return param1 != null && field1 == param1.field1; + } + + public override bool Equals(object? param2) + { + return param2 is TestClass2 tc && Equals(tc); + } + + public override int GetHashCode() + { + return field1; + } + } + + class TestClass3 : IEquatable + { + private int field1; + + public bool Equals(TestClass3? param1) + { + return param1 != null && field1 == param1.field1; + } + + public override bool Equals(object param2) + { + return param2 is TestClass3 tc && Equals(tc); + } + + public override int GetHashCode() + { + return field1; + } + } + + class TestClass4 : IEquatable + { + private int field1; + + public bool Equals(TestClass4 param1) + { + return param1 != null && field1 == param1.field1; + } + + public override bool Equals(object param2) + { + return param2 is TestClass4 tc && Equals(tc); + } + + public override int GetHashCode() + { + return field1; + } + } +} \ No newline at end of file diff --git a/docs/codeql/reusables/supported-versions-compilers.rst b/docs/codeql/reusables/supported-versions-compilers.rst index 6216bae08df..566238658f3 100644 --- a/docs/codeql/reusables/supported-versions-compilers.rst +++ b/docs/codeql/reusables/supported-versions-compilers.rst @@ -18,7 +18,7 @@ .NET 5, .NET 6, .NET 7, .NET 8, .NET 9","``.sln``, ``.slnx``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" GitHub Actions,"Not applicable",Not applicable,"``.github/workflows/*.yml``, ``.github/workflows/*.yaml``, ``**/action.yml``, ``**/action.yaml``" Go (aka Golang), "Go up to 1.26", "Go 1.11 or more recent", ``.go`` - Java,"Java 7 to 25 [6]_","javac (OpenJDK and Oracle JDK), + Java,"Java 7 to 26 [6]_","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [7]_",``.java`` Kotlin,"Kotlin 1.8.0 to 2.3.0\ *x*","kotlinc",``.kt`` @@ -36,7 +36,7 @@ .. [3] Objective-C, Objective-C++, C++/CLI, and C++/CX are not supported. .. [4] Support for the clang-cl compiler is preliminary. .. [5] Support for the Arm Compiler (armcc) is preliminary. - .. [6] Builds that execute on Java 7 to 25 can be analyzed. The analysis understands standard language features in Java 8 to 25; "preview" and "incubator" features are not supported. Source code using Java language versions older than Java 8 are analyzed as Java 8 code. + .. [6] Builds that execute on Java 7 to 26 can be analyzed. The analysis understands standard language features in Java 8 to 26; "preview" and "incubator" features are not supported. Source code using Java language versions older than Java 8 are analyzed as Java 8 code. .. [7] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. .. [8] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. .. [9] The extractor requires Python 3 to run. To analyze Python 2.7 you should install both versions of Python. diff --git a/go/ql/consistency-queries/CHANGELOG.md b/go/ql/consistency-queries/CHANGELOG.md index d0c8171cdf6..e91058f491a 100644 --- a/go/ql/consistency-queries/CHANGELOG.md +++ b/go/ql/consistency-queries/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/go/ql/consistency-queries/change-notes/released/1.0.42.md b/go/ql/consistency-queries/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/go/ql/consistency-queries/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/go/ql/consistency-queries/codeql-pack.release.yml b/go/ql/consistency-queries/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/go/ql/consistency-queries/codeql-pack.release.yml +++ b/go/ql/consistency-queries/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/go/ql/consistency-queries/qlpack.yml b/go/ql/consistency-queries/qlpack.yml index 9db7c50224d..6f9302c9ac4 100644 --- a/go/ql/consistency-queries/qlpack.yml +++ b/go/ql/consistency-queries/qlpack.yml @@ -1,5 +1,5 @@ name: codeql-go-consistency-queries -version: 1.0.42-dev +version: 1.0.43-dev groups: - go - queries diff --git a/go/ql/lib/CHANGELOG.md b/go/ql/lib/CHANGELOG.md index 126058537ce..34751dc5d8a 100644 --- a/go/ql/lib/CHANGELOG.md +++ b/go/ql/lib/CHANGELOG.md @@ -1,3 +1,13 @@ +## 7.0.0 + +### Breaking Changes + +* The `BasicBlock` class is now defined using the shared basic blocks library. `BasicBlock.getRoot` has been replaced by `BasicBlock.getScope`. `BasicBlock.getAPredecessor` and `BasicBlock.getASuccessor` now take a `SuccessorType` argument. `ReachableJoinBlock.inDominanceFrontierOf` has been removed, so use `BasicBlock.inDominanceFrontier` instead, swapping the receiver and the argument. + +### Major Analysis Improvements + +* Go 1.26 is now supported. + ## 6.0.1 ### Minor Analysis Improvements diff --git a/go/ql/lib/change-notes/2026-01-20-go-version-1-26.md b/go/ql/lib/change-notes/2026-01-20-go-version-1-26.md deleted file mode 100644 index 97f022480c4..00000000000 --- a/go/ql/lib/change-notes/2026-01-20-go-version-1-26.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: majorAnalysis ---- -* Go 1.26 is now supported. diff --git a/go/ql/lib/change-notes/2026-01-28-shared-basic-block-library.md b/go/ql/lib/change-notes/released/7.0.0.md similarity index 80% rename from go/ql/lib/change-notes/2026-01-28-shared-basic-block-library.md rename to go/ql/lib/change-notes/released/7.0.0.md index f26aeb9c07a..602f9f36e35 100644 --- a/go/ql/lib/change-notes/2026-01-28-shared-basic-block-library.md +++ b/go/ql/lib/change-notes/released/7.0.0.md @@ -1,4 +1,9 @@ ---- -category: breaking ---- +## 7.0.0 + +### Breaking Changes + * The `BasicBlock` class is now defined using the shared basic blocks library. `BasicBlock.getRoot` has been replaced by `BasicBlock.getScope`. `BasicBlock.getAPredecessor` and `BasicBlock.getASuccessor` now take a `SuccessorType` argument. `ReachableJoinBlock.inDominanceFrontierOf` has been removed, so use `BasicBlock.inDominanceFrontier` instead, swapping the receiver and the argument. + +### Major Analysis Improvements + +* Go 1.26 is now supported. diff --git a/go/ql/lib/codeql-pack.release.yml b/go/ql/lib/codeql-pack.release.yml index d1f3c68c812..e0db21c7869 100644 --- a/go/ql/lib/codeql-pack.release.yml +++ b/go/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 6.0.1 +lastReleaseVersion: 7.0.0 diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index 758bb94451c..ac5f63a29bc 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 6.0.2-dev +version: 7.0.1-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/src/CHANGELOG.md b/go/ql/src/CHANGELOG.md index f2475a92207..95f203839c5 100644 --- a/go/ql/src/CHANGELOG.md +++ b/go/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.5.6 + +No user-facing changes. + ## 1.5.5 No user-facing changes. diff --git a/go/ql/src/change-notes/released/1.5.6.md b/go/ql/src/change-notes/released/1.5.6.md new file mode 100644 index 00000000000..17fb577dc9e --- /dev/null +++ b/go/ql/src/change-notes/released/1.5.6.md @@ -0,0 +1,3 @@ +## 1.5.6 + +No user-facing changes. diff --git a/go/ql/src/codeql-pack.release.yml b/go/ql/src/codeql-pack.release.yml index 1c73e9d9ce9..9a0b3c9461b 100644 --- a/go/ql/src/codeql-pack.release.yml +++ b/go/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.5.5 +lastReleaseVersion: 1.5.6 diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index cb2e964d440..bbac3ffc212 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 1.5.6-dev +version: 1.5.7-dev groups: - go - queries diff --git a/java/ql/lib/CHANGELOG.md b/java/ql/lib/CHANGELOG.md index f238699b4e5..fb2908a561e 100644 --- a/java/ql/lib/CHANGELOG.md +++ b/java/ql/lib/CHANGELOG.md @@ -1,3 +1,24 @@ +## 8.1.0 + +### Deprecated APIs + +* The `UnreachableBlocks.qll` library has been deprecated. +* Renamed the following predicates to increase uniformity across languages. The `getBody` predicate already existed on `LoopStmt`, but is now properly inherited. + - `UnaryExpr.getExpr` to `getOperand`. + - `ConditionalExpr.getTrueExpr` to `getThen`. + - `ConditionalExpr.getFalseExpr` to `getElse`. + - `ReturnStmt.getResult` to `getExpr`. + - `WhileStmt.getStmt` to `getBody`. + - `DoStmt.getStmt` to `getBody`. + - `ForStmt.getStmt` to `getBody`. + - `EnhancedForStmt.getStmt` to `getBody`. + +### Minor Analysis Improvements + +* Using a regular expression to check that a string doesn't contain any line breaks is already a sanitizer for `java/log-injection`. Additional ways of doing the regular expression check are now recognised, including annotation with `@javax.validation.constraints.Pattern`. +* More ways of checking that a string matches a regular expression are now considered as sanitizers for various queries, including `java/ssrf` and `java/path-injection`. In particular, being annotated with `@javax.validation.constraints.Pattern` is now recognised as a sanitizer for those queries. +* Kotlin versions up to 2.3.10 are now supported. + ## 8.0.0 ### Breaking Changes @@ -6,7 +27,7 @@ ### New Features -* Kotlin versions up to 2.3.0*x* are now supported. +* Kotlin versions up to 2.3.0 are now supported. ### Minor Analysis Improvements diff --git a/java/ql/lib/change-notes/2026-02-04-renames.md b/java/ql/lib/change-notes/2026-02-04-renames.md deleted file mode 100644 index 9392bcbb4f6..00000000000 --- a/java/ql/lib/change-notes/2026-02-04-renames.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -category: deprecated ---- -* Renamed the following predicates to increase uniformity across languages. The `getBody` predicate already existed on `LoopStmt`, but is now properly inherited. - - `UnaryExpr.getExpr` to `getOperand`. - - `ConditionalExpr.getTrueExpr` to `getThen`. - - `ConditionalExpr.getFalseExpr` to `getElse`. - - `ReturnStmt.getResult` to `getExpr`. - - `WhileStmt.getStmt` to `getBody`. - - `DoStmt.getStmt` to `getBody`. - - `ForStmt.getStmt` to `getBody`. - - `EnhancedForStmt.getStmt` to `getBody`. diff --git a/java/ql/lib/change-notes/2026-02-06-kotlin-2.3.10.md b/java/ql/lib/change-notes/2026-02-06-kotlin-2.3.10.md deleted file mode 100644 index 49b62ea6bbd..00000000000 --- a/java/ql/lib/change-notes/2026-02-06-kotlin-2.3.10.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Kotlin versions up to 2.3.10 are now supported. diff --git a/java/ql/lib/change-notes/2026-02-12-deprecate-unreachableblocks.md b/java/ql/lib/change-notes/2026-02-12-deprecate-unreachableblocks.md deleted file mode 100644 index 24748cbb09e..00000000000 --- a/java/ql/lib/change-notes/2026-02-12-deprecate-unreachableblocks.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: deprecated ---- -* The `UnreachableBlocks.qll` library has been deprecated. diff --git a/java/ql/lib/change-notes/2026-02-12-jakarta.md b/java/ql/lib/change-notes/2026-02-12-jakarta.md new file mode 100644 index 00000000000..062e202cb8a --- /dev/null +++ b/java/ql/lib/change-notes/2026-02-12-jakarta.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Some modelling which previously only worked for Java EE packages beginning with "javax" will now also work for Java EE packages beginning with "jakarta" as well. This may lead to some alert changes. diff --git a/java/ql/lib/change-notes/released/8.1.0.md b/java/ql/lib/change-notes/released/8.1.0.md new file mode 100644 index 00000000000..e560747144d --- /dev/null +++ b/java/ql/lib/change-notes/released/8.1.0.md @@ -0,0 +1,20 @@ +## 8.1.0 + +### Deprecated APIs + +* The `UnreachableBlocks.qll` library has been deprecated. +* Renamed the following predicates to increase uniformity across languages. The `getBody` predicate already existed on `LoopStmt`, but is now properly inherited. + - `UnaryExpr.getExpr` to `getOperand`. + - `ConditionalExpr.getTrueExpr` to `getThen`. + - `ConditionalExpr.getFalseExpr` to `getElse`. + - `ReturnStmt.getResult` to `getExpr`. + - `WhileStmt.getStmt` to `getBody`. + - `DoStmt.getStmt` to `getBody`. + - `ForStmt.getStmt` to `getBody`. + - `EnhancedForStmt.getStmt` to `getBody`. + +### Minor Analysis Improvements + +* Using a regular expression to check that a string doesn't contain any line breaks is already a sanitizer for `java/log-injection`. Additional ways of doing the regular expression check are now recognised, including annotation with `@javax.validation.constraints.Pattern`. +* More ways of checking that a string matches a regular expression are now considered as sanitizers for various queries, including `java/ssrf` and `java/path-injection`. In particular, being annotated with `@javax.validation.constraints.Pattern` is now recognised as a sanitizer for those queries. +* Kotlin versions up to 2.3.10 are now supported. diff --git a/java/ql/lib/codeql-pack.release.yml b/java/ql/lib/codeql-pack.release.yml index 0f48687270d..59984961848 100644 --- a/java/ql/lib/codeql-pack.release.yml +++ b/java/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 8.0.0 +lastReleaseVersion: 8.1.0 diff --git a/java/ql/lib/experimental/quantum/JCA.qll b/java/ql/lib/experimental/quantum/JCA.qll index b1b536a3ccb..feac5aaf0ea 100644 --- a/java/ql/lib/experimental/quantum/JCA.qll +++ b/java/ql/lib/experimental/quantum/JCA.qll @@ -295,7 +295,7 @@ module JCAModel { class CipherGetInstanceCall extends MethodCall { CipherGetInstanceCall() { - this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") + this.getCallee().hasQualifiedName(javaxOrJakarta() + ".crypto", "Cipher", "getInstance") } Expr getAlgorithmArg() { result = this.getArgument(0) } @@ -307,7 +307,8 @@ module JCAModel { private class CipherOperationCall extends MethodCall { CipherOperationCall() { this.getMethod() - .hasQualifiedName("javax.crypto", "Cipher", ["update", "doFinal", "wrap", "unwrap"]) + .hasQualifiedName(javaxOrJakarta() + ".crypto", "Cipher", + ["update", "doFinal", "wrap", "unwrap"]) } predicate isIntermediate() { this.getMethod().getName() = "update" } @@ -474,7 +475,9 @@ module JCAModel { * An access to the `javax.crypto.Cipher` class. */ private class CipherAccess extends TypeAccess { - CipherAccess() { this.getType().(Class).hasQualifiedName("javax.crypto", "Cipher") } + CipherAccess() { + this.getType().(Class).hasQualifiedName(javaxOrJakarta() + ".crypto", "Cipher") + } } /** @@ -708,7 +711,9 @@ module JCAModel { // and through setter methods class IvParameterSpecInstance extends NonceParameterInstantiation { IvParameterSpecInstance() { - super.getConstructedType().hasQualifiedName("javax.crypto.spec", "IvParameterSpec") + super + .getConstructedType() + .hasQualifiedName(javaxOrJakarta() + ".crypto.spec", "IvParameterSpec") } override DataFlow::Node getInputNode() { result.asExpr() = super.getArgument(0) } @@ -717,7 +722,9 @@ module JCAModel { // TODO: this also specifies the tag length for GCM class GCMParameterSpecInstance extends NonceParameterInstantiation { GCMParameterSpecInstance() { - super.getConstructedType().hasQualifiedName("javax.crypto.spec", "GCMParameterSpec") + super + .getConstructedType() + .hasQualifiedName(javaxOrJakarta() + ".crypto.spec", "GCMParameterSpec") } override DataFlow::Node getInputNode() { result.asExpr() = super.getArgument(1) } @@ -725,7 +732,8 @@ module JCAModel { class IvParameterSpecGetIvCall extends MethodCall { IvParameterSpecGetIvCall() { - this.getMethod().hasQualifiedName("javax.crypto.spec", "IvParameterSpec", "getIV") + this.getMethod() + .hasQualifiedName(javaxOrJakarta() + ".crypto.spec", "IvParameterSpec", "getIV") } } @@ -797,7 +805,9 @@ module JCAModel { } class CipherInitCall extends MethodCall { - CipherInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "init") } + CipherInitCall() { + this.getCallee().hasQualifiedName(javaxOrJakarta() + ".crypto", "Cipher", "init") + } /** * Returns the mode argument to the `init` method @@ -966,7 +976,9 @@ module JCAModel { class DHGenParameterSpecInstance extends KeyGeneratorParameterSpecClassInstanceExpr { DHGenParameterSpecInstance() { - super.getConstructedType().hasQualifiedName("javax.crypto.spec", "DHGenParameterSpec") + super + .getConstructedType() + .hasQualifiedName(javaxOrJakarta() + ".crypto.spec", "DHGenParameterSpec") } Expr getPrimeSizeArg() { result = this.getArgument(0) } @@ -1067,7 +1079,7 @@ module JCAModel { //TODO: Link getAlgorithm from KeyPairGenerator to algorithm instances or AVCs? High priority. class KeyGeneratorGetInstanceCall extends MethodCall { KeyGeneratorGetInstanceCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") + this.getCallee().hasQualifiedName(javaxOrJakarta() + ".crypto", "KeyGenerator", "getInstance") or this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") } @@ -1082,7 +1094,8 @@ module JCAModel { this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "initialize") and keyType = Crypto::TAsymmetricKeyType() or - this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", ["init", "initialize"]) and + this.getCallee() + .hasQualifiedName(javaxOrJakarta() + ".crypto", "KeyGenerator", ["init", "initialize"]) and keyType = Crypto::TSymmetricKeyType() } @@ -1111,7 +1124,7 @@ module JCAModel { Crypto::KeyArtifactType type; KeyGeneratorGenerateCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "generateKey") and + this.getCallee().hasQualifiedName(javaxOrJakarta() + ".crypto", "KeyGenerator", "generateKey") and type instanceof Crypto::TSymmetricKeyType or this.getCallee() @@ -1176,7 +1189,7 @@ module JCAModel { class KeySpecInstantiation extends ClassInstanceExpr { KeySpecInstantiation() { this.getConstructedType() - .hasQualifiedName("javax.crypto.spec", + .hasQualifiedName(javaxOrJakarta() + ".crypto.spec", ["PBEKeySpec", "SecretKeySpec", "PBEKeySpec", "DESedeKeySpec"]) } @@ -1227,7 +1240,8 @@ module JCAModel { class SecretKeyFactoryGetInstanceCall extends MethodCall { SecretKeyFactoryGetInstanceCall() { - this.getCallee().hasQualifiedName("javax.crypto", "SecretKeyFactory", "getInstance") + this.getCallee() + .hasQualifiedName(javaxOrJakarta() + ".crypto", "SecretKeyFactory", "getInstance") } Expr getAlgorithmArg() { result = this.getArgument(0) } @@ -1235,7 +1249,8 @@ module JCAModel { class SecretKeyFactoryGenerateSecretCall extends MethodCall { SecretKeyFactoryGenerateSecretCall() { - this.getCallee().hasQualifiedName("javax.crypto", "SecretKeyFactory", "generateSecret") + this.getCallee() + .hasQualifiedName(javaxOrJakarta() + ".crypto", "SecretKeyFactory", "generateSecret") } Expr getKeySpecArg() { result = this.getArgument(0) } @@ -1430,7 +1445,7 @@ module JCAModel { class KeyAgreementInitCall extends MethodCall { KeyAgreementInitCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "init") + this.getCallee().hasQualifiedName(javaxOrJakarta() + ".crypto", "KeyAgreement", "init") } Expr getServerKeyArg() { result = this.getArgument(0) } @@ -1438,7 +1453,7 @@ module JCAModel { class KeyAgreementGetInstanceCall extends MethodCall { KeyAgreementGetInstanceCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "getInstance") + this.getCallee().hasQualifiedName(javaxOrJakarta() + ".crypto", "KeyAgreement", "getInstance") } Expr getAlgorithmArg() { result = super.getArgument(0) } @@ -1482,7 +1497,8 @@ module JCAModel { class KeyAgreementCall extends MethodCall { KeyAgreementCall() { this.getCallee() - .hasQualifiedName("javax.crypto", "KeyAgreement", ["generateSecret", "doPhase"]) + .hasQualifiedName(javaxOrJakarta() + ".crypto", "KeyAgreement", + ["generateSecret", "doPhase"]) } predicate isIntermediate() { this.getCallee().getName() = "doPhase" } @@ -1647,7 +1663,9 @@ module JCAModel { } class MacGetInstanceCall extends MethodCall { - MacGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Mac", "getInstance") } + MacGetInstanceCall() { + this.getCallee().hasQualifiedName(javaxOrJakarta() + ".crypto", "Mac", "getInstance") + } Expr getAlgorithmArg() { result = this.getArgument(0) } @@ -1663,7 +1681,7 @@ module JCAModel { } class MacInitCall extends MethodCall { - MacInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Mac", "init") } + MacInitCall() { this.getCallee().hasQualifiedName(javaxOrJakarta() + ".crypto", "Mac", "init") } Expr getKeyArg() { result = this.getArgument(0) and this.getMethod().getParameterType(0).hasName("Key") @@ -1691,7 +1709,7 @@ module JCAModel { Expr output; MacOperationCall() { - super.getMethod().getDeclaringType().hasQualifiedName("javax.crypto", "Mac") and + super.getMethod().getDeclaringType().hasQualifiedName(javaxOrJakarta() + ".crypto", "Mac") and ( super.getMethod().hasStringSignature(["doFinal()", "doFinal(byte[])"]) and this = output or diff --git a/java/ql/lib/java.qll b/java/ql/lib/java.qll index 9644343e93b..7d0f0b7546d 100644 --- a/java/ql/lib/java.qll +++ b/java/ql/lib/java.qll @@ -9,6 +9,7 @@ import semmle.code.Unit import semmle.code.java.Annotation import semmle.code.java.Compilation import semmle.code.java.CompilationUnit +import semmle.code.java.Concepts import semmle.code.java.ControlFlowGraph import semmle.code.java.Dependency import semmle.code.java.Element diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index 177711350d5..a1737f2d1cb 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 8.0.1-dev +version: 8.1.1-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/lib/semmle/code/java/Concepts.qll b/java/ql/lib/semmle/code/java/Concepts.qll new file mode 100644 index 00000000000..7ed61223ea8 --- /dev/null +++ b/java/ql/lib/semmle/code/java/Concepts.qll @@ -0,0 +1,75 @@ +/** + * Provides abstract classes representing generic concepts such as file system + * access or system command execution, for which individual framework libraries + * provide concrete subclasses. + */ +overlay[local?] +module; + +import java + +/** + * A module importing the frameworks that implement `RegexMatch`es, + * ensuring that they are visible to the concepts library. + */ +private module Frameworks { + private import semmle.code.java.JDK + private import semmle.code.java.frameworks.JavaxAnnotations +} + +/** + * An expression that represents a regular expression match. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `RegexMatch::Range` instead. + * + * These are either method calls, which return `true` when there is a match, or + * annotations, which are considered to match if they are present. + */ +class RegexMatch extends Expr instanceof RegexMatch::Range { + /** Gets the expression for the regex being executed by this node. */ + Expr getRegex() { result = super.getRegex() } + + /** Gets an expression for the string to be searched or matched against. */ + Expr getString() { result = super.getString() } + + /** Gets an expression to be sanitized. */ + Expr getASanitizedExpr() { result = [this.getString(), super.getAdditionalSanitizedExpr()] } + + /** + * Gets the name of this regex match, typically the name of an executing + * method. This is used for nice alert messages and should include the + * type-qualified name if possible. + */ + string getName() { result = super.getName() } +} + +/** Provides classes for modeling regular-expression execution APIs. */ +module RegexMatch { + /** + * An expression that executes a regular expression. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `RegexMatch` instead. + * + * These are either method calls, which return `true` when there is a match, or + * annotations, which are considered to match if they are present. + */ + abstract class Range extends Expr { + /** Gets the expression for the regex being executed by this node. */ + abstract Expr getRegex(); + + /** Gets an expression for the string to be searched or matched against. */ + abstract Expr getString(); + + /** Gets an additional expression to be sanitized, if any. */ + Expr getAdditionalSanitizedExpr() { none() } + + /** + * Gets the name of this regex match, typically the name of an executing + * method. This is used for nice alert messages and should include the + * type-qualified name if possible. + */ + abstract string getName(); + } +} diff --git a/java/ql/lib/semmle/code/java/J2EE.qll b/java/ql/lib/semmle/code/java/J2EE.qll index 4412b3715e3..4cfffcdfa9f 100644 --- a/java/ql/lib/semmle/code/java/J2EE.qll +++ b/java/ql/lib/semmle/code/java/J2EE.qll @@ -6,52 +6,67 @@ module; import Type +/** Gets "java" or "jakarta". */ +string javaxOrJakarta() { result = ["javax", "jakarta"] } + /** An entity bean. */ class EntityBean extends Class { EntityBean() { - exists(Interface i | i.hasQualifiedName("javax.ejb", "EntityBean") | this.hasSupertype+(i)) + exists(Interface i | i.hasQualifiedName(javaxOrJakarta() + ".ejb", "EntityBean") | + this.hasSupertype+(i) + ) } } /** An enterprise bean. */ class EnterpriseBean extends RefType { EnterpriseBean() { - exists(Interface i | i.hasQualifiedName("javax.ejb", "EnterpriseBean") | this.hasSupertype+(i)) + exists(Interface i | i.hasQualifiedName(javaxOrJakarta() + ".ejb", "EnterpriseBean") | + this.hasSupertype+(i) + ) } } /** A local EJB home interface. */ class LocalEjbHomeInterface extends Interface { LocalEjbHomeInterface() { - exists(Interface i | i.hasQualifiedName("javax.ejb", "EJBLocalHome") | this.hasSupertype+(i)) + exists(Interface i | i.hasQualifiedName(javaxOrJakarta() + ".ejb", "EJBLocalHome") | + this.hasSupertype+(i) + ) } } /** A remote EJB home interface. */ class RemoteEjbHomeInterface extends Interface { RemoteEjbHomeInterface() { - exists(Interface i | i.hasQualifiedName("javax.ejb", "EJBHome") | this.hasSupertype+(i)) + exists(Interface i | i.hasQualifiedName(javaxOrJakarta() + ".ejb", "EJBHome") | + this.hasSupertype+(i) + ) } } /** A local EJB interface. */ class LocalEjbInterface extends Interface { LocalEjbInterface() { - exists(Interface i | i.hasQualifiedName("javax.ejb", "EJBLocalObject") | this.hasSupertype+(i)) + exists(Interface i | i.hasQualifiedName(javaxOrJakarta() + ".ejb", "EJBLocalObject") | + this.hasSupertype+(i) + ) } } /** A remote EJB interface. */ class RemoteEjbInterface extends Interface { RemoteEjbInterface() { - exists(Interface i | i.hasQualifiedName("javax.ejb", "EJBObject") | this.hasSupertype+(i)) + exists(Interface i | i.hasQualifiedName(javaxOrJakarta() + ".ejb", "EJBObject") | + this.hasSupertype+(i) + ) } } /** A message bean. */ class MessageBean extends Class { MessageBean() { - exists(Interface i | i.hasQualifiedName("javax.ejb", "MessageDrivenBean") | + exists(Interface i | i.hasQualifiedName(javaxOrJakarta() + ".ejb", "MessageDrivenBean") | this.hasSupertype+(i) ) } @@ -60,6 +75,8 @@ class MessageBean extends Class { /** A session bean. */ class SessionBean extends Class { SessionBean() { - exists(Interface i | i.hasQualifiedName("javax.ejb", "SessionBean") | this.hasSupertype+(i)) + exists(Interface i | i.hasQualifiedName(javaxOrJakarta() + ".ejb", "SessionBean") | + this.hasSupertype+(i) + ) } } diff --git a/java/ql/lib/semmle/code/java/JDK.qll b/java/ql/lib/semmle/code/java/JDK.qll index f965fbfe6ba..93562c7c3d8 100644 --- a/java/ql/lib/semmle/code/java/JDK.qll +++ b/java/ql/lib/semmle/code/java/JDK.qll @@ -48,13 +48,19 @@ class StringContainsMethod extends Method { } /** A call to the `java.lang.String.matches` method. */ -class StringMatchesCall extends MethodCall { +class StringMatchesCall extends MethodCall, RegexMatch::Range { StringMatchesCall() { exists(Method m | m = this.getMethod() | m.getDeclaringType() instanceof TypeString and m.hasName("matches") ) } + + override Expr getRegex() { result = this.getArgument(0) } + + override Expr getString() { result = this.getQualifier() } + + override string getName() { result = "String.matches" } } /** A call to the `java.lang.String.replaceAll` method. */ diff --git a/java/ql/lib/semmle/code/java/JMX.qll b/java/ql/lib/semmle/code/java/JMX.qll index 3f18e0ecf3d..a951b2a7d1a 100644 --- a/java/ql/lib/semmle/code/java/JMX.qll +++ b/java/ql/lib/semmle/code/java/JMX.qll @@ -18,7 +18,7 @@ class MBean extends ManagedBean { class MXBean extends ManagedBean { MXBean() { this.getQualifiedName().matches("%MXBean%") or - this.getAnAnnotation().getType().hasQualifiedName("javax.management", "MXBean") + this.getAnAnnotation().getType().hasQualifiedName(javaxOrJakarta() + ".management", "MXBean") } } @@ -61,7 +61,7 @@ class JmxRegistrationCall extends MethodCall { class JmxRegistrationMethod extends Method { JmxRegistrationMethod() { // A direct registration with the `MBeanServer`. - this.getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and + this.getDeclaringType().hasQualifiedName(javaxOrJakarta() + ".management", "MBeanServer") and this.getName() = "registerMBean" or // The `MBeanServer` is often wrapped by an application specific management class, so identify @@ -78,7 +78,7 @@ class JmxRegistrationMethod extends Method { */ int getObjectPosition() { // Passed as the first argument to `registerMBean`. - this.getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and + this.getDeclaringType().hasQualifiedName(javaxOrJakarta() + ".management", "MBeanServer") and this.getName() = "registerMBean" and result = 0 or @@ -92,16 +92,20 @@ class JmxRegistrationMethod extends Method { /** The class `javax.management.remote.JMXConnectorFactory`. */ class TypeJmxConnectorFactory extends Class { TypeJmxConnectorFactory() { - this.hasQualifiedName("javax.management.remote", "JMXConnectorFactory") + this.hasQualifiedName(javaxOrJakarta() + ".management.remote", "JMXConnectorFactory") } } /** The class `javax.management.remote.JMXServiceURL`. */ class TypeJmxServiceUrl extends Class { - TypeJmxServiceUrl() { this.hasQualifiedName("javax.management.remote", "JMXServiceURL") } + TypeJmxServiceUrl() { + this.hasQualifiedName(javaxOrJakarta() + ".management.remote", "JMXServiceURL") + } } /** The class `javax.management.remote.rmi.RMIConnector`. */ class TypeRmiConnector extends Class { - TypeRmiConnector() { this.hasQualifiedName("javax.management.remote.rmi", "RMIConnector") } + TypeRmiConnector() { + this.hasQualifiedName(javaxOrJakarta() + ".management.remote.rmi", "RMIConnector") + } } diff --git a/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll index ec8ad6e2d4f..26444920a7e 100644 --- a/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll @@ -316,7 +316,7 @@ class FacesComponentReflectivelyConstructedClass extends ReflectivelyConstructed * Entry point for EJB home interfaces. */ class EjbHome extends Interface, EntryPoint { - EjbHome() { this.getAnAncestor().hasQualifiedName("javax.ejb", "EJBHome") } + EjbHome() { this.getAnAncestor().hasQualifiedName(javaxOrJakarta() + ".ejb", "EJBHome") } override Callable getALiveCallable() { result = this.getACallable() } } @@ -325,7 +325,7 @@ class EjbHome extends Interface, EntryPoint { * Entry point for EJB object interfaces. */ class EjbObject extends Interface, EntryPoint { - EjbObject() { this.getAnAncestor().hasQualifiedName("javax.ejb", "EJBObject") } + EjbObject() { this.getAnAncestor().hasQualifiedName(javaxOrJakarta() + ".ejb", "EJBObject") } override Callable getALiveCallable() { result = this.getACallable() } } @@ -341,7 +341,9 @@ class GsonDeserializationEntryPoint extends ReflectivelyConstructedClass { class JaxbDeserializationEntryPoint extends ReflectivelyConstructedClass { JaxbDeserializationEntryPoint() { // A class can be deserialized by JAXB if it's an `XmlRootElement`... - this.getAnAnnotation().getType().hasQualifiedName("javax.xml.bind.annotation", "XmlRootElement") + this.getAnAnnotation() + .getType() + .hasQualifiedName(javaxOrJakarta() + ".xml.bind.annotation", "XmlRootElement") or // ... or the type of an `XmlElement` field. exists(Field elementField | diff --git a/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll index df9ef0a7b7c..63b142ae3ad 100644 --- a/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll @@ -45,7 +45,7 @@ class ServletListenerClass extends ReflectivelyConstructedClass { */ class ServletFilterClass extends ReflectivelyConstructedClass { ServletFilterClass() { - this.getAnAncestor().hasQualifiedName("javax.servlet", "Filter") and + this.getAnAncestor().hasQualifiedName(javaxOrJakarta() + ".servlet", "Filter") and // If we have seen any `web.xml` files, this filter will be considered to be live only if it is // referred to as a filter-class in at least one. If no `web.xml` files are found, we assume // that XML extraction was not enabled, and therefore consider all filter classes as live. diff --git a/java/ql/lib/semmle/code/java/frameworks/JAXB.qll b/java/ql/lib/semmle/code/java/frameworks/JAXB.qll index 1283aa3d21e..c781abdb828 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JAXB.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JAXB.qll @@ -6,20 +6,20 @@ import semmle.code.java.Type class JaxbElement extends Class { JaxbElement() { - this.getAnAncestor().hasQualifiedName("javax.xml.bind", "JAXBElement") or + this.getAnAncestor().hasQualifiedName(javaxOrJakarta() + ".xml.bind", "JAXBElement") or this.getAnAnnotation().getType().getName() = "XmlRootElement" } } class JaxbMarshalMethod extends Method { JaxbMarshalMethod() { - this.getDeclaringType().hasQualifiedName("javax.xml.bind", "Marshaller") and + this.getDeclaringType().hasQualifiedName(javaxOrJakarta() + ".xml.bind", "Marshaller") and this.getName() = "marshal" } } class JaxbAnnotationType extends AnnotationType { - JaxbAnnotationType() { this.getPackage().getName() = "javax.xml.bind.annotation" } + JaxbAnnotationType() { this.getPackage().getName() = javaxOrJakarta() + ".xml.bind.annotation" } } class JaxbAnnotated extends Annotatable { diff --git a/java/ql/lib/semmle/code/java/frameworks/JavaxAnnotations.qll b/java/ql/lib/semmle/code/java/frameworks/JavaxAnnotations.qll index 22f33d346df..3b70c42fbec 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JavaxAnnotations.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JavaxAnnotations.qll @@ -14,35 +14,45 @@ import java * A `@javax.annotation.Generated` annotation. */ class GeneratedAnnotation extends Annotation { - GeneratedAnnotation() { this.getType().hasQualifiedName("javax.annotation", "Generated") } + GeneratedAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation", "Generated") + } } /** * A `@javax.annotation.PostConstruct` annotation. */ class PostConstructAnnotation extends Annotation { - PostConstructAnnotation() { this.getType().hasQualifiedName("javax.annotation", "PostConstruct") } + PostConstructAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation", "PostConstruct") + } } /** * A `@javax.annotation.PreDestroy` annotation. */ class PreDestroyAnnotation extends Annotation { - PreDestroyAnnotation() { this.getType().hasQualifiedName("javax.annotation", "PreDestroy") } + PreDestroyAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation", "PreDestroy") + } } /** * A `@javax.annotation.Resource` annotation. */ class ResourceAnnotation extends Annotation { - ResourceAnnotation() { this.getType().hasQualifiedName("javax.annotation", "Resource") } + ResourceAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation", "Resource") + } } /** * A `@javax.annotation.Resources` annotation. */ class ResourcesAnnotation extends Annotation { - ResourcesAnnotation() { this.getType().hasQualifiedName("javax.annotation", "Resources") } + ResourcesAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation", "Resources") + } } /** @@ -50,7 +60,7 @@ class ResourcesAnnotation extends Annotation { */ class JavaxManagedBeanAnnotation extends Annotation { JavaxManagedBeanAnnotation() { - this.getType().hasQualifiedName("javax.annotation", "ManagedBean") + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation", "ManagedBean") } } @@ -63,7 +73,7 @@ class JavaxManagedBeanAnnotation extends Annotation { */ class DeclareRolesAnnotation extends Annotation { DeclareRolesAnnotation() { - this.getType().hasQualifiedName("javax.annotation.security", "DeclareRoles") + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation.security", "DeclareRoles") } } @@ -71,7 +81,9 @@ class DeclareRolesAnnotation extends Annotation { * A `@javax.annotation.security.DenyAll` annotation. */ class DenyAllAnnotation extends Annotation { - DenyAllAnnotation() { this.getType().hasQualifiedName("javax.annotation.security", "DenyAll") } + DenyAllAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation.security", "DenyAll") + } } /** @@ -79,7 +91,7 @@ class DenyAllAnnotation extends Annotation { */ class PermitAllAnnotation extends Annotation { PermitAllAnnotation() { - this.getType().hasQualifiedName("javax.annotation.security", "PermitAll") + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation.security", "PermitAll") } } @@ -88,7 +100,7 @@ class PermitAllAnnotation extends Annotation { */ class RolesAllowedAnnotation extends Annotation { RolesAllowedAnnotation() { - this.getType().hasQualifiedName("javax.annotation.security", "RolesAllowed") + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation.security", "RolesAllowed") } } @@ -96,7 +108,9 @@ class RolesAllowedAnnotation extends Annotation { * A `@javax.annotation.security.RunAs` annotation. */ class RunAsAnnotation extends Annotation { - RunAsAnnotation() { this.getType().hasQualifiedName("javax.annotation.security", "RunAs") } + RunAsAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".annotation.security", "RunAs") + } } /* @@ -107,7 +121,9 @@ class RunAsAnnotation extends Annotation { * A `@javax.interceptor.AroundInvoke` annotation. */ class AroundInvokeAnnotation extends Annotation { - AroundInvokeAnnotation() { this.getType().hasQualifiedName("javax.interceptor", "AroundInvoke") } + AroundInvokeAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".interceptor", "AroundInvoke") + } } /** @@ -115,7 +131,7 @@ class AroundInvokeAnnotation extends Annotation { */ class ExcludeClassInterceptorsAnnotation extends Annotation { ExcludeClassInterceptorsAnnotation() { - this.getType().hasQualifiedName("javax.interceptor", "ExcludeClassInterceptors") + this.getType().hasQualifiedName(javaxOrJakarta() + ".interceptor", "ExcludeClassInterceptors") } } @@ -124,7 +140,7 @@ class ExcludeClassInterceptorsAnnotation extends Annotation { */ class ExcludeDefaultInterceptorsAnnotation extends Annotation { ExcludeDefaultInterceptorsAnnotation() { - this.getType().hasQualifiedName("javax.interceptor", "ExcludeDefaultInterceptors") + this.getType().hasQualifiedName(javaxOrJakarta() + ".interceptor", "ExcludeDefaultInterceptors") } } @@ -132,7 +148,9 @@ class ExcludeDefaultInterceptorsAnnotation extends Annotation { * A `@javax.interceptor.Interceptors` annotation. */ class InterceptorsAnnotation extends Annotation { - InterceptorsAnnotation() { this.getType().hasQualifiedName("javax.interceptor", "Interceptors") } + InterceptorsAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".interceptor", "Interceptors") + } } /* @@ -143,14 +161,16 @@ class InterceptorsAnnotation extends Annotation { * A `@javax.jws.WebMethod` annotation. */ class WebMethodAnnotation extends Annotation { - WebMethodAnnotation() { this.getType().hasQualifiedName("javax.jws", "WebMethod") } + WebMethodAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".jws", "WebMethod") } } /** * A `@javax.jws.WebService` annotation. */ class WebServiceAnnotation extends Annotation { - WebServiceAnnotation() { this.getType().hasQualifiedName("javax.jws", "WebService") } + WebServiceAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".jws", "WebService") + } } /* @@ -161,5 +181,40 @@ class WebServiceAnnotation extends Annotation { * A `@javax.xml.ws.WebServiceRef` annotation. */ class WebServiceRefAnnotation extends Annotation { - WebServiceRefAnnotation() { this.getType().hasQualifiedName("javax.xml.ws", "WebServiceRef") } + WebServiceRefAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".xml.ws", "WebServiceRef") + } +} + +/* + * Annotations in the package `javax.validation.constraints`. + */ + +/** + * A `@javax.validation.constraints.Pattern` annotation. + */ +class PatternAnnotation extends Annotation, RegexMatch::Range { + PatternAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".validation.constraints", "Pattern") + } + + override Expr getRegex() { result = this.getValue("regexp") } + + override Expr getString() { + // Annotation on field accessed by direct read - value of field will match regexp + result.(FieldRead).getField() = this.getAnnotatedElement() + or + // Annotation on field accessed by getter - value of field will match regexp + result.(MethodCall).getMethod().(GetterMethod).getField() = this.getAnnotatedElement() + or + // Annotation on parameter - value of parameter will match regexp + result.(VarRead).getVariable().(Parameter) = this.getAnnotatedElement() + or + // Annotation on method - return value of method will match regexp + result.(Call).getCallee() = this.getAnnotatedElement() + // TODO - we could also consider the case where the annotation is on a type + // but this harder to model and not very common. + } + + override string getName() { result = "@javax.validation.constraints.Pattern annotation" } } diff --git a/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll b/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll index 8b3ab081ee0..38bac53485b 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll @@ -13,7 +13,7 @@ private import semmle.code.java.security.XSS /** * Gets a name for the root package of JAX-RS. */ -string getAJaxRsPackage() { result in ["javax.ws.rs", "jakarta.ws.rs"] } +string getAJaxRsPackage() { result = javaxOrJakarta() + ".ws.rs" } /** * Gets a name for package `subpackage` within the JAX-RS hierarchy. @@ -42,7 +42,7 @@ class JaxWsEndpoint extends Class { result.isPublic() and not result instanceof InitializerMethod and not exists(Annotation a | a = result.getAnAnnotation() | - a.getType().hasQualifiedName(["javax", "jakarta"] + ".jws", "WebMethod") and + a.getType().hasQualifiedName(javaxOrJakarta() + ".jws", "WebMethod") and a.getValue("exclude").(BooleanLiteral).getBooleanValue() = true ) and forex(ParamOrReturn paramOrRet | paramOrRet = result.getAParameter() or paramOrRet = result | @@ -62,8 +62,7 @@ class JaxWsEndpoint extends Class { /** The annotation type `@XmlJavaTypeAdapter`. */ class XmlJavaTypeAdapter extends AnnotationType { XmlJavaTypeAdapter() { - this.hasQualifiedName(["javax", "jakarta"] + ".xml.bind.annotation.adapters", - "XmlJavaTypeAdapter") + this.hasQualifiedName(javaxOrJakarta() + ".xml.bind.annotation.adapters", "XmlJavaTypeAdapter") } } @@ -292,7 +291,7 @@ class JaxRSAnnotation extends Annotation { JaxRSAnnotation() { exists(AnnotationType a | a = this.getType() and - a.getPackage().getName().regexpMatch(["javax\\.ws\\.rs(\\..*)?", "jakarta\\.ws\\.rs(\\..*)?"]) + a.getPackage().getName().regexpMatch(javaxOrJakarta() + "\\.ws\\.rs(\\..*)?") ) } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Jms.qll b/java/ql/lib/semmle/code/java/frameworks/Jms.qll index 3cc76771a77..abee6b3a427 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Jms.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Jms.qll @@ -7,6 +7,6 @@ import java /** The method `ObjectMessage.getObject`. */ class ObjectMessageGetObjectMethod extends Method { ObjectMessageGetObjectMethod() { - this.hasQualifiedName(["javax", "jakarta"] + ".jms", "ObjectMessage", "getObject") + this.hasQualifiedName(javaxOrJakarta() + ".jms", "ObjectMessage", "getObject") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Jndi.qll b/java/ql/lib/semmle/code/java/frameworks/Jndi.qll index 0d7d481dc1d..d2b14d5f58e 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Jndi.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Jndi.qll @@ -9,32 +9,34 @@ import java /*--- Types ---*/ /** The interface `javax.naming.Context`. */ class TypeNamingContext extends Interface { - TypeNamingContext() { this.hasQualifiedName("javax.naming", "Context") } + TypeNamingContext() { this.hasQualifiedName(javaxOrJakarta() + ".naming", "Context") } } /** The class `javax.naming.CompositeName`. */ class TypeCompositeName extends Class { - TypeCompositeName() { this.hasQualifiedName("javax.naming", "CompositeName") } + TypeCompositeName() { this.hasQualifiedName(javaxOrJakarta() + ".naming", "CompositeName") } } /** The class `javax.naming.CompoundName`. */ class TypeCompoundName extends Class { - TypeCompoundName() { this.hasQualifiedName("javax.naming", "CompoundName") } + TypeCompoundName() { this.hasQualifiedName(javaxOrJakarta() + ".naming", "CompoundName") } } /** The interface `javax.naming.directory.DirContext`. */ class TypeDirContext extends Interface { - TypeDirContext() { this.hasQualifiedName("javax.naming.directory", "DirContext") } + TypeDirContext() { this.hasQualifiedName(javaxOrJakarta() + ".naming.directory", "DirContext") } } /** The class `javax.naming.directory.SearchControls` */ class TypeSearchControls extends Class { - TypeSearchControls() { this.hasQualifiedName("javax.naming.directory", "SearchControls") } + TypeSearchControls() { + this.hasQualifiedName(javaxOrJakarta() + ".naming.directory", "SearchControls") + } } /** The class `javax.naming.ldap.LdapName`. */ class TypeLdapName extends Class { - TypeLdapName() { this.hasQualifiedName("javax.naming.ldap", "LdapName") } + TypeLdapName() { this.hasQualifiedName(javaxOrJakarta() + ".naming.ldap", "LdapName") } } /*--- Methods ---*/ diff --git a/java/ql/lib/semmle/code/java/frameworks/Mail.qll b/java/ql/lib/semmle/code/java/frameworks/Mail.qll index c61e5ae34f9..b99220c1737 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Mail.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Mail.qll @@ -8,7 +8,7 @@ import java * The class `javax.mail.Session` or `jakarta.mail.Session`. */ class MailSession extends Class { - MailSession() { this.hasQualifiedName(["javax.mail", "jakarta.mail"], "Session") } + MailSession() { this.hasQualifiedName(javaxOrJakarta() + ".mail", "Session") } } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/Networking.qll b/java/ql/lib/semmle/code/java/frameworks/Networking.qll index 6eeb5aa9024..21df7ae7f8d 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Networking.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Networking.qll @@ -20,7 +20,7 @@ class TypeSocket extends RefType { /** The type `javax.net.SocketFactory` */ class TypeSocketFactory extends RefType { - TypeSocketFactory() { this.hasQualifiedName("javax.net", "SocketFactory") } + TypeSocketFactory() { this.hasQualifiedName(javaxOrJakarta() + ".net", "SocketFactory") } } /** The type `java.net.URL`. */ diff --git a/java/ql/lib/semmle/code/java/frameworks/Regex.qll b/java/ql/lib/semmle/code/java/frameworks/Regex.qll index 56be77eae82..83d7336a341 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Regex.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Regex.qll @@ -3,6 +3,7 @@ overlay[local?] module; import java +private import semmle.code.java.dataflow.DataFlow /** The class `java.util.regex.Matcher`. */ class TypeRegexMatcher extends Class { @@ -24,6 +25,16 @@ class TypeRegexPattern extends Class { TypeRegexPattern() { this.hasQualifiedName("java.util.regex", "Pattern") } } +/** + * The `compile` method of `java.util.regex.Pattern`. + */ +class PatternCompileMethod extends Method { + PatternCompileMethod() { + this.getDeclaringType() instanceof TypeRegexPattern and + this.hasName("compile") + } +} + /** * The `matches` method of `java.util.regex.Pattern`. */ @@ -59,3 +70,66 @@ class PatternLiteralField extends Field { this.hasName("LITERAL") } } + +/** A call to the `compile` method of `java.util.regex.Pattern`. */ +class PatternCompileCall extends MethodCall { + PatternCompileCall() { this.getMethod() instanceof PatternCompileMethod } +} + +/** A call to the `matcher` method of `java.util.regex.Pattern`. */ +class PatternMatcherCall extends MethodCall { + PatternMatcherCall() { this.getMethod() instanceof PatternMatcherMethod } +} + +/** A call to the `matches` method of `java.util.regex.Pattern`. */ +class PatternMatchesCall extends MethodCall, RegexMatch::Range { + PatternMatchesCall() { this.getMethod() instanceof PatternMatchesMethod } + + override Expr getRegex() { result = this.getArgument(0) } + + override Expr getString() { result = this.getArgument(1) } + + override string getName() { result = "Pattern.matches" } +} + +/** A call to the `matches` method of `java.util.regex.Matcher`. */ +class MatcherMatchesCall extends MethodCall, RegexMatch::Range { + MatcherMatchesCall() { this.getMethod() instanceof MatcherMatchesMethod } + + /** + * Gets the call to `java.util.regex.Pattern.matcher` that returned the + * qualifier of this call. This is needed to determine the string being + * matched. + */ + PatternMatcherCall getPatternMatcherCall() { + DataFlow::localExprFlow(result, this.getQualifier()) + } + + /** + * Gets the call to `java.util.regex.Pattern.compile` that returned the + * `Pattern` used by this matcher. This is needed to determine the regular + * expression being used. + */ + PatternCompileCall getPatternCompileCall() { + DataFlow::localExprFlow(result, this.getPatternMatcherCall()) + } + + override Expr getRegex() { result = this.getPatternCompileCall().getArgument(0) } + + override Expr getString() { result = this.getPatternMatcherCall().getArgument(0) } + + override Expr getAdditionalSanitizedExpr() { + // Special case for MatcherMatchesCall. Consider the following code: + // + // Matcher matcher = Pattern.compile(regexp).matcher(taintedInput); + // if (matcher.matches()) { + // sink(matcher.group(1)); + // } + // + // Even though the string is `taintedInput`, we also want to sanitize + // `matcher` as it can be used to get substrings of `taintedInput`. + result = this.getQualifier() + } + + override string getName() { result = "Matcher.matches" } +} diff --git a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll index 7d7beb74fc3..826636ce073 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll @@ -12,7 +12,7 @@ import semmle.code.java.Type */ class ServletRequest extends RefType { ServletRequest() { - this.hasQualifiedName("javax.servlet", "ServletRequest") or + this.hasQualifiedName(javaxOrJakarta() + ".servlet", "ServletRequest") or this instanceof HttpServletRequest } } @@ -21,7 +21,9 @@ class ServletRequest extends RefType { * The interface `javax.servlet.http.HttpServletRequest`. */ class HttpServletRequest extends RefType { - HttpServletRequest() { this.hasQualifiedName("javax.servlet.http", "HttpServletRequest") } + HttpServletRequest() { + this.hasQualifiedName(javaxOrJakarta() + ".servlet.http", "HttpServletRequest") + } } /** @@ -168,7 +170,7 @@ class ServletRequestGetBodyMethod extends Method { */ class ServletResponse extends RefType { ServletResponse() { - this.hasQualifiedName("javax.servlet", "ServletResponse") or + this.hasQualifiedName(javaxOrJakarta() + ".servlet", "ServletResponse") or this instanceof HttpServletResponse } } @@ -177,7 +179,9 @@ class ServletResponse extends RefType { * The interface `javax.servlet.http.HttpServletResponse`. */ class HttpServletResponse extends RefType { - HttpServletResponse() { this.hasQualifiedName("javax.servlet.http", "HttpServletResponse") } + HttpServletResponse() { + this.hasQualifiedName(javaxOrJakarta() + ".servlet.http", "HttpServletResponse") + } } /** @@ -239,7 +243,7 @@ class ServletResponseGetOutputStreamMethod extends Method { /** The class `javax.servlet.http.Cookie`. */ class TypeCookie extends Class { - TypeCookie() { this.hasQualifiedName("javax.servlet.http", "Cookie") } + TypeCookie() { this.hasQualifiedName(javaxOrJakarta() + ".servlet.http", "Cookie") } } /** @@ -331,7 +335,7 @@ class ResponseSetContentTypeMethod extends Method { * A class that has `javax.servlet.Servlet` as an ancestor. */ class ServletClass extends Class { - ServletClass() { this.getAnAncestor().hasQualifiedName("javax.servlet", "Servlet") } + ServletClass() { this.getAnAncestor().hasQualifiedName(javaxOrJakarta() + ".servlet", "Servlet") } } /** @@ -342,13 +346,13 @@ class ServletClass extends Class { */ class ServletWebXmlListenerType extends RefType { ServletWebXmlListenerType() { - this.hasQualifiedName("javax.servlet", "ServletContextAttributeListener") or - this.hasQualifiedName("javax.servlet", "ServletContextListener") or - this.hasQualifiedName("javax.servlet", "ServletRequestAttributeListener") or - this.hasQualifiedName("javax.servlet", "ServletRequestListener") or - this.hasQualifiedName("javax.servlet.http", "HttpSessionAttributeListener") or - this.hasQualifiedName("javax.servlet.http", "HttpSessionIdListener") or - this.hasQualifiedName("javax.servlet.http", "HttpSessionListener") + this.hasQualifiedName(javaxOrJakarta() + ".servlet", "ServletContextAttributeListener") or + this.hasQualifiedName(javaxOrJakarta() + ".servlet", "ServletContextListener") or + this.hasQualifiedName(javaxOrJakarta() + ".servlet", "ServletRequestAttributeListener") or + this.hasQualifiedName(javaxOrJakarta() + ".servlet", "ServletRequestListener") or + this.hasQualifiedName(javaxOrJakarta() + ".servlet.http", "HttpSessionAttributeListener") or + this.hasQualifiedName(javaxOrJakarta() + ".servlet.http", "HttpSessionIdListener") or + this.hasQualifiedName(javaxOrJakarta() + ".servlet.http", "HttpSessionListener") // Listeners that are not configured in `web.xml`: // - `HttpSessionActivationListener` // - `HttpSessionBindingListener` @@ -373,8 +377,8 @@ predicate isRequestGetParamMethod(MethodCall ma) { /** The Java EE RequestDispatcher. */ class RequestDispatcher extends RefType { RequestDispatcher() { - this.hasQualifiedName(["javax.servlet", "jakarta.servlet"], "RequestDispatcher") or - this.hasQualifiedName("javax.portlet", "PortletRequestDispatcher") + this.hasQualifiedName(javaxOrJakarta() + ".servlet", "RequestDispatcher") or + this.hasQualifiedName(javaxOrJakarta() + ".portlet", "PortletRequestDispatcher") } } @@ -398,7 +402,7 @@ class RequestDispatchMethod extends Method { * The interface `javax.servlet.ServletContext`. */ class ServletContext extends RefType { - ServletContext() { this.hasQualifiedName("javax.servlet", "ServletContext") } + ServletContext() { this.hasQualifiedName(javaxOrJakarta() + ".servlet", "ServletContext") } } /** The `getResource` method of `ServletContext`. */ @@ -419,5 +423,5 @@ class GetServletResourceAsStreamMethod extends Method { /** The interface `javax.servlet.http.HttpSession` */ class HttpServletSession extends RefType { - HttpServletSession() { this.hasQualifiedName("javax.servlet.http", "HttpSession") } + HttpServletSession() { this.hasQualifiedName(javaxOrJakarta() + ".servlet.http", "HttpSession") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/JavaServerFaces.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/JavaServerFaces.qll index 2f749962e94..285bd7fd670 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/JavaServerFaces.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/JavaServerFaces.qll @@ -61,7 +61,7 @@ class FacesAccessibleType extends RefType { class FacesComponent extends Class { FacesComponent() { // Must extend UIComponent for it to be a valid component. - this.getAnAncestor().hasQualifiedName("javax.faces.component", "UIComponent") and + this.getAnAncestor().hasQualifiedName(javaxOrJakarta() + ".faces.component", "UIComponent") and ( // Must be registered using either an annotation exists(FacesComponentAnnotation componentAnnotation | diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll index b5031d7dff0..a6cedcc3fee 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll @@ -9,7 +9,7 @@ import java /** * Gets a JavaEE Persistence API package name. */ -string getAPersistencePackageName() { result = ["javax.persistence", "jakarta.persistence"] } +string getAPersistencePackageName() { result = javaxOrJakarta() + ".persistence" } /** * A `RefType` with the `@Entity` annotation that indicates that it can be persisted using a JPA diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/Xml.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/Xml.qll index 222b778ba58..6943c8023d4 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/Xml.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/Xml.qll @@ -33,7 +33,7 @@ private class ValidatorConfig extends TransformerConfig { /** The class `javax.xml.validation.Validator`. */ private class Validator extends RefType { - Validator() { this.hasQualifiedName("javax.xml.validation", "Validator") } + Validator() { this.hasQualifiedName(javaxOrJakarta() + ".xml.validation", "Validator") } } /** A safely configured `Validator`. */ diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll index a866d84df21..efbd0c0b1eb 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll @@ -64,7 +64,7 @@ class SessionEjb extends EJB { result = this.getASupertype() and not result.hasQualifiedName("java.io", "Serializable") and not result.hasQualifiedName("java.io", "Externalizable") and - not result.getPackage().getName() = "javax.ejb" + not result.getPackage().getName() = javaxOrJakarta() + ".ejb" } /** Any remote interfaces of this EJB. */ @@ -216,14 +216,14 @@ abstract class BusinessInterfaceAnnotation extends EjbInterfaceAnnotation { } * An instance of a `@Remote` annotation. */ class RemoteAnnotation extends BusinessInterfaceAnnotation { - RemoteAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Remote") } + RemoteAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Remote") } } /** * An instance of a `@Local` annotation. */ class LocalAnnotation extends BusinessInterfaceAnnotation { - LocalAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Local") } + LocalAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Local") } } /** @@ -330,7 +330,7 @@ class LocalAnnotatedBusinessInterface extends AnnotatedBusinessInterface { * A `@javax.ejb.Init` annotation. */ class InitAnnotation extends Annotation { - InitAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Init") } + InitAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Init") } } /** @@ -383,14 +383,16 @@ abstract class HomeAnnotation extends EjbInterfaceAnnotation { } * An instance of a `@RemoteHome` annotation. */ class RemoteHomeAnnotation extends HomeAnnotation { - RemoteHomeAnnotation() { this.getType().hasQualifiedName("javax.ejb", "RemoteHome") } + RemoteHomeAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "RemoteHome") + } } /** * An instance of a `@LocalHome` annotation. */ class LocalHomeAnnotation extends HomeAnnotation { - LocalHomeAnnotation() { this.getType().hasQualifiedName("javax.ejb", "LocalHome") } + LocalHomeAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "LocalHome") } } /** @@ -748,7 +750,9 @@ Type inheritsMatchingCreateMethodExceptThrows(StatefulSessionEjb ejb, EjbInterfa * A `@javax.ejb.AccessTimeout` annotation. */ class AccessTimeoutAnnotation extends Annotation { - AccessTimeoutAnnotation() { this.getType().hasQualifiedName("javax.ejb", "AccessTimeout") } + AccessTimeoutAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "AccessTimeout") + } } /** @@ -756,7 +760,7 @@ class AccessTimeoutAnnotation extends Annotation { */ class ActivationConfigPropertyAnnotation extends Annotation { ActivationConfigPropertyAnnotation() { - this.getType().hasQualifiedName("javax.ejb", "ActivationConfigProperty") + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "ActivationConfigProperty") } } @@ -764,14 +768,18 @@ class ActivationConfigPropertyAnnotation extends Annotation { * A `@javax.ejb.AfterBegin` annotation. */ class AfterBeginAnnotation extends Annotation { - AfterBeginAnnotation() { this.getType().hasQualifiedName("javax.ejb", "AfterBegin") } + AfterBeginAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "AfterBegin") + } } /** * A `@javax.ejb.AfterCompletion` annotation. */ class AfterCompletionAnnotation extends Annotation { - AfterCompletionAnnotation() { this.getType().hasQualifiedName("javax.ejb", "AfterCompletion") } + AfterCompletionAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "AfterCompletion") + } } /** @@ -779,7 +787,7 @@ class AfterCompletionAnnotation extends Annotation { */ class ApplicationExceptionAnnotation extends Annotation { ApplicationExceptionAnnotation() { - this.getType().hasQualifiedName("javax.ejb", "ApplicationException") + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "ApplicationException") } } @@ -787,14 +795,18 @@ class ApplicationExceptionAnnotation extends Annotation { * A `@javax.ejb.Asynchronous` annotation. */ class AsynchronousAnnotation extends Annotation { - AsynchronousAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Asynchronous") } + AsynchronousAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Asynchronous") + } } /** * A `@javax.ejb.BeforeCompletion` annotation. */ class BeforeCompletionAnnotation extends Annotation { - BeforeCompletionAnnotation() { this.getType().hasQualifiedName("javax.ejb", "BeforeCompletion") } + BeforeCompletionAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "BeforeCompletion") + } } /** @@ -802,7 +814,7 @@ class BeforeCompletionAnnotation extends Annotation { */ class ConcurrencyManagementAnnotation extends Annotation { ConcurrencyManagementAnnotation() { - this.getType().hasQualifiedName("javax.ejb", "ConcurrencyManagement") + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "ConcurrencyManagement") } } @@ -810,119 +822,127 @@ class ConcurrencyManagementAnnotation extends Annotation { * A `@javax.ejb.DependsOn` annotation. */ class DependsOnAnnotation extends Annotation { - DependsOnAnnotation() { this.getType().hasQualifiedName("javax.ejb", "DependsOn") } + DependsOnAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "DependsOn") } } /** * A `@javax.ejb.EJB` annotation. */ class EjbAnnotation extends Annotation { - EjbAnnotation() { this.getType().hasQualifiedName("javax.ejb", "EJB") } + EjbAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "EJB") } } /** * A `@javax.ejb.EJBs` annotation. */ class EJBsAnnotation extends Annotation { - EJBsAnnotation() { this.getType().hasQualifiedName("javax.ejb", "EJBs") } + EJBsAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "EJBs") } } /** * A `@javax.ejb.LocalBean` annotation. */ class LocalBeanAnnotation extends Annotation { - LocalBeanAnnotation() { this.getType().hasQualifiedName("javax.ejb", "LocalBean") } + LocalBeanAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "LocalBean") } } /** * A `@javax.ejb.Lock` annotation. */ class LockAnnotation extends Annotation { - LockAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Lock") } + LockAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Lock") } } /** * A `@javax.ejb.MessageDriven` annotation. */ class MessageDrivenAnnotation extends Annotation { - MessageDrivenAnnotation() { this.getType().hasQualifiedName("javax.ejb", "MessageDriven") } + MessageDrivenAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "MessageDriven") + } } /** * A `@javax.ejb.PostActivate` annotation. */ class PostActivateAnnotation extends Annotation { - PostActivateAnnotation() { this.getType().hasQualifiedName("javax.ejb", "PostActivate") } + PostActivateAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "PostActivate") + } } /** * A `@javax.ejb.PrePassivate` annotation. */ class PrePassivateAnnotation extends Annotation { - PrePassivateAnnotation() { this.getType().hasQualifiedName("javax.ejb", "PrePassivate") } + PrePassivateAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "PrePassivate") + } } /** * A `@javax.ejb.Remove` annotation. */ class RemoveAnnotation extends Annotation { - RemoveAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Remove") } + RemoveAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Remove") } } /** * A `@javax.ejb.Schedule` annotation. */ class ScheduleAnnotation extends Annotation { - ScheduleAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Schedule") } + ScheduleAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Schedule") } } /** * A `@javax.ejb.Schedules` annotation. */ class SchedulesAnnotation extends Annotation { - SchedulesAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Schedules") } + SchedulesAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Schedules") } } /** * A `@javax.ejb.Singleton` annotation. */ class SingletonAnnotation extends Annotation { - SingletonAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Singleton") } + SingletonAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Singleton") } } /** * A `@javax.ejb.Startup` annotation. */ class StartupAnnotation extends Annotation { - StartupAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Startup") } + StartupAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Startup") } } /** * A `@javax.ejb.Stateful` annotation. */ class StatefulAnnotation extends Annotation { - StatefulAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Stateful") } + StatefulAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Stateful") } } /** * A `@javax.ejb.StatefulTimeout` annotation. */ class StatefulTimeoutAnnotation extends Annotation { - StatefulTimeoutAnnotation() { this.getType().hasQualifiedName("javax.ejb", "StatefulTimeout") } + StatefulTimeoutAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "StatefulTimeout") + } } /** * A `@javax.ejb.Stateless` annotation. */ class StatelessAnnotation extends Annotation { - StatelessAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Stateless") } + StatelessAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Stateless") } } /** * A `@javax.ejb.Timeout` annotation. */ class TimeoutAnnotation extends Annotation { - TimeoutAnnotation() { this.getType().hasQualifiedName("javax.ejb", "Timeout") } + TimeoutAnnotation() { this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "Timeout") } } /** @@ -930,7 +950,7 @@ class TimeoutAnnotation extends Annotation { */ class TransactionAttributeAnnotation extends Annotation { TransactionAttributeAnnotation() { - this.getType().hasQualifiedName("javax.ejb", "TransactionAttribute") + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "TransactionAttribute") } } @@ -939,7 +959,7 @@ class TransactionAttributeAnnotation extends Annotation { */ class TransactionManagementAnnotation extends Annotation { TransactionManagementAnnotation() { - this.getType().hasQualifiedName("javax.ejb", "TransactionManagement") + this.getType().hasQualifiedName(javaxOrJakarta() + ".ejb", "TransactionManagement") } } @@ -951,7 +971,10 @@ class RequiredTransactionAttributeAnnotation extends TransactionAttributeAnnotat RequiredTransactionAttributeAnnotation() { exists(FieldRead fr | this.getValue("value") = fr and - fr.getField().getType().(RefType).hasQualifiedName("javax.ejb", "TransactionAttributeType") and + fr.getField() + .getType() + .(RefType) + .hasQualifiedName(javaxOrJakarta() + ".ejb", "TransactionAttributeType") and fr.getField().getName() = "REQUIRED" ) } @@ -965,7 +988,10 @@ class RequiresNewTransactionAttributeAnnotation extends TransactionAttributeAnno RequiresNewTransactionAttributeAnnotation() { exists(FieldRead fr | this.getValue("value") = fr and - fr.getField().getType().(RefType).hasQualifiedName("javax.ejb", "TransactionAttributeType") and + fr.getField() + .getType() + .(RefType) + .hasQualifiedName(javaxOrJakarta() + ".ejb", "TransactionAttributeType") and fr.getField().getName() = "REQUIRES_NEW" ) } @@ -999,7 +1025,9 @@ TransactionAttributeAnnotation getInnermostTransactionAttributeAnnotation(Method */ class SetRollbackOnlyMethod extends Method { SetRollbackOnlyMethod() { - this.getDeclaringType().getAnAncestor().hasQualifiedName("javax.ejb", "EJBContext") and + this.getDeclaringType() + .getAnAncestor() + .hasQualifiedName(javaxOrJakarta() + ".ejb", "EJBContext") and this.getName() = "setRollbackOnly" and this.hasNoParameters() } 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 10b6e7f3df2..47872816825 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 @@ -159,8 +159,8 @@ class GraphicsPackage extends Package { GraphicsPackage() { this.getName() = "java.awt" or this.getName().matches("java.awt.%") or - this.getName() = "javax.swing" or - this.getName().matches("javax.swing.%") + this.getName() = javaxOrJakarta() + ".swing" or + this.getName().matches(javaxOrJakarta() + ".swing.%") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFAnnotations.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFAnnotations.qll index 3338fa840ab..f62d9e50b68 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFAnnotations.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFAnnotations.qll @@ -9,7 +9,7 @@ import default */ class FacesManagedBeanAnnotation extends Annotation { FacesManagedBeanAnnotation() { - this.getType().hasQualifiedName("javax.faces.bean", "ManagedBean") + this.getType().hasQualifiedName(javaxOrJakarta() + ".faces.bean", "ManagedBean") } /** @@ -25,7 +25,7 @@ class FacesManagedBeanAnnotation extends Annotation { */ class FacesComponentAnnotation extends Annotation { FacesComponentAnnotation() { - this.getType().hasQualifiedName("javax.faces.component", "FacesComponent") + this.getType().hasQualifiedName(javaxOrJakarta() + ".faces.component", "FacesComponent") } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFRenderer.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFRenderer.qll index df646e8a9a2..21f8fba6785 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFRenderer.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFRenderer.qll @@ -8,9 +8,7 @@ import java * The JSF class `FacesContext` for processing HTTP requests. */ class FacesContext extends RefType { - FacesContext() { - this.hasQualifiedName(["javax.faces.context", "jakarta.faces.context"], "FacesContext") - } + FacesContext() { this.hasQualifiedName(javaxOrJakarta() + ".faces.context", "FacesContext") } } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll index e758811b368..970870f9503 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll @@ -14,7 +14,7 @@ import SpringComponentScan predicate hasInjectAnnotation(Annotatable a) { a.hasAnnotation("org.springframework.beans.factory.annotation", "Autowired") or a.getAnAnnotation() instanceof SpringResourceAnnotation or - a.hasAnnotation("javax.inject", "Inject") + a.hasAnnotation(javaxOrJakarta() + ".inject", "Inject") } /** @@ -292,7 +292,7 @@ class SpringBeanAutowiredField extends Field { class SpringQualifierAnnotationType extends AnnotationType { SpringQualifierAnnotationType() { this.hasQualifiedName("org.springframework.beans.factory.annotation", "Qualifier") or - this.hasQualifiedName("javax.inject", "Qualifier") or + this.hasQualifiedName(javaxOrJakarta() + ".inject", "Qualifier") or this.getAnAnnotation().getType() instanceof SpringQualifierAnnotationType } } @@ -340,7 +340,9 @@ class SpringQualifierAnnotation extends Annotation { * autowired by Spring, and can optionally specify a qualifier in the "name". */ class SpringResourceAnnotation extends Annotation { - SpringResourceAnnotation() { this.getType().hasQualifiedName("javax.inject", "Resource") } + SpringResourceAnnotation() { + this.getType().hasQualifiedName(javaxOrJakarta() + ".inject", "Resource") + } /** * Gets the specified name value, if any. 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 a444dc96d5a..a26e4edc277 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -210,10 +210,22 @@ class SpringRequestMappingParameter extends Parameter { predicate isNotDirectlyTaintedInput() { this.getType().(RefType).getAnAncestor() instanceof SpringWebRequest or this.getType().(RefType).getAnAncestor() instanceof SpringNativeWebRequest or - this.getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet", "ServletRequest") or - this.getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet", "ServletResponse") or - this.getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet.http", "HttpSession") or - this.getType().(RefType).getAnAncestor().hasQualifiedName("javax.servlet.http", "PushBuilder") or + this.getType() + .(RefType) + .getAnAncestor() + .hasQualifiedName(javaxOrJakarta() + ".servlet", "ServletRequest") or + this.getType() + .(RefType) + .getAnAncestor() + .hasQualifiedName(javaxOrJakarta() + ".servlet", "ServletResponse") or + this.getType() + .(RefType) + .getAnAncestor() + .hasQualifiedName(javaxOrJakarta() + ".servlet.http", "HttpSession") or + this.getType() + .(RefType) + .getAnAncestor() + .hasQualifiedName(javaxOrJakarta() + ".servlet.http", "PushBuilder") or this.getType().(RefType).getAnAncestor().hasQualifiedName("java.security", "Principal") or this.getType() .(RefType) diff --git a/java/ql/lib/semmle/code/java/security/CleartextStorageCookieQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStorageCookieQuery.qll index 1c99821386d..9f04aff7e40 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStorageCookieQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStorageCookieQuery.qll @@ -23,7 +23,9 @@ private class CookieCleartextStorageSink extends CleartextStorageSink { /** The instantiation of a cookie, which can act as storage. */ class Cookie extends Storable, ClassInstanceExpr { Cookie() { - this.getConstructor().getDeclaringType().hasQualifiedName("javax.servlet.http", "Cookie") + this.getConstructor() + .getDeclaringType() + .hasQualifiedName(javaxOrJakarta() + ".servlet.http", "Cookie") } /** Gets an input, for example `input` in `new Cookie("...", input);`. */ @@ -42,7 +44,8 @@ private predicate cookieStore(DataFlow::Node cookie, Expr store) { exists(MethodCall m, Method def | m.getMethod() = def and def.getName() = "addCookie" and - def.getDeclaringType().hasQualifiedName("javax.servlet.http", "HttpServletResponse") and + def.getDeclaringType() + .hasQualifiedName(javaxOrJakarta() + ".servlet.http", "HttpServletResponse") and store = m and cookie.asExpr() = m.getAnArgument() ) diff --git a/java/ql/lib/semmle/code/java/security/Encryption.qll b/java/ql/lib/semmle/code/java/security/Encryption.qll index b948a94962c..b0a0fc72df7 100644 --- a/java/ql/lib/semmle/code/java/security/Encryption.qll +++ b/java/ql/lib/semmle/code/java/security/Encryption.qll @@ -9,6 +9,7 @@ import java class SslClass extends RefType { SslClass() { exists(Class c | this.getAnAncestor() = c | + // Note there are no jakarta equivalents of these classes. c.hasQualifiedName("javax.net.ssl", _) or c.hasQualifiedName("javax.rmi.ssl", _) ) diff --git a/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll index e1c840ce264..88fb540e83b 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll @@ -25,7 +25,7 @@ class SetMessageInterpolatorCall extends MethodCall { this.getMethod() = m and m.getDeclaringType().getASourceSupertype*() = t and ( - t.hasQualifiedName("javax.validation", ["Configuration", "ValidatorContext"]) and + t.hasQualifiedName(javaxOrJakarta() + ".validation", ["Configuration", "ValidatorContext"]) and m.getName() = "messageInterpolator" or t.hasQualifiedName("org.springframework.validation.beanvalidation", diff --git a/java/ql/lib/semmle/code/java/security/LogInjection.qll b/java/ql/lib/semmle/code/java/security/LogInjection.qll index da5a1dc73a0..b585c249d1e 100644 --- a/java/ql/lib/semmle/code/java/security/LogInjection.qll +++ b/java/ql/lib/semmle/code/java/security/LogInjection.qll @@ -45,11 +45,11 @@ private class LineBreaksLogInjectionSanitizer extends LogInjectionSanitizer { } private predicate stringMethodCall( - MethodCall ma, CompileTimeConstantExpr arg0, CompileTimeConstantExpr arg1 + MethodCall mc, CompileTimeConstantExpr arg0, CompileTimeConstantExpr arg1 ) { - ma.getMethod().getDeclaringType() instanceof TypeString and - arg0 = ma.getArgument(0) and - arg1 = ma.getArgument(1) + mc.getMethod().getDeclaringType() instanceof TypeString and + arg0 = mc.getArgument(0) and + arg1 = mc.getArgument(1) } private predicate stringMethodArgument(CompileTimeConstantExpr arg) { @@ -64,22 +64,23 @@ private predicate stringMethodArgumentValueMatches(CompileTimeConstantExpr const } /** - * Holds if the return value of `ma` is sanitized against log injection attacks - * by removing line breaks from it. + * Holds if `e` is sanitized against log injection attacks by removing line + * breaks from it. */ -private predicate logInjectionSanitizer(MethodCall ma) { - exists(CompileTimeConstantExpr target, CompileTimeConstantExpr replacement | - stringMethodCall(ma, target, replacement) and +private predicate logInjectionSanitizer(Expr e) { + exists(MethodCall mc, CompileTimeConstantExpr target, CompileTimeConstantExpr replacement | + e = mc and + stringMethodCall(mc, target, replacement) and not stringMethodArgumentValueMatches(replacement, ["%\n%", "%\r%"]) | - ma.getMethod().hasName("replace") and + mc.getMethod().hasName("replace") and not replacement.getIntValue() = [10, 13] and ( target.getIntValue() = [10, 13] or // 10 == '\n', 13 == '\r' target.getStringValue() = ["\n", "\r"] ) or - ma.getMethod().hasName("replaceAll") and + mc.getMethod().hasName("replaceAll") and ( // Replace anything not in an allow list target.getStringValue().matches("[^%]") and @@ -89,6 +90,13 @@ private predicate logInjectionSanitizer(MethodCall ma) { target.getStringValue() = ["\n", "\r", "\\n", "\\r", "\\R"] ) ) + or + exists(RegexMatch rm, CompileTimeConstantExpr target | + rm instanceof Annotation and + e = rm.getASanitizedExpr() and + target = rm.getRegex() and + regexPreventsLogInjection(target.getStringValue(), true) + ) } /** @@ -96,41 +104,44 @@ private predicate logInjectionSanitizer(MethodCall ma) { * by checking if there are line breaks in `e`. */ private predicate logInjectionGuard(Guard g, Expr e, boolean branch) { - exists(MethodCall ma, CompileTimeConstantExpr target | - ma = g and - target = ma.getArgument(0) - | - ma.getMethod().getDeclaringType() instanceof TypeString and - ma.getMethod().hasName("contains") and - target.getStringValue() = ["\n", "\r"] and - e = ma.getQualifier() and + exists(MethodCall mc | mc = g | + mc.getMethod() instanceof StringContainsMethod and + mc.getArgument(0).(CompileTimeConstantExpr).getStringValue() = ["\n", "\r"] and + e = mc.getQualifier() and branch = false - or - ma.getMethod().hasName("matches") and - ( - ma.getMethod().getDeclaringType() instanceof TypeString and - e = ma.getQualifier() - or - ma.getMethod().getDeclaringType().hasQualifiedName("java.util.regex", "Pattern") and - e = ma.getArgument(1) - ) and - ( - // Allow anything except line breaks - ( - not target.getStringValue().matches("%[^%]%") and - not target.getStringValue().matches("%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%") - or - target.getStringValue().matches("%[^%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%]%") - ) and - branch = true - or - // Disallow line breaks - ( - not target.getStringValue().matches("%[^%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%]%") and - // Assuming a regex containing line breaks is correctly matching line breaks in a string - target.getStringValue().matches("%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%") - ) and - branch = false - ) + ) + or + exists(RegexMatch rm, CompileTimeConstantExpr target | + rm = g and + not rm instanceof Annotation and + target = rm.getRegex() and + e = rm.getASanitizedExpr() + | + regexPreventsLogInjection(target.getStringValue(), branch) ) } + +/** + * Holds if `regex` matches against a pattern that allows anything except + * line breaks when `branch` is `true`, or a pattern that matches line breaks + * when `branch` is `false`. + */ +bindingset[regex] +private predicate regexPreventsLogInjection(string regex, boolean branch) { + // Allow anything except line breaks + ( + not regex.matches("%[^%]%") and + not regex.matches("%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%") + or + regex.matches("%[^%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%]%") + ) and + branch = true + or + // Disallow line breaks + ( + not regex.matches("%[^%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%]%") and + // Assuming a regex containing line breaks is correctly matching line breaks in a string + regex.matches("%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%") + ) and + branch = false +} diff --git a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll index 4685f5e48f7..788cd542939 100644 --- a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll +++ b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll @@ -427,20 +427,15 @@ private class ReplaceDirectoryCharactersSanitizer extends StringReplaceOrReplace } } -/** Holds if `target` is the first argument of `matchesCall`. */ -private predicate isMatchesTarget(StringMatchesCall matchesCall, CompileTimeConstantExpr target) { - target = matchesCall.getArgument(0) -} - /** * Holds if `matchesCall` confirms that `checkedExpr` does not contain any directory characters * on the given `branch`. */ -private predicate isMatchesCall(StringMatchesCall matchesCall, Expr checkedExpr, boolean branch) { +private predicate isMatchesCall(RegexMatch regexMatch, Expr checkedExpr, boolean branch) { exists(CompileTimeConstantExpr target, string targetValue | - isMatchesTarget(matchesCall, target) and + target = regexMatch.getRegex() and target.getStringValue() = targetValue and - checkedExpr = matchesCall.getQualifier() + checkedExpr = regexMatch.getString() | ( // Allow anything except `.`, '/', '\' diff --git a/java/ql/lib/semmle/code/java/security/Sanitizers.qll b/java/ql/lib/semmle/code/java/security/Sanitizers.qll index 3f909864d2c..e00071da2d8 100644 --- a/java/ql/lib/semmle/code/java/security/Sanitizers.qll +++ b/java/ql/lib/semmle/code/java/security/Sanitizers.qll @@ -41,24 +41,10 @@ class SimpleTypeSanitizer extends DataFlow::Node { * make the type recursive. Otherwise use `RegexpCheckBarrier`. */ predicate regexpMatchGuardChecks(Guard guard, Expr e, boolean branch) { - exists(Method method, MethodCall mc | - method = mc.getMethod() and - guard = mc and + exists(RegexMatch rm | not rm instanceof Annotation | + guard = rm and + e = rm.getASanitizedExpr() and branch = true - | - // `String.matches` and other `matches` methods. - method.getName() = "matches" and - e = mc.getQualifier() - or - method instanceof PatternMatchesMethod and - e = mc.getArgument(1) - or - method instanceof MatcherMatchesMethod and - exists(MethodCall matcherCall | - matcherCall.getMethod() instanceof PatternMatcherMethod and - e = matcherCall.getArgument(0) and - DataFlow::localExprFlow(matcherCall, mc.getQualifier()) - ) ) } @@ -70,5 +56,10 @@ predicate regexpMatchGuardChecks(Guard guard, Expr e, boolean branch) { class RegexpCheckBarrier extends DataFlow::Node { RegexpCheckBarrier() { this = DataFlow::BarrierGuard::getABarrierNode() + or + // Annotations don't fit into the model of barrier guards because the + // annotation doesn't dominate the sanitized expression, so we instead + // treat them as barriers directly. + exists(RegexMatch rm | rm instanceof Annotation | this.asExpr() = rm.getString()) } } diff --git a/java/ql/lib/semmle/code/java/security/XSS.qll b/java/ql/lib/semmle/code/java/security/XSS.qll index 0d52d480ae7..b094346b753 100644 --- a/java/ql/lib/semmle/code/java/security/XSS.qll +++ b/java/ql/lib/semmle/code/java/security/XSS.qll @@ -127,7 +127,7 @@ class XssVulnerableWriterSource extends MethodCall { ) or exists(Method m | m = this.getMethod() | - m.hasQualifiedName("javax.servlet.jsp", "JspContext", "getOut") + m.hasQualifiedName(javaxOrJakarta() + ".servlet.jsp", "JspContext", "getOut") ) or this.getMethod() instanceof FacesGetResponseWriterMethod diff --git a/java/ql/lib/semmle/code/java/security/XmlParsers.qll b/java/ql/lib/semmle/code/java/security/XmlParsers.qll index 8bb2a015a14..bd1520034eb 100644 --- a/java/ql/lib/semmle/code/java/security/XmlParsers.qll +++ b/java/ql/lib/semmle/code/java/security/XmlParsers.qll @@ -62,12 +62,14 @@ abstract class ParserConfig extends MethodCall { /** The class `javax.xml.parsers.DocumentBuilderFactory`. */ class DocumentBuilderFactory extends RefType { - DocumentBuilderFactory() { this.hasQualifiedName("javax.xml.parsers", "DocumentBuilderFactory") } + DocumentBuilderFactory() { + this.hasQualifiedName(javaxOrJakarta() + ".xml.parsers", "DocumentBuilderFactory") + } } /** The class `javax.xml.parsers.DocumentBuilder`. */ class DocumentBuilder extends RefType { - DocumentBuilder() { this.hasQualifiedName("javax.xml.parsers", "DocumentBuilder") } + DocumentBuilder() { this.hasQualifiedName(javaxOrJakarta() + ".xml.parsers", "DocumentBuilder") } } /** A call to `DocumentBuilder.parse`. */ @@ -174,7 +176,7 @@ class SafeDocumentBuilder extends DocumentBuilderConstruction { /** The class `javax.xml.stream.XMLInputFactory`. */ class XmlInputFactory extends RefType { - XmlInputFactory() { this.hasQualifiedName("javax.xml.stream", "XMLInputFactory") } + XmlInputFactory() { this.hasQualifiedName(javaxOrJakarta() + ".xml.stream", "XMLInputFactory") } } /** A call to `XMLInputFactory.createXMLStreamReader`. */ @@ -243,7 +245,8 @@ class XmlInputFactoryConfig extends ParserConfig { * An `XmlInputFactory` specific expression that indicates whether parsing external entities is supported. */ Expr configOptionIsSupportingExternalEntities() { - result.(ConstantStringExpr).getStringValue() = "javax.xml.stream.isSupportingExternalEntities" + result.(ConstantStringExpr).getStringValue() = + javaxOrJakarta() + ".xml.stream.isSupportingExternalEntities" or exists(Field f | result = f.getAnAccess() and @@ -256,7 +259,7 @@ Expr configOptionIsSupportingExternalEntities() { * An `XmlInputFactory` specific expression that indicates whether DTD is supported. */ Expr configOptionSupportDtd() { - result.(ConstantStringExpr).getStringValue() = "javax.xml.stream.supportDTD" + result.(ConstantStringExpr).getStringValue() = javaxOrJakarta() + ".xml.stream.supportDTD" or exists(Field f | result = f.getAnAccess() and @@ -357,12 +360,14 @@ class SafeSaxBuilder extends VarAccess { * The class `javax.xml.parsers.SAXParser`. */ class SaxParser extends RefType { - SaxParser() { this.hasQualifiedName("javax.xml.parsers", "SAXParser") } + SaxParser() { this.hasQualifiedName(javaxOrJakarta() + ".xml.parsers", "SAXParser") } } /** The class `javax.xml.parsers.SAXParserFactory`. */ class SaxParserFactory extends RefType { - SaxParserFactory() { this.hasQualifiedName("javax.xml.parsers", "SAXParserFactory") } + SaxParserFactory() { + this.hasQualifiedName(javaxOrJakarta() + ".xml.parsers", "SAXParserFactory") + } } /** A call to `SAXParser.parse`. */ @@ -635,7 +640,7 @@ class CreatedSafeXmlReader extends Call { /** The class `javax.xml.transform.sax.SAXSource` */ class SaxSource extends RefType { - SaxSource() { this.hasQualifiedName("javax.xml.transform.sax", "SAXSource") } + SaxSource() { this.hasQualifiedName(javaxOrJakarta() + ".xml.transform.sax", "SAXSource") } } /** A call to the constructor of `SAXSource` with `XmlReader` and `InputSource`. */ @@ -697,7 +702,7 @@ abstract class TransformerConfig extends MethodCall { /** The class `javax.xml.XMLConstants`. */ class XmlConstants extends RefType { - XmlConstants() { this.hasQualifiedName("javax.xml", "XMLConstants") } + XmlConstants() { this.hasQualifiedName(javaxOrJakarta() + ".xml", "XMLConstants") } } /** A configuration specific for transformers and schema. */ @@ -739,14 +744,14 @@ Expr configAccessExternalSchema() { /** The class `javax.xml.transform.TransformerFactory` or `javax.xml.transform.sax.SAXTransformerFactory`. */ class TransformerFactory extends RefType { TransformerFactory() { - this.hasQualifiedName("javax.xml.transform", "TransformerFactory") or - this.hasQualifiedName("javax.xml.transform.sax", "SAXTransformerFactory") + this.hasQualifiedName(javaxOrJakarta() + ".xml.transform", "TransformerFactory") or + this.hasQualifiedName(javaxOrJakarta() + ".xml.transform.sax", "SAXTransformerFactory") } } /** The class `javax.xml.transform.Transformer`. */ class Transformer extends RefType { - Transformer() { this.hasQualifiedName("javax.xml.transform", "Transformer") } + Transformer() { this.hasQualifiedName(javaxOrJakarta() + ".xml.transform", "Transformer") } } /** A call to `Transformer.transform`. */ @@ -843,7 +848,8 @@ class SaxTransformerFactoryNewXmlFilter extends XmlParserCall { SaxTransformerFactoryNewXmlFilter() { exists(Method m | this.getMethod() = m and - m.getDeclaringType().hasQualifiedName("javax.xml.transform.sax", "SAXTransformerFactory") and + m.getDeclaringType() + .hasQualifiedName(javaxOrJakarta() + ".xml.transform.sax", "SAXTransformerFactory") and m.hasName("newXMLFilter") ) } @@ -858,7 +864,7 @@ class SaxTransformerFactoryNewXmlFilter extends XmlParserCall { /* Schema: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#schemafactory */ /** The class `javax.xml.validation.SchemaFactory`. */ class SchemaFactory extends RefType { - SchemaFactory() { this.hasQualifiedName("javax.xml.validation", "SchemaFactory") } + SchemaFactory() { this.hasQualifiedName(javaxOrJakarta() + ".xml.validation", "SchemaFactory") } } /** A `ParserConfig` specific to `SchemaFactory`. */ @@ -913,7 +919,7 @@ class SafeSchemaFactory extends VarAccess { /* Unmarshaller: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller */ /** The class `javax.xml.bind.Unmarshaller`. */ class XmlUnmarshaller extends RefType { - XmlUnmarshaller() { this.hasQualifiedName("javax.xml.bind", "Unmarshaller") } + XmlUnmarshaller() { this.hasQualifiedName(javaxOrJakarta() + ".xml.bind", "Unmarshaller") } } /** A call to `Unmarshaller.unmarshal`. */ @@ -934,12 +940,12 @@ class XmlUnmarshal extends XmlParserCall { /* XPathExpression: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xpathexpression */ /** The interface `javax.xml.xpath.XPathExpression`. */ class XPathExpression extends Interface { - XPathExpression() { this.hasQualifiedName("javax.xml.xpath", "XPathExpression") } + XPathExpression() { this.hasQualifiedName(javaxOrJakarta() + ".xml.xpath", "XPathExpression") } } /** The interface `java.xml.xpath.XPath`. */ class XPath extends Interface { - XPath() { this.hasQualifiedName("javax.xml.xpath", "XPath") } + XPath() { this.hasQualifiedName(javaxOrJakarta() + ".xml.xpath", "XPath") } } /** A call to the method `evaluate` of the classes `XPathExpression` or `XPath`. */ diff --git a/java/ql/lib/semmle/code/java/security/XsltInjection.qll b/java/ql/lib/semmle/code/java/security/XsltInjection.qll index d54e9206644..a6b18e1518f 100644 --- a/java/ql/lib/semmle/code/java/security/XsltInjection.qll +++ b/java/ql/lib/semmle/code/java/security/XsltInjection.qll @@ -163,17 +163,17 @@ private predicate xsltPackageStep(DataFlow::Node n1, DataFlow::Node n2) { /** The class `javax.xml.transform.stax.StAXSource`. */ private class TypeStAXSource extends Class { - TypeStAXSource() { this.hasQualifiedName("javax.xml.transform.stax", "StAXSource") } + TypeStAXSource() { this.hasQualifiedName(javaxOrJakarta() + ".xml.transform.stax", "StAXSource") } } /** The class `javax.xml.transform.dom.DOMSource`. */ private class TypeDomSource extends Class { - TypeDomSource() { this.hasQualifiedName("javax.xml.transform.dom", "DOMSource") } + TypeDomSource() { this.hasQualifiedName(javaxOrJakarta() + ".xml.transform.dom", "DOMSource") } } /** The interface `javax.xml.transform.Templates`. */ private class TypeTemplates extends Interface { - TypeTemplates() { this.hasQualifiedName("javax.xml.transform", "Templates") } + TypeTemplates() { this.hasQualifiedName(javaxOrJakarta() + ".xml.transform", "Templates") } } /** The class `net.sf.saxon.s9api.XsltCompiler`. */ @@ -205,7 +205,7 @@ private class DocumentBuilderParse extends MethodCall { /** The class `javax.xml.parsers.DocumentBuilder`. */ private class DocumentBuilder extends RefType { - DocumentBuilder() { this.hasQualifiedName("javax.xml.parsers", "DocumentBuilder") } + DocumentBuilder() { this.hasQualifiedName(javaxOrJakarta() + ".xml.parsers", "DocumentBuilder") } } /** A call to `XMLInputFactory.createXMLStreamReader`. */ @@ -232,5 +232,5 @@ private class XmlInputFactoryEventReader extends MethodCall { /** The class `javax.xml.stream.XMLInputFactory`. */ private class XmlInputFactory extends RefType { - XmlInputFactory() { this.hasQualifiedName("javax.xml.stream", "XMLInputFactory") } + XmlInputFactory() { this.hasQualifiedName(javaxOrJakarta() + ".xml.stream", "XMLInputFactory") } } diff --git a/java/ql/lib/semmle/code/java/security/regexp/RegexInjection.qll b/java/ql/lib/semmle/code/java/security/regexp/RegexInjection.qll index 944ffca803a..a14a07e0446 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/RegexInjection.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/RegexInjection.qll @@ -31,11 +31,9 @@ private class ExternalRegexInjectionSanitizer extends RegexInjectionSanitizer { */ private class PatternLiteralFlag extends RegexInjectionSanitizer { PatternLiteralFlag() { - exists(MethodCall ma, Method m, PatternLiteralField field | m = ma.getMethod() | - ma.getArgument(0) = this.asExpr() and - m.getDeclaringType() instanceof TypeRegexPattern and - m.hasName("compile") and - ma.getArgument(1) = field.getAnAccess() + exists(PatternCompileCall pcc, PatternLiteralField field | + pcc.getArgument(0) = this.asExpr() and + pcc.getArgument(1) = field.getAnAccess() ) } } diff --git a/java/ql/src/CHANGELOG.md b/java/ql/src/CHANGELOG.md index a7307229a49..20585a7e1cc 100644 --- a/java/ql/src/CHANGELOG.md +++ b/java/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.7 + +No user-facing changes. + ## 1.10.6 No user-facing changes. diff --git a/java/ql/src/Likely Bugs/Frameworks/Swing/BadlyOverriddenAdapter.ql b/java/ql/src/Likely Bugs/Frameworks/Swing/BadlyOverriddenAdapter.ql index 6a2db4b695f..34fd190ccf1 100644 --- a/java/ql/src/Likely Bugs/Frameworks/Swing/BadlyOverriddenAdapter.ql +++ b/java/ql/src/Likely Bugs/Frameworks/Swing/BadlyOverriddenAdapter.ql @@ -19,7 +19,7 @@ class Adapter extends Class { this.getName().matches("%Adapter") and ( this.getPackage().hasName("java.awt.event") or - this.getPackage().hasName("javax.swing.event") + this.getPackage().hasName(javaxOrJakarta() + ".swing.event") ) } } diff --git a/java/ql/src/Likely Bugs/Frameworks/Swing/ThreadSafety.ql b/java/ql/src/Likely Bugs/Frameworks/Swing/ThreadSafety.ql index 8d49cf1d59e..623470aefc1 100644 --- a/java/ql/src/Likely Bugs/Frameworks/Swing/ThreadSafety.ql +++ b/java/ql/src/Likely Bugs/Frameworks/Swing/ThreadSafety.ql @@ -15,7 +15,12 @@ import java from MethodCall ma, Method m, MainMethod main where - ma.getQualifier().getType().getCompilationUnit().getPackage().getName().matches("javax.swing%") and + ma.getQualifier() + .getType() + .getCompilationUnit() + .getPackage() + .getName() + .matches(javaxOrJakarta() + ".swing%") and ( m.hasName("show") and m.hasNoParameters() or diff --git a/java/ql/src/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql b/java/ql/src/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql index 494e851a533..afa08fb6928 100644 --- a/java/ql/src/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql +++ b/java/ql/src/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql @@ -77,7 +77,9 @@ module MatchesHttpOnlyToRawHeaderFlow = TaintTracking::Global] : String | JdbcUrlSSRF.java:54:49:54:53 | props | provenance | Sink:MaD:1 | | JdbcUrlSSRF.java:52:38:52:44 | jdbcUrl : String | JdbcUrlSSRF.java:52:9:52:13 | props : Properties | provenance | Config | -| JdbcUrlSSRF.java:52:38:52:44 | jdbcUrl : String | JdbcUrlSSRF.java:52:9:52:13 | props [post update] : Properties [] : String | provenance | MaD:291 | +| JdbcUrlSSRF.java:52:38:52:44 | jdbcUrl : String | JdbcUrlSSRF.java:52:9:52:13 | props [post update] : Properties [] : String | provenance | MaD:293 | | JdbcUrlSSRF.java:60:26:60:56 | getParameter(...) : String | JdbcUrlSSRF.java:65:27:65:33 | jdbcUrl | provenance | Src:MaD:277 Sink:MaD:257 | | JdbcUrlSSRF.java:60:26:60:56 | getParameter(...) : String | JdbcUrlSSRF.java:67:75:67:81 | jdbcUrl | provenance | Src:MaD:277 Sink:MaD:258 | | JdbcUrlSSRF.java:60:26:60:56 | getParameter(...) : String | JdbcUrlSSRF.java:70:75:70:81 | jdbcUrl | provenance | Src:MaD:277 Sink:MaD:260 | @@ -721,118 +723,130 @@ edges | JdbcUrlSSRF.java:80:26:80:56 | getParameter(...) : String | JdbcUrlSSRF.java:88:19:88:25 | jdbcUrl | provenance | Src:MaD:277 Sink:MaD:240 | | ReactiveWebClientSSRF.java:15:26:15:52 | getParameter(...) : String | ReactiveWebClientSSRF.java:16:52:16:54 | url | provenance | Src:MaD:277 Sink:MaD:274 | | ReactiveWebClientSSRF.java:32:26:32:52 | getParameter(...) : String | ReactiveWebClientSSRF.java:35:30:35:32 | url | provenance | Src:MaD:277 Sink:MaD:273 | -| SanitizationTests.java:21:23:21:58 | new URI(...) : URI | SanitizationTests.java:24:52:24:54 | uri | provenance | Sink:MaD:6 | -| SanitizationTests.java:21:23:21:58 | new URI(...) : URI | SanitizationTests.java:24:52:24:54 | uri : URI | provenance | | -| SanitizationTests.java:21:31:21:57 | getParameter(...) : String | SanitizationTests.java:21:23:21:58 | new URI(...) : URI | provenance | Src:MaD:277 Config | -| SanitizationTests.java:21:31:21:57 | getParameter(...) : String | SanitizationTests.java:21:23:21:58 | new URI(...) : URI | provenance | Src:MaD:277 MaD:285 | -| SanitizationTests.java:24:29:24:55 | newBuilder(...) : Builder | SanitizationTests.java:24:29:24:63 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:24:29:24:63 | build(...) : HttpRequest | SanitizationTests.java:25:25:25:25 | r | provenance | Sink:MaD:4 | -| SanitizationTests.java:24:52:24:54 | uri : URI | SanitizationTests.java:24:29:24:55 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:77:33:77:63 | getParameter(...) : String | SanitizationTests.java:78:67:78:76 | unsafeUri3 : String | provenance | Src:MaD:277 | -| SanitizationTests.java:78:36:78:78 | newBuilder(...) : Builder | SanitizationTests.java:78:36:78:86 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:78:36:78:86 | build(...) : HttpRequest | SanitizationTests.java:79:25:79:32 | unsafer3 | provenance | Sink:MaD:4 | -| SanitizationTests.java:78:59:78:77 | new URI(...) : URI | SanitizationTests.java:78:36:78:78 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:78:67:78:76 | unsafeUri3 : String | SanitizationTests.java:78:59:78:77 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:78:67:78:76 | unsafeUri3 : String | SanitizationTests.java:78:59:78:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:78:67:78:76 | unsafeUri3 : String | SanitizationTests.java:78:59:78:77 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:78:67:78:76 | unsafeUri3 : String | SanitizationTests.java:78:59:78:77 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:81:49:81:79 | getParameter(...) : String | SanitizationTests.java:82:67:82:76 | unsafeUri4 : String | provenance | Src:MaD:277 | -| SanitizationTests.java:82:36:82:78 | newBuilder(...) : Builder | SanitizationTests.java:82:36:82:86 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:82:36:82:86 | build(...) : HttpRequest | SanitizationTests.java:83:25:83:32 | unsafer4 | provenance | Sink:MaD:4 | -| SanitizationTests.java:82:59:82:77 | new URI(...) : URI | SanitizationTests.java:82:36:82:78 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:82:67:82:76 | unsafeUri4 : String | SanitizationTests.java:82:59:82:77 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:82:67:82:76 | unsafeUri4 : String | SanitizationTests.java:82:59:82:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:82:67:82:76 | unsafeUri4 : String | SanitizationTests.java:82:59:82:77 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:82:67:82:76 | unsafeUri4 : String | SanitizationTests.java:82:59:82:77 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:86:13:86:22 | unsafeUri5 [post update] : StringBuilder | SanitizationTests.java:87:67:87:76 | unsafeUri5 : StringBuilder | provenance | | -| SanitizationTests.java:86:31:86:61 | getParameter(...) : String | SanitizationTests.java:86:13:86:22 | unsafeUri5 [post update] : StringBuilder | provenance | Src:MaD:277 MaD:278 | -| SanitizationTests.java:87:36:87:89 | newBuilder(...) : Builder | SanitizationTests.java:87:36:87:97 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:87:36:87:97 | build(...) : HttpRequest | SanitizationTests.java:88:25:88:32 | unsafer5 | provenance | Sink:MaD:4 | -| SanitizationTests.java:87:59:87:88 | new URI(...) : URI | SanitizationTests.java:87:36:87:89 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:87:67:87:76 | unsafeUri5 : StringBuilder | SanitizationTests.java:87:67:87:87 | toString(...) : String | provenance | MaD:280 | -| SanitizationTests.java:87:67:87:87 | toString(...) : String | SanitizationTests.java:87:59:87:88 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:87:67:87:87 | toString(...) : String | SanitizationTests.java:87:59:87:88 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:87:67:87:87 | toString(...) : String | SanitizationTests.java:87:59:87:88 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:87:67:87:87 | toString(...) : String | SanitizationTests.java:87:59:87:88 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:90:40:90:87 | new StringBuilder(...) : StringBuilder | SanitizationTests.java:92:68:92:77 | unafeUri5a : StringBuilder | provenance | | -| SanitizationTests.java:90:58:90:86 | getParameter(...) : String | SanitizationTests.java:90:40:90:87 | new StringBuilder(...) : StringBuilder | provenance | Src:MaD:277 MaD:282 | -| SanitizationTests.java:92:37:92:90 | newBuilder(...) : Builder | SanitizationTests.java:92:37:92:98 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:92:37:92:98 | build(...) : HttpRequest | SanitizationTests.java:93:25:93:33 | unsafer5a | provenance | Sink:MaD:4 | -| SanitizationTests.java:92:60:92:89 | new URI(...) : URI | SanitizationTests.java:92:37:92:90 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:92:68:92:77 | unafeUri5a : StringBuilder | SanitizationTests.java:92:68:92:88 | toString(...) : String | provenance | MaD:280 | -| SanitizationTests.java:92:68:92:88 | toString(...) : String | SanitizationTests.java:92:60:92:89 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:92:68:92:88 | toString(...) : String | SanitizationTests.java:92:60:92:89 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:92:68:92:88 | toString(...) : String | SanitizationTests.java:92:60:92:89 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:92:68:92:88 | toString(...) : String | SanitizationTests.java:92:60:92:89 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:95:41:95:105 | append(...) : StringBuilder | SanitizationTests.java:97:68:97:78 | unsafeUri5b : StringBuilder | provenance | | -| SanitizationTests.java:95:42:95:89 | new StringBuilder(...) : StringBuilder | SanitizationTests.java:95:41:95:105 | append(...) : StringBuilder | provenance | MaD:279 | -| SanitizationTests.java:95:60:95:88 | getParameter(...) : String | SanitizationTests.java:95:42:95:89 | new StringBuilder(...) : StringBuilder | provenance | Src:MaD:277 MaD:282 | -| SanitizationTests.java:97:37:97:91 | newBuilder(...) : Builder | SanitizationTests.java:97:37:97:99 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:97:37:97:99 | build(...) : HttpRequest | SanitizationTests.java:98:25:98:33 | unsafer5b | provenance | Sink:MaD:4 | -| SanitizationTests.java:97:60:97:90 | new URI(...) : URI | SanitizationTests.java:97:37:97:91 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:97:68:97:78 | unsafeUri5b : StringBuilder | SanitizationTests.java:97:68:97:89 | toString(...) : String | provenance | MaD:280 | -| SanitizationTests.java:97:68:97:89 | toString(...) : String | SanitizationTests.java:97:60:97:90 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:97:68:97:89 | toString(...) : String | SanitizationTests.java:97:60:97:90 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:97:68:97:89 | toString(...) : String | SanitizationTests.java:97:60:97:90 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:97:68:97:89 | toString(...) : String | SanitizationTests.java:97:60:97:90 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:100:41:100:106 | append(...) : StringBuilder | SanitizationTests.java:102:68:102:78 | unsafeUri5c : StringBuilder | provenance | | -| SanitizationTests.java:100:77:100:105 | getParameter(...) : String | SanitizationTests.java:100:41:100:106 | append(...) : StringBuilder | provenance | Src:MaD:277 MaD:278+MaD:279 | -| SanitizationTests.java:102:37:102:91 | newBuilder(...) : Builder | SanitizationTests.java:102:37:102:99 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:102:37:102:99 | build(...) : HttpRequest | SanitizationTests.java:103:25:103:33 | unsafer5c | provenance | Sink:MaD:4 | -| SanitizationTests.java:102:60:102:90 | new URI(...) : URI | SanitizationTests.java:102:37:102:91 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:102:68:102:78 | unsafeUri5c : StringBuilder | SanitizationTests.java:102:68:102:89 | toString(...) : String | provenance | MaD:280 | -| SanitizationTests.java:102:68:102:89 | toString(...) : String | SanitizationTests.java:102:60:102:90 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:102:68:102:89 | toString(...) : String | SanitizationTests.java:102:60:102:90 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:102:68:102:89 | toString(...) : String | SanitizationTests.java:102:60:102:90 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:102:68:102:89 | toString(...) : String | SanitizationTests.java:102:60:102:90 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:105:33:105:104 | format(...) : String | SanitizationTests.java:106:67:106:76 | unsafeUri6 : String | provenance | | -| SanitizationTests.java:105:33:105:104 | new ..[] { .. } : Object[] [[]] : String | SanitizationTests.java:105:33:105:104 | format(...) : String | provenance | MaD:281 | -| SanitizationTests.java:105:73:105:103 | getParameter(...) : String | SanitizationTests.java:105:33:105:104 | new ..[] { .. } : Object[] [[]] : String | provenance | Src:MaD:277 | -| SanitizationTests.java:106:36:106:78 | newBuilder(...) : Builder | SanitizationTests.java:106:36:106:86 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:106:36:106:86 | build(...) : HttpRequest | SanitizationTests.java:107:25:107:32 | unsafer6 | provenance | Sink:MaD:4 | -| SanitizationTests.java:106:59:106:77 | new URI(...) : URI | SanitizationTests.java:106:36:106:78 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:106:67:106:76 | unsafeUri6 : String | SanitizationTests.java:106:59:106:77 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:106:67:106:76 | unsafeUri6 : String | SanitizationTests.java:106:59:106:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:106:67:106:76 | unsafeUri6 : String | SanitizationTests.java:106:59:106:77 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:106:67:106:76 | unsafeUri6 : String | SanitizationTests.java:106:59:106:77 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:109:33:109:110 | format(...) : String | SanitizationTests.java:110:67:110:76 | unsafeUri7 : String | provenance | | -| SanitizationTests.java:109:33:109:110 | new ..[] { .. } : Object[] [[]] : String | SanitizationTests.java:109:33:109:110 | format(...) : String | provenance | MaD:281 | -| SanitizationTests.java:109:56:109:86 | getParameter(...) : String | SanitizationTests.java:109:33:109:110 | new ..[] { .. } : Object[] [[]] : String | provenance | Src:MaD:277 | -| SanitizationTests.java:110:36:110:78 | newBuilder(...) : Builder | SanitizationTests.java:110:36:110:86 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:110:36:110:86 | build(...) : HttpRequest | SanitizationTests.java:111:25:111:32 | unsafer7 | provenance | Sink:MaD:4 | -| SanitizationTests.java:110:59:110:77 | new URI(...) : URI | SanitizationTests.java:110:36:110:78 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:110:67:110:76 | unsafeUri7 : String | SanitizationTests.java:110:59:110:77 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:110:67:110:76 | unsafeUri7 : String | SanitizationTests.java:110:59:110:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:110:67:110:76 | unsafeUri7 : String | SanitizationTests.java:110:59:110:77 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:110:67:110:76 | unsafeUri7 : String | SanitizationTests.java:110:59:110:77 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:113:33:113:110 | format(...) : String | SanitizationTests.java:114:67:114:76 | unsafeUri8 : String | provenance | | -| SanitizationTests.java:113:33:113:110 | new ..[] { .. } : Object[] [[]] : String | SanitizationTests.java:113:33:113:110 | format(...) : String | provenance | MaD:281 | -| SanitizationTests.java:113:55:113:85 | getParameter(...) : String | SanitizationTests.java:113:33:113:110 | new ..[] { .. } : Object[] [[]] : String | provenance | Src:MaD:277 | -| SanitizationTests.java:114:36:114:78 | newBuilder(...) : Builder | SanitizationTests.java:114:36:114:86 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:114:36:114:86 | build(...) : HttpRequest | SanitizationTests.java:115:25:115:32 | unsafer8 | provenance | Sink:MaD:4 | -| SanitizationTests.java:114:59:114:77 | new URI(...) : URI | SanitizationTests.java:114:36:114:78 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:114:67:114:76 | unsafeUri8 : String | SanitizationTests.java:114:59:114:77 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:114:67:114:76 | unsafeUri8 : String | SanitizationTests.java:114:59:114:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:114:67:114:76 | unsafeUri8 : String | SanitizationTests.java:114:59:114:77 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:114:67:114:76 | unsafeUri8 : String | SanitizationTests.java:114:59:114:77 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:117:33:117:63 | getParameter(...) : String | SanitizationTests.java:118:67:118:76 | unsafeUri9 : String | provenance | Src:MaD:277 | -| SanitizationTests.java:118:36:118:78 | newBuilder(...) : Builder | SanitizationTests.java:118:36:118:86 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:118:36:118:86 | build(...) : HttpRequest | SanitizationTests.java:119:25:119:32 | unsafer9 | provenance | Sink:MaD:4 | -| SanitizationTests.java:118:59:118:77 | new URI(...) : URI | SanitizationTests.java:118:36:118:78 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:118:67:118:76 | unsafeUri9 : String | SanitizationTests.java:118:59:118:77 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:118:67:118:76 | unsafeUri9 : String | SanitizationTests.java:118:59:118:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:118:67:118:76 | unsafeUri9 : String | SanitizationTests.java:118:59:118:77 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:118:67:118:76 | unsafeUri9 : String | SanitizationTests.java:118:59:118:77 | new URI(...) : URI | provenance | MaD:285 | -| SanitizationTests.java:121:34:121:126 | format(...) : String | SanitizationTests.java:122:68:122:78 | unsafeUri10 : String | provenance | | -| SanitizationTests.java:121:34:121:126 | new ..[] { .. } : Object[] [[]] : String | SanitizationTests.java:121:34:121:126 | format(...) : String | provenance | MaD:281 | -| SanitizationTests.java:121:94:121:125 | getParameter(...) : String | SanitizationTests.java:121:34:121:126 | new ..[] { .. } : Object[] [[]] : String | provenance | Src:MaD:277 | -| SanitizationTests.java:122:37:122:80 | newBuilder(...) : Builder | SanitizationTests.java:122:37:122:88 | build(...) : HttpRequest | provenance | MaD:283 | -| SanitizationTests.java:122:37:122:88 | build(...) : HttpRequest | SanitizationTests.java:123:25:123:33 | unsafer10 | provenance | Sink:MaD:4 | -| SanitizationTests.java:122:60:122:79 | new URI(...) : URI | SanitizationTests.java:122:37:122:80 | newBuilder(...) : Builder | provenance | MaD:284 | -| SanitizationTests.java:122:68:122:78 | unsafeUri10 : String | SanitizationTests.java:122:60:122:79 | new URI(...) | provenance | Config Sink:MaD:6 | -| SanitizationTests.java:122:68:122:78 | unsafeUri10 : String | SanitizationTests.java:122:60:122:79 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | -| SanitizationTests.java:122:68:122:78 | unsafeUri10 : String | SanitizationTests.java:122:60:122:79 | new URI(...) : URI | provenance | Config | -| SanitizationTests.java:122:68:122:78 | unsafeUri10 : String | SanitizationTests.java:122:60:122:79 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:22:23:22:58 | new URI(...) : URI | SanitizationTests.java:25:52:25:54 | uri | provenance | Sink:MaD:6 | +| SanitizationTests.java:22:23:22:58 | new URI(...) : URI | SanitizationTests.java:25:52:25:54 | uri : URI | provenance | | +| SanitizationTests.java:22:31:22:57 | getParameter(...) : String | SanitizationTests.java:22:23:22:58 | new URI(...) : URI | provenance | Src:MaD:277 Config | +| SanitizationTests.java:22:31:22:57 | getParameter(...) : String | SanitizationTests.java:22:23:22:58 | new URI(...) : URI | provenance | Src:MaD:277 MaD:285 | +| SanitizationTests.java:25:29:25:55 | newBuilder(...) : Builder | SanitizationTests.java:25:29:25:63 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:25:29:25:63 | build(...) : HttpRequest | SanitizationTests.java:26:25:26:25 | r | provenance | Sink:MaD:4 | +| SanitizationTests.java:25:52:25:54 | uri : URI | SanitizationTests.java:25:29:25:55 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:78:33:78:63 | getParameter(...) : String | SanitizationTests.java:79:67:79:76 | unsafeUri3 : String | provenance | Src:MaD:277 | +| SanitizationTests.java:79:36:79:78 | newBuilder(...) : Builder | SanitizationTests.java:79:36:79:86 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:79:36:79:86 | build(...) : HttpRequest | SanitizationTests.java:80:25:80:32 | unsafer3 | provenance | Sink:MaD:4 | +| SanitizationTests.java:79:59:79:77 | new URI(...) : URI | SanitizationTests.java:79:36:79:78 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:79:67:79:76 | unsafeUri3 : String | SanitizationTests.java:79:59:79:77 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:79:67:79:76 | unsafeUri3 : String | SanitizationTests.java:79:59:79:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:79:67:79:76 | unsafeUri3 : String | SanitizationTests.java:79:59:79:77 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:79:67:79:76 | unsafeUri3 : String | SanitizationTests.java:79:59:79:77 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:82:49:82:79 | getParameter(...) : String | SanitizationTests.java:83:67:83:76 | unsafeUri4 : String | provenance | Src:MaD:277 | +| SanitizationTests.java:83:36:83:78 | newBuilder(...) : Builder | SanitizationTests.java:83:36:83:86 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:83:36:83:86 | build(...) : HttpRequest | SanitizationTests.java:84:25:84:32 | unsafer4 | provenance | Sink:MaD:4 | +| SanitizationTests.java:83:59:83:77 | new URI(...) : URI | SanitizationTests.java:83:36:83:78 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:83:67:83:76 | unsafeUri4 : String | SanitizationTests.java:83:59:83:77 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:83:67:83:76 | unsafeUri4 : String | SanitizationTests.java:83:59:83:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:83:67:83:76 | unsafeUri4 : String | SanitizationTests.java:83:59:83:77 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:83:67:83:76 | unsafeUri4 : String | SanitizationTests.java:83:59:83:77 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:87:13:87:22 | unsafeUri5 [post update] : StringBuilder | SanitizationTests.java:88:67:88:76 | unsafeUri5 : StringBuilder | provenance | | +| SanitizationTests.java:87:31:87:61 | getParameter(...) : String | SanitizationTests.java:87:13:87:22 | unsafeUri5 [post update] : StringBuilder | provenance | Src:MaD:277 MaD:278 | +| SanitizationTests.java:88:36:88:89 | newBuilder(...) : Builder | SanitizationTests.java:88:36:88:97 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:88:36:88:97 | build(...) : HttpRequest | SanitizationTests.java:89:25:89:32 | unsafer5 | provenance | Sink:MaD:4 | +| SanitizationTests.java:88:59:88:88 | new URI(...) : URI | SanitizationTests.java:88:36:88:89 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:88:67:88:76 | unsafeUri5 : StringBuilder | SanitizationTests.java:88:67:88:87 | toString(...) : String | provenance | MaD:280 | +| SanitizationTests.java:88:67:88:87 | toString(...) : String | SanitizationTests.java:88:59:88:88 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:88:67:88:87 | toString(...) : String | SanitizationTests.java:88:59:88:88 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:88:67:88:87 | toString(...) : String | SanitizationTests.java:88:59:88:88 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:88:67:88:87 | toString(...) : String | SanitizationTests.java:88:59:88:88 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:91:40:91:87 | new StringBuilder(...) : StringBuilder | SanitizationTests.java:93:68:93:77 | unafeUri5a : StringBuilder | provenance | | +| SanitizationTests.java:91:58:91:86 | getParameter(...) : String | SanitizationTests.java:91:40:91:87 | new StringBuilder(...) : StringBuilder | provenance | Src:MaD:277 MaD:282 | +| SanitizationTests.java:93:37:93:90 | newBuilder(...) : Builder | SanitizationTests.java:93:37:93:98 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:93:37:93:98 | build(...) : HttpRequest | SanitizationTests.java:94:25:94:33 | unsafer5a | provenance | Sink:MaD:4 | +| SanitizationTests.java:93:60:93:89 | new URI(...) : URI | SanitizationTests.java:93:37:93:90 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:93:68:93:77 | unafeUri5a : StringBuilder | SanitizationTests.java:93:68:93:88 | toString(...) : String | provenance | MaD:280 | +| SanitizationTests.java:93:68:93:88 | toString(...) : String | SanitizationTests.java:93:60:93:89 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:93:68:93:88 | toString(...) : String | SanitizationTests.java:93:60:93:89 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:93:68:93:88 | toString(...) : String | SanitizationTests.java:93:60:93:89 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:93:68:93:88 | toString(...) : String | SanitizationTests.java:93:60:93:89 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:96:41:96:105 | append(...) : StringBuilder | SanitizationTests.java:98:68:98:78 | unsafeUri5b : StringBuilder | provenance | | +| SanitizationTests.java:96:42:96:89 | new StringBuilder(...) : StringBuilder | SanitizationTests.java:96:41:96:105 | append(...) : StringBuilder | provenance | MaD:279 | +| SanitizationTests.java:96:60:96:88 | getParameter(...) : String | SanitizationTests.java:96:42:96:89 | new StringBuilder(...) : StringBuilder | provenance | Src:MaD:277 MaD:282 | +| SanitizationTests.java:98:37:98:91 | newBuilder(...) : Builder | SanitizationTests.java:98:37:98:99 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:98:37:98:99 | build(...) : HttpRequest | SanitizationTests.java:99:25:99:33 | unsafer5b | provenance | Sink:MaD:4 | +| SanitizationTests.java:98:60:98:90 | new URI(...) : URI | SanitizationTests.java:98:37:98:91 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:98:68:98:78 | unsafeUri5b : StringBuilder | SanitizationTests.java:98:68:98:89 | toString(...) : String | provenance | MaD:280 | +| SanitizationTests.java:98:68:98:89 | toString(...) : String | SanitizationTests.java:98:60:98:90 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:98:68:98:89 | toString(...) : String | SanitizationTests.java:98:60:98:90 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:98:68:98:89 | toString(...) : String | SanitizationTests.java:98:60:98:90 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:98:68:98:89 | toString(...) : String | SanitizationTests.java:98:60:98:90 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:101:41:101:106 | append(...) : StringBuilder | SanitizationTests.java:103:68:103:78 | unsafeUri5c : StringBuilder | provenance | | +| SanitizationTests.java:101:77:101:105 | getParameter(...) : String | SanitizationTests.java:101:41:101:106 | append(...) : StringBuilder | provenance | Src:MaD:277 MaD:278+MaD:279 | +| SanitizationTests.java:103:37:103:91 | newBuilder(...) : Builder | SanitizationTests.java:103:37:103:99 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:103:37:103:99 | build(...) : HttpRequest | SanitizationTests.java:104:25:104:33 | unsafer5c | provenance | Sink:MaD:4 | +| SanitizationTests.java:103:60:103:90 | new URI(...) : URI | SanitizationTests.java:103:37:103:91 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:103:68:103:78 | unsafeUri5c : StringBuilder | SanitizationTests.java:103:68:103:89 | toString(...) : String | provenance | MaD:280 | +| SanitizationTests.java:103:68:103:89 | toString(...) : String | SanitizationTests.java:103:60:103:90 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:103:68:103:89 | toString(...) : String | SanitizationTests.java:103:60:103:90 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:103:68:103:89 | toString(...) : String | SanitizationTests.java:103:60:103:90 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:103:68:103:89 | toString(...) : String | SanitizationTests.java:103:60:103:90 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:106:33:106:104 | format(...) : String | SanitizationTests.java:107:67:107:76 | unsafeUri6 : String | provenance | | +| SanitizationTests.java:106:33:106:104 | new ..[] { .. } : Object[] [[]] : String | SanitizationTests.java:106:33:106:104 | format(...) : String | provenance | MaD:281 | +| SanitizationTests.java:106:73:106:103 | getParameter(...) : String | SanitizationTests.java:106:33:106:104 | new ..[] { .. } : Object[] [[]] : String | provenance | Src:MaD:277 | +| SanitizationTests.java:107:36:107:78 | newBuilder(...) : Builder | SanitizationTests.java:107:36:107:86 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:107:36:107:86 | build(...) : HttpRequest | SanitizationTests.java:108:25:108:32 | unsafer6 | provenance | Sink:MaD:4 | +| SanitizationTests.java:107:59:107:77 | new URI(...) : URI | SanitizationTests.java:107:36:107:78 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:107:67:107:76 | unsafeUri6 : String | SanitizationTests.java:107:59:107:77 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:107:67:107:76 | unsafeUri6 : String | SanitizationTests.java:107:59:107:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:107:67:107:76 | unsafeUri6 : String | SanitizationTests.java:107:59:107:77 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:107:67:107:76 | unsafeUri6 : String | SanitizationTests.java:107:59:107:77 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:110:33:110:110 | format(...) : String | SanitizationTests.java:111:67:111:76 | unsafeUri7 : String | provenance | | +| SanitizationTests.java:110:33:110:110 | new ..[] { .. } : Object[] [[]] : String | SanitizationTests.java:110:33:110:110 | format(...) : String | provenance | MaD:281 | +| SanitizationTests.java:110:56:110:86 | getParameter(...) : String | SanitizationTests.java:110:33:110:110 | new ..[] { .. } : Object[] [[]] : String | provenance | Src:MaD:277 | +| SanitizationTests.java:111:36:111:78 | newBuilder(...) : Builder | SanitizationTests.java:111:36:111:86 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:111:36:111:86 | build(...) : HttpRequest | SanitizationTests.java:112:25:112:32 | unsafer7 | provenance | Sink:MaD:4 | +| SanitizationTests.java:111:59:111:77 | new URI(...) : URI | SanitizationTests.java:111:36:111:78 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:111:67:111:76 | unsafeUri7 : String | SanitizationTests.java:111:59:111:77 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:111:67:111:76 | unsafeUri7 : String | SanitizationTests.java:111:59:111:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:111:67:111:76 | unsafeUri7 : String | SanitizationTests.java:111:59:111:77 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:111:67:111:76 | unsafeUri7 : String | SanitizationTests.java:111:59:111:77 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:114:33:114:110 | format(...) : String | SanitizationTests.java:115:67:115:76 | unsafeUri8 : String | provenance | | +| SanitizationTests.java:114:33:114:110 | new ..[] { .. } : Object[] [[]] : String | SanitizationTests.java:114:33:114:110 | format(...) : String | provenance | MaD:281 | +| SanitizationTests.java:114:55:114:85 | getParameter(...) : String | SanitizationTests.java:114:33:114:110 | new ..[] { .. } : Object[] [[]] : String | provenance | Src:MaD:277 | +| SanitizationTests.java:115:36:115:78 | newBuilder(...) : Builder | SanitizationTests.java:115:36:115:86 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:115:36:115:86 | build(...) : HttpRequest | SanitizationTests.java:116:25:116:32 | unsafer8 | provenance | Sink:MaD:4 | +| SanitizationTests.java:115:59:115:77 | new URI(...) : URI | SanitizationTests.java:115:36:115:78 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:115:67:115:76 | unsafeUri8 : String | SanitizationTests.java:115:59:115:77 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:115:67:115:76 | unsafeUri8 : String | SanitizationTests.java:115:59:115:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:115:67:115:76 | unsafeUri8 : String | SanitizationTests.java:115:59:115:77 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:115:67:115:76 | unsafeUri8 : String | SanitizationTests.java:115:59:115:77 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:118:33:118:63 | getParameter(...) : String | SanitizationTests.java:119:67:119:76 | unsafeUri9 : String | provenance | Src:MaD:277 | +| SanitizationTests.java:119:36:119:78 | newBuilder(...) : Builder | SanitizationTests.java:119:36:119:86 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:119:36:119:86 | build(...) : HttpRequest | SanitizationTests.java:120:25:120:32 | unsafer9 | provenance | Sink:MaD:4 | +| SanitizationTests.java:119:59:119:77 | new URI(...) : URI | SanitizationTests.java:119:36:119:78 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:119:67:119:76 | unsafeUri9 : String | SanitizationTests.java:119:59:119:77 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:119:67:119:76 | unsafeUri9 : String | SanitizationTests.java:119:59:119:77 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:119:67:119:76 | unsafeUri9 : String | SanitizationTests.java:119:59:119:77 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:119:67:119:76 | unsafeUri9 : String | SanitizationTests.java:119:59:119:77 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:122:34:122:126 | format(...) : String | SanitizationTests.java:123:68:123:78 | unsafeUri10 : String | provenance | | +| SanitizationTests.java:122:34:122:126 | new ..[] { .. } : Object[] [[]] : String | SanitizationTests.java:122:34:122:126 | format(...) : String | provenance | MaD:281 | +| SanitizationTests.java:122:94:122:125 | getParameter(...) : String | SanitizationTests.java:122:34:122:126 | new ..[] { .. } : Object[] [[]] : String | provenance | Src:MaD:277 | +| SanitizationTests.java:123:37:123:80 | newBuilder(...) : Builder | SanitizationTests.java:123:37:123:88 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:123:37:123:88 | build(...) : HttpRequest | SanitizationTests.java:124:25:124:33 | unsafer10 | provenance | Sink:MaD:4 | +| SanitizationTests.java:123:60:123:79 | new URI(...) : URI | SanitizationTests.java:123:37:123:80 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:123:68:123:78 | unsafeUri10 : String | SanitizationTests.java:123:60:123:79 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:123:68:123:78 | unsafeUri10 : String | SanitizationTests.java:123:60:123:79 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:123:68:123:78 | unsafeUri10 : String | SanitizationTests.java:123:60:123:79 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:123:68:123:78 | unsafeUri10 : String | SanitizationTests.java:123:60:123:79 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:177:31:177:114 | newBuilder(...) : Builder | SanitizationTests.java:177:31:177:122 | build(...) : HttpRequest | provenance | MaD:283 | +| SanitizationTests.java:177:31:177:122 | build(...) : HttpRequest | SanitizationTests.java:178:25:178:27 | r18 | provenance | Sink:MaD:4 | +| SanitizationTests.java:177:54:177:113 | new URI(...) : URI | SanitizationTests.java:177:31:177:114 | newBuilder(...) : Builder | provenance | MaD:284 | +| SanitizationTests.java:177:62:177:112 | getFromList(...) : String | SanitizationTests.java:177:54:177:113 | new URI(...) | provenance | Config Sink:MaD:6 | +| SanitizationTests.java:177:62:177:112 | getFromList(...) : String | SanitizationTests.java:177:54:177:113 | new URI(...) | provenance | MaD:285 Sink:MaD:6 | +| SanitizationTests.java:177:62:177:112 | getFromList(...) : String | SanitizationTests.java:177:54:177:113 | new URI(...) : URI | provenance | Config | +| SanitizationTests.java:177:62:177:112 | getFromList(...) : String | SanitizationTests.java:177:54:177:113 | new URI(...) : URI | provenance | MaD:285 | +| SanitizationTests.java:177:74:177:111 | of(...) : List [] : String | SanitizationTests.java:177:62:177:112 | getFromList(...) : String | provenance | MaD:290 | +| SanitizationTests.java:177:74:177:111 | of(...) : List [] : String | SanitizationTests.java:199:31:199:112 | list : List [] : String | provenance | | +| SanitizationTests.java:177:82:177:110 | getParameter(...) : String | SanitizationTests.java:177:74:177:111 | of(...) : List [] : String | provenance | Src:MaD:277 MaD:289 | +| SanitizationTests.java:199:31:199:112 | list : List [] : String | SanitizationTests.java:200:16:200:19 | list : List [] : String | provenance | | +| SanitizationTests.java:200:16:200:19 | list : List [] : String | SanitizationTests.java:200:16:200:26 | get(...) : String | provenance | MaD:290 | | SpringSSRF.java:28:33:28:60 | getParameter(...) : String | SpringSSRF.java:32:39:32:59 | ... + ... | provenance | Src:MaD:277 Sink:MaD:264 | | SpringSSRF.java:28:33:28:60 | getParameter(...) : String | SpringSSRF.java:33:69:33:82 | fooResourceUrl | provenance | Src:MaD:277 | | SpringSSRF.java:28:33:28:60 | getParameter(...) : String | SpringSSRF.java:34:73:34:86 | fooResourceUrl | provenance | Src:MaD:277 | @@ -864,16 +878,16 @@ edges | SpringSSRF.java:28:33:28:60 | getParameter(...) : String | SpringSSRF.java:82:107:82:120 | fooResourceUrl : String | provenance | Src:MaD:277 | | SpringSSRF.java:28:33:28:60 | getParameter(...) : String | SpringSSRF.java:84:129:84:142 | fooResourceUrl : String | provenance | Src:MaD:277 | | SpringSSRF.java:28:33:28:60 | getParameter(...) : String | SpringSSRF.java:87:48:87:61 | fooResourceUrl : String | provenance | Src:MaD:277 | -| SpringSSRF.java:38:83:38:96 | fooResourceUrl : String | SpringSSRF.java:38:69:38:97 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:40:105:40:118 | fooResourceUrl : String | SpringSSRF.java:40:69:40:119 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:49:105:49:118 | fooResourceUrl : String | SpringSSRF.java:49:91:49:119 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:51:127:51:140 | fooResourceUrl : String | SpringSSRF.java:51:91:51:141 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:60:93:60:106 | fooResourceUrl : String | SpringSSRF.java:60:79:60:107 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:62:115:62:128 | fooResourceUrl : String | SpringSSRF.java:62:79:62:129 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:71:83:71:96 | fooResourceUrl : String | SpringSSRF.java:71:69:71:97 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:73:105:73:118 | fooResourceUrl : String | SpringSSRF.java:73:69:73:119 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:82:107:82:120 | fooResourceUrl : String | SpringSSRF.java:82:93:82:121 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:84:129:84:142 | fooResourceUrl : String | SpringSSRF.java:84:93:84:143 | of(...) | provenance | MaD:290 | +| SpringSSRF.java:38:83:38:96 | fooResourceUrl : String | SpringSSRF.java:38:69:38:97 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:40:105:40:118 | fooResourceUrl : String | SpringSSRF.java:40:69:40:119 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:49:105:49:118 | fooResourceUrl : String | SpringSSRF.java:49:91:49:119 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:51:127:51:140 | fooResourceUrl : String | SpringSSRF.java:51:91:51:141 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:60:93:60:106 | fooResourceUrl : String | SpringSSRF.java:60:79:60:107 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:62:115:62:128 | fooResourceUrl : String | SpringSSRF.java:62:79:62:129 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:71:83:71:96 | fooResourceUrl : String | SpringSSRF.java:71:69:71:97 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:73:105:73:118 | fooResourceUrl : String | SpringSSRF.java:73:69:73:119 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:82:107:82:120 | fooResourceUrl : String | SpringSSRF.java:82:93:82:121 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:84:129:84:142 | fooResourceUrl : String | SpringSSRF.java:84:93:84:143 | of(...) | provenance | MaD:292 | | SpringSSRF.java:87:48:87:61 | fooResourceUrl : String | SpringSSRF.java:87:40:87:62 | new URI(...) | provenance | Config Sink:MaD:269 | | SpringSSRF.java:87:48:87:61 | fooResourceUrl : String | SpringSSRF.java:87:40:87:62 | new URI(...) | provenance | MaD:285 Sink:MaD:269 | | SpringSSRF.java:87:48:87:61 | fooResourceUrl : String | SpringSSRF.java:88:92:88:105 | fooResourceUrl | provenance | | @@ -918,20 +932,20 @@ edges | SpringSSRF.java:87:48:87:61 | fooResourceUrl : String | SpringSSRF.java:159:72:159:85 | fooResourceUrl : String | provenance | | | SpringSSRF.java:87:48:87:61 | fooResourceUrl : String | SpringSSRF.java:161:94:161:107 | fooResourceUrl : String | provenance | | | SpringSSRF.java:87:48:87:61 | fooResourceUrl : String | SpringSSRF.java:166:35:166:48 | fooResourceUrl : String | provenance | | -| SpringSSRF.java:93:106:93:119 | fooResourceUrl : String | SpringSSRF.java:93:92:93:120 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:95:128:95:141 | fooResourceUrl : String | SpringSSRF.java:95:92:95:142 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:104:94:104:107 | fooResourceUrl : String | SpringSSRF.java:104:80:104:108 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:106:116:106:129 | fooResourceUrl : String | SpringSSRF.java:106:80:106:130 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:115:106:115:119 | fooResourceUrl : String | SpringSSRF.java:115:92:115:120 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:117:128:117:141 | fooResourceUrl : String | SpringSSRF.java:117:92:117:142 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:126:82:126:95 | fooResourceUrl : String | SpringSSRF.java:126:68:126:96 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:128:104:128:117 | fooResourceUrl : String | SpringSSRF.java:128:68:128:118 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:137:63:137:76 | fooResourceUrl : String | SpringSSRF.java:137:49:137:77 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:139:85:139:98 | fooResourceUrl : String | SpringSSRF.java:139:49:139:99 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:148:71:148:84 | fooResourceUrl : String | SpringSSRF.java:148:57:148:85 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:150:93:150:106 | fooResourceUrl : String | SpringSSRF.java:150:57:150:107 | of(...) | provenance | MaD:290 | -| SpringSSRF.java:159:72:159:85 | fooResourceUrl : String | SpringSSRF.java:159:58:159:86 | of(...) | provenance | MaD:289 | -| SpringSSRF.java:161:94:161:107 | fooResourceUrl : String | SpringSSRF.java:161:58:161:108 | of(...) | provenance | MaD:290 | +| SpringSSRF.java:93:106:93:119 | fooResourceUrl : String | SpringSSRF.java:93:92:93:120 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:95:128:95:141 | fooResourceUrl : String | SpringSSRF.java:95:92:95:142 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:104:94:104:107 | fooResourceUrl : String | SpringSSRF.java:104:80:104:108 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:106:116:106:129 | fooResourceUrl : String | SpringSSRF.java:106:80:106:130 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:115:106:115:119 | fooResourceUrl : String | SpringSSRF.java:115:92:115:120 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:117:128:117:141 | fooResourceUrl : String | SpringSSRF.java:117:92:117:142 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:126:82:126:95 | fooResourceUrl : String | SpringSSRF.java:126:68:126:96 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:128:104:128:117 | fooResourceUrl : String | SpringSSRF.java:128:68:128:118 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:137:63:137:76 | fooResourceUrl : String | SpringSSRF.java:137:49:137:77 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:139:85:139:98 | fooResourceUrl : String | SpringSSRF.java:139:49:139:99 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:148:71:148:84 | fooResourceUrl : String | SpringSSRF.java:148:57:148:85 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:150:93:150:106 | fooResourceUrl : String | SpringSSRF.java:150:57:150:107 | of(...) | provenance | MaD:292 | +| SpringSSRF.java:159:72:159:85 | fooResourceUrl : String | SpringSSRF.java:159:58:159:86 | of(...) | provenance | MaD:291 | +| SpringSSRF.java:161:94:161:107 | fooResourceUrl : String | SpringSSRF.java:161:58:161:108 | of(...) | provenance | MaD:292 | | SpringSSRF.java:166:27:166:49 | new URI(...) : URI | SpringSSRF.java:168:44:168:46 | uri | provenance | Sink:MaD:255 | | SpringSSRF.java:166:27:166:49 | new URI(...) : URI | SpringSSRF.java:170:35:170:37 | uri | provenance | Sink:MaD:250 | | SpringSSRF.java:166:27:166:49 | new URI(...) : URI | SpringSSRF.java:171:35:171:37 | uri | provenance | Sink:MaD:256 | @@ -1352,11 +1366,13 @@ models | 286 | Summary: java.net; URI; false; toString; ; ; Argument[this]; ReturnValue; taint; manual | | 287 | Summary: java.net; URI; false; toURL; ; ; Argument[this]; ReturnValue; taint; manual | | 288 | Summary: java.net; URL; false; URL; (String); ; Argument[0]; Argument[this]; taint; manual | -| 289 | Summary: java.util; Map; false; of; ; ; Argument[1]; ReturnValue.MapValue; value; manual | -| 290 | Summary: java.util; Map; false; of; ; ; Argument[3]; ReturnValue.MapValue; value; manual | -| 291 | Summary: java.util; Properties; true; setProperty; (String,String); ; Argument[1]; Argument[this].MapValue; value; manual | -| 292 | Summary: org.apache.hc.core5.http; HttpHost; true; HttpHost; (String); ; Argument[0]; Argument[this]; taint; hq-manual | -| 293 | Summary: org.apache.http.message; BasicRequestLine; false; BasicRequestLine; ; ; Argument[1]; Argument[this]; taint; manual | +| 289 | Summary: java.util; List; false; of; (Object); ; Argument[0]; ReturnValue.Element; value; manual | +| 290 | Summary: java.util; List; true; get; (int); ; Argument[this].Element; ReturnValue; value; manual | +| 291 | Summary: java.util; Map; false; of; ; ; Argument[1]; ReturnValue.MapValue; value; manual | +| 292 | Summary: java.util; Map; false; of; ; ; Argument[3]; ReturnValue.MapValue; value; manual | +| 293 | Summary: java.util; Properties; true; setProperty; (String,String); ; Argument[1]; Argument[this].MapValue; value; manual | +| 294 | Summary: org.apache.hc.core5.http; HttpHost; true; HttpHost; (String); ; Argument[0]; Argument[this]; taint; hq-manual | +| 295 | Summary: org.apache.http.message; BasicRequestLine; false; BasicRequestLine; ; ; Argument[1]; Argument[this]; taint; manual | nodes | ApacheHttpSSRF.java:27:27:27:53 | getParameter(...) : String | semmle.label | getParameter(...) : String | | ApacheHttpSSRF.java:28:23:28:35 | new URI(...) : URI | semmle.label | new URI(...) : URI | @@ -1714,107 +1730,118 @@ nodes | ReactiveWebClientSSRF.java:16:52:16:54 | url | semmle.label | url | | ReactiveWebClientSSRF.java:32:26:32:52 | getParameter(...) : String | semmle.label | getParameter(...) : String | | ReactiveWebClientSSRF.java:35:30:35:32 | url | semmle.label | url | -| SanitizationTests.java:21:23:21:58 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:21:31:21:57 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:24:29:24:55 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:24:29:24:63 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:24:52:24:54 | uri | semmle.label | uri | -| SanitizationTests.java:24:52:24:54 | uri : URI | semmle.label | uri : URI | -| SanitizationTests.java:25:25:25:25 | r | semmle.label | r | -| SanitizationTests.java:77:33:77:63 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:78:36:78:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:78:36:78:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:78:59:78:77 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:78:59:78:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:78:67:78:76 | unsafeUri3 : String | semmle.label | unsafeUri3 : String | -| SanitizationTests.java:79:25:79:32 | unsafer3 | semmle.label | unsafer3 | -| SanitizationTests.java:81:49:81:79 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:82:36:82:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:82:36:82:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:82:59:82:77 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:82:59:82:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:82:67:82:76 | unsafeUri4 : String | semmle.label | unsafeUri4 : String | -| SanitizationTests.java:83:25:83:32 | unsafer4 | semmle.label | unsafer4 | -| SanitizationTests.java:86:13:86:22 | unsafeUri5 [post update] : StringBuilder | semmle.label | unsafeUri5 [post update] : StringBuilder | -| SanitizationTests.java:86:31:86:61 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:87:36:87:89 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:87:36:87:97 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:87:59:87:88 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:87:59:87:88 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:87:67:87:76 | unsafeUri5 : StringBuilder | semmle.label | unsafeUri5 : StringBuilder | -| SanitizationTests.java:87:67:87:87 | toString(...) : String | semmle.label | toString(...) : String | -| SanitizationTests.java:88:25:88:32 | unsafer5 | semmle.label | unsafer5 | -| SanitizationTests.java:90:40:90:87 | new StringBuilder(...) : StringBuilder | semmle.label | new StringBuilder(...) : StringBuilder | -| SanitizationTests.java:90:58:90:86 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:92:37:92:90 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:92:37:92:98 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:92:60:92:89 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:92:60:92:89 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:92:68:92:77 | unafeUri5a : StringBuilder | semmle.label | unafeUri5a : StringBuilder | -| SanitizationTests.java:92:68:92:88 | toString(...) : String | semmle.label | toString(...) : String | -| SanitizationTests.java:93:25:93:33 | unsafer5a | semmle.label | unsafer5a | -| SanitizationTests.java:95:41:95:105 | append(...) : StringBuilder | semmle.label | append(...) : StringBuilder | -| SanitizationTests.java:95:42:95:89 | new StringBuilder(...) : StringBuilder | semmle.label | new StringBuilder(...) : StringBuilder | -| SanitizationTests.java:95:60:95:88 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:97:37:97:91 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:97:37:97:99 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:97:60:97:90 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:97:60:97:90 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:97:68:97:78 | unsafeUri5b : StringBuilder | semmle.label | unsafeUri5b : StringBuilder | -| SanitizationTests.java:97:68:97:89 | toString(...) : String | semmle.label | toString(...) : String | -| SanitizationTests.java:98:25:98:33 | unsafer5b | semmle.label | unsafer5b | -| SanitizationTests.java:100:41:100:106 | append(...) : StringBuilder | semmle.label | append(...) : StringBuilder | -| SanitizationTests.java:100:77:100:105 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:102:37:102:91 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:102:37:102:99 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:102:60:102:90 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:102:60:102:90 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:102:68:102:78 | unsafeUri5c : StringBuilder | semmle.label | unsafeUri5c : StringBuilder | -| SanitizationTests.java:102:68:102:89 | toString(...) : String | semmle.label | toString(...) : String | -| SanitizationTests.java:103:25:103:33 | unsafer5c | semmle.label | unsafer5c | -| SanitizationTests.java:105:33:105:104 | format(...) : String | semmle.label | format(...) : String | -| SanitizationTests.java:105:33:105:104 | new ..[] { .. } : Object[] [[]] : String | semmle.label | new ..[] { .. } : Object[] [[]] : String | -| SanitizationTests.java:105:73:105:103 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:106:36:106:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:106:36:106:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:106:59:106:77 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:106:59:106:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:106:67:106:76 | unsafeUri6 : String | semmle.label | unsafeUri6 : String | -| SanitizationTests.java:107:25:107:32 | unsafer6 | semmle.label | unsafer6 | -| SanitizationTests.java:109:33:109:110 | format(...) : String | semmle.label | format(...) : String | -| SanitizationTests.java:109:33:109:110 | new ..[] { .. } : Object[] [[]] : String | semmle.label | new ..[] { .. } : Object[] [[]] : String | -| SanitizationTests.java:109:56:109:86 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:110:36:110:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:110:36:110:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:110:59:110:77 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:110:59:110:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:110:67:110:76 | unsafeUri7 : String | semmle.label | unsafeUri7 : String | -| SanitizationTests.java:111:25:111:32 | unsafer7 | semmle.label | unsafer7 | -| SanitizationTests.java:113:33:113:110 | format(...) : String | semmle.label | format(...) : String | -| SanitizationTests.java:113:33:113:110 | new ..[] { .. } : Object[] [[]] : String | semmle.label | new ..[] { .. } : Object[] [[]] : String | -| SanitizationTests.java:113:55:113:85 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:114:36:114:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:114:36:114:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:114:59:114:77 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:114:59:114:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:114:67:114:76 | unsafeUri8 : String | semmle.label | unsafeUri8 : String | -| SanitizationTests.java:115:25:115:32 | unsafer8 | semmle.label | unsafer8 | -| SanitizationTests.java:117:33:117:63 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:118:36:118:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:118:36:118:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:118:59:118:77 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:118:59:118:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:118:67:118:76 | unsafeUri9 : String | semmle.label | unsafeUri9 : String | -| SanitizationTests.java:119:25:119:32 | unsafer9 | semmle.label | unsafer9 | -| SanitizationTests.java:121:34:121:126 | format(...) : String | semmle.label | format(...) : String | -| SanitizationTests.java:121:34:121:126 | new ..[] { .. } : Object[] [[]] : String | semmle.label | new ..[] { .. } : Object[] [[]] : String | -| SanitizationTests.java:121:94:121:125 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| SanitizationTests.java:122:37:122:80 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | -| SanitizationTests.java:122:37:122:88 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | -| SanitizationTests.java:122:60:122:79 | new URI(...) | semmle.label | new URI(...) | -| SanitizationTests.java:122:60:122:79 | new URI(...) : URI | semmle.label | new URI(...) : URI | -| SanitizationTests.java:122:68:122:78 | unsafeUri10 : String | semmle.label | unsafeUri10 : String | -| SanitizationTests.java:123:25:123:33 | unsafer10 | semmle.label | unsafer10 | +| SanitizationTests.java:22:23:22:58 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:22:31:22:57 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:25:29:25:55 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:25:29:25:63 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:25:52:25:54 | uri | semmle.label | uri | +| SanitizationTests.java:25:52:25:54 | uri : URI | semmle.label | uri : URI | +| SanitizationTests.java:26:25:26:25 | r | semmle.label | r | +| SanitizationTests.java:78:33:78:63 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:79:36:79:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:79:36:79:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:79:59:79:77 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:79:59:79:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:79:67:79:76 | unsafeUri3 : String | semmle.label | unsafeUri3 : String | +| SanitizationTests.java:80:25:80:32 | unsafer3 | semmle.label | unsafer3 | +| SanitizationTests.java:82:49:82:79 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:83:36:83:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:83:36:83:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:83:59:83:77 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:83:59:83:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:83:67:83:76 | unsafeUri4 : String | semmle.label | unsafeUri4 : String | +| SanitizationTests.java:84:25:84:32 | unsafer4 | semmle.label | unsafer4 | +| SanitizationTests.java:87:13:87:22 | unsafeUri5 [post update] : StringBuilder | semmle.label | unsafeUri5 [post update] : StringBuilder | +| SanitizationTests.java:87:31:87:61 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:88:36:88:89 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:88:36:88:97 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:88:59:88:88 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:88:59:88:88 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:88:67:88:76 | unsafeUri5 : StringBuilder | semmle.label | unsafeUri5 : StringBuilder | +| SanitizationTests.java:88:67:88:87 | toString(...) : String | semmle.label | toString(...) : String | +| SanitizationTests.java:89:25:89:32 | unsafer5 | semmle.label | unsafer5 | +| SanitizationTests.java:91:40:91:87 | new StringBuilder(...) : StringBuilder | semmle.label | new StringBuilder(...) : StringBuilder | +| SanitizationTests.java:91:58:91:86 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:93:37:93:90 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:93:37:93:98 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:93:60:93:89 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:93:60:93:89 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:93:68:93:77 | unafeUri5a : StringBuilder | semmle.label | unafeUri5a : StringBuilder | +| SanitizationTests.java:93:68:93:88 | toString(...) : String | semmle.label | toString(...) : String | +| SanitizationTests.java:94:25:94:33 | unsafer5a | semmle.label | unsafer5a | +| SanitizationTests.java:96:41:96:105 | append(...) : StringBuilder | semmle.label | append(...) : StringBuilder | +| SanitizationTests.java:96:42:96:89 | new StringBuilder(...) : StringBuilder | semmle.label | new StringBuilder(...) : StringBuilder | +| SanitizationTests.java:96:60:96:88 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:98:37:98:91 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:98:37:98:99 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:98:60:98:90 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:98:60:98:90 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:98:68:98:78 | unsafeUri5b : StringBuilder | semmle.label | unsafeUri5b : StringBuilder | +| SanitizationTests.java:98:68:98:89 | toString(...) : String | semmle.label | toString(...) : String | +| SanitizationTests.java:99:25:99:33 | unsafer5b | semmle.label | unsafer5b | +| SanitizationTests.java:101:41:101:106 | append(...) : StringBuilder | semmle.label | append(...) : StringBuilder | +| SanitizationTests.java:101:77:101:105 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:103:37:103:91 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:103:37:103:99 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:103:60:103:90 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:103:60:103:90 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:103:68:103:78 | unsafeUri5c : StringBuilder | semmle.label | unsafeUri5c : StringBuilder | +| SanitizationTests.java:103:68:103:89 | toString(...) : String | semmle.label | toString(...) : String | +| SanitizationTests.java:104:25:104:33 | unsafer5c | semmle.label | unsafer5c | +| SanitizationTests.java:106:33:106:104 | format(...) : String | semmle.label | format(...) : String | +| SanitizationTests.java:106:33:106:104 | new ..[] { .. } : Object[] [[]] : String | semmle.label | new ..[] { .. } : Object[] [[]] : String | +| SanitizationTests.java:106:73:106:103 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:107:36:107:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:107:36:107:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:107:59:107:77 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:107:59:107:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:107:67:107:76 | unsafeUri6 : String | semmle.label | unsafeUri6 : String | +| SanitizationTests.java:108:25:108:32 | unsafer6 | semmle.label | unsafer6 | +| SanitizationTests.java:110:33:110:110 | format(...) : String | semmle.label | format(...) : String | +| SanitizationTests.java:110:33:110:110 | new ..[] { .. } : Object[] [[]] : String | semmle.label | new ..[] { .. } : Object[] [[]] : String | +| SanitizationTests.java:110:56:110:86 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:111:36:111:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:111:36:111:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:111:59:111:77 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:111:59:111:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:111:67:111:76 | unsafeUri7 : String | semmle.label | unsafeUri7 : String | +| SanitizationTests.java:112:25:112:32 | unsafer7 | semmle.label | unsafer7 | +| SanitizationTests.java:114:33:114:110 | format(...) : String | semmle.label | format(...) : String | +| SanitizationTests.java:114:33:114:110 | new ..[] { .. } : Object[] [[]] : String | semmle.label | new ..[] { .. } : Object[] [[]] : String | +| SanitizationTests.java:114:55:114:85 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:115:36:115:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:115:36:115:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:115:59:115:77 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:115:59:115:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:115:67:115:76 | unsafeUri8 : String | semmle.label | unsafeUri8 : String | +| SanitizationTests.java:116:25:116:32 | unsafer8 | semmle.label | unsafer8 | +| SanitizationTests.java:118:33:118:63 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:119:36:119:78 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:119:36:119:86 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:119:59:119:77 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:119:59:119:77 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:119:67:119:76 | unsafeUri9 : String | semmle.label | unsafeUri9 : String | +| SanitizationTests.java:120:25:120:32 | unsafer9 | semmle.label | unsafer9 | +| SanitizationTests.java:122:34:122:126 | format(...) : String | semmle.label | format(...) : String | +| SanitizationTests.java:122:34:122:126 | new ..[] { .. } : Object[] [[]] : String | semmle.label | new ..[] { .. } : Object[] [[]] : String | +| SanitizationTests.java:122:94:122:125 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:123:37:123:80 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:123:37:123:88 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:123:60:123:79 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:123:60:123:79 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:123:68:123:78 | unsafeUri10 : String | semmle.label | unsafeUri10 : String | +| SanitizationTests.java:124:25:124:33 | unsafer10 | semmle.label | unsafer10 | +| SanitizationTests.java:177:31:177:114 | newBuilder(...) : Builder | semmle.label | newBuilder(...) : Builder | +| SanitizationTests.java:177:31:177:122 | build(...) : HttpRequest | semmle.label | build(...) : HttpRequest | +| SanitizationTests.java:177:54:177:113 | new URI(...) | semmle.label | new URI(...) | +| SanitizationTests.java:177:54:177:113 | new URI(...) : URI | semmle.label | new URI(...) : URI | +| SanitizationTests.java:177:62:177:112 | getFromList(...) : String | semmle.label | getFromList(...) : String | +| SanitizationTests.java:177:74:177:111 | of(...) : List [] : String | semmle.label | of(...) : List [] : String | +| SanitizationTests.java:177:82:177:110 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| SanitizationTests.java:178:25:178:27 | r18 | semmle.label | r18 | +| SanitizationTests.java:199:31:199:112 | list : List [] : String | semmle.label | list : List [] : String | +| SanitizationTests.java:200:16:200:19 | list : List [] : String | semmle.label | list : List [] : String | +| SanitizationTests.java:200:16:200:26 | get(...) : String | semmle.label | get(...) : String | | SpringSSRF.java:28:33:28:60 | getParameter(...) : String | semmle.label | getParameter(...) : String | | SpringSSRF.java:32:39:32:59 | ... + ... | semmle.label | ... + ... | | SpringSSRF.java:33:69:33:82 | fooResourceUrl | semmle.label | fooResourceUrl | @@ -2035,3 +2062,4 @@ nodes | mad/Test.java:112:15:112:31 | (...)... | semmle.label | (...)... | | mad/Test.java:112:24:112:31 | source(...) : String | semmle.label | source(...) : String | subpaths +| SanitizationTests.java:177:74:177:111 | of(...) : List [] : String | SanitizationTests.java:199:31:199:112 | list : List [] : String | SanitizationTests.java:200:16:200:26 | get(...) : String | SanitizationTests.java:177:62:177:112 | getFromList(...) : String | diff --git a/java/ql/test/query-tests/security/CWE-918/SanitizationTests.java b/java/ql/test/query-tests/security/CWE-918/SanitizationTests.java index 4da70e8dd75..f14158de0d1 100644 --- a/java/ql/test/query-tests/security/CWE-918/SanitizationTests.java +++ b/java/ql/test/query-tests/security/CWE-918/SanitizationTests.java @@ -2,8 +2,9 @@ import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; -import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -140,13 +141,41 @@ public class SanitizationTests extends HttpServlet { client.send(r12, null); } - Pattern pattern = Pattern.compile("[a-zA-Z0-9_-]+"); + Pattern pattern = Pattern.compile("([a-zA-Z0-9_-]+)"); String param13 = request.getParameter("uri13"); Matcher matcher = pattern.matcher(param13); if (matcher.matches()) { - HttpRequest r13 = HttpRequest.newBuilder(new URI(param13)).build(); - client.send(r13, null); + HttpRequest r13a = HttpRequest.newBuilder(new URI(param13)).build(); + client.send(r13a, null); + HttpRequest r13b = HttpRequest.newBuilder(new URI(matcher.group(1))).build(); + client.send(r13b, null); } + + // GOOD: sanitisation by @Pattern annotation on a field + AnnotatedFieldObject obj14 = new AnnotatedFieldObject(request.getParameter("uri14")); + HttpRequest r14a = HttpRequest.newBuilder(new URI(obj14.uri)).build(); + client.send(r14a, null); + HttpRequest r14b = HttpRequest.newBuilder(new URI(obj14.getUri())).build(); + client.send(r14b, null); + + // GOOD: sanitisation by @Pattern annotation on a parameter of a constructor + AnnotatedParameterObject obj15 = new AnnotatedParameterObject(request.getParameter("uri15")); + HttpRequest r15a = HttpRequest.newBuilder(new URI(obj15.uri)).build(); + client.send(r15a, null); + HttpRequest r15b = HttpRequest.newBuilder(new URI(obj15.getUri())).build(); + client.send(r15b, null); + + // GOOD: sanitisation by @Pattern annotation on a parameter of a method + HttpRequest r16 = HttpRequest.newBuilder(new URI(identity1(request.getParameter("uri16")))).build(); + client.send(r16, null); + + // GOOD: sanitisation by @Pattern annotation on a method (which constrains the return value) + HttpRequest r17 = HttpRequest.newBuilder(new URI(identity2(request.getParameter("uri17")))).build(); + client.send(r17, null); + + // GOOD: sanitisation by @Pattern annotation on a type (we do not recognise this, so we get an FP) + HttpRequest r18 = HttpRequest.newBuilder(new URI(getFromList(List.of(request.getParameter("uri18"))))).build(); // $ SPURIOUS: Source Alert + client.send(r18, null); // $ SPURIOUS: Alert } catch (Exception e) { // TODO: handle exception } @@ -157,4 +186,44 @@ public class SanitizationTests extends HttpServlet { throw new IllegalArgumentException("Invalid ID"); } } + + public String identity1(@javax.validation.constraints.Pattern(regexp = "[a-zA-Z0-9_-]+") String uri) { + return uri; + } + + @javax.validation.constraints.Pattern(regexp = "[a-zA-Z0-9_-]+") + public String identity2(String uri) { + return uri; + } + + public String getFromList(List<@javax.validation.constraints.Pattern(regexp = "[a-zA-Z0-9_-]+") String> list) { + return list.get(0); + } + + public class AnnotatedFieldObject { + @javax.validation.constraints.Pattern(regexp = "[a-zA-Z0-9_-]+") + String uri; + + String otherField; + + public AnnotatedFieldObject(String uri) { + this.uri = uri; + } + + public String getUri() { + return uri; + } + } + + public class AnnotatedParameterObject { + String uri; + + public AnnotatedParameterObject(@javax.validation.constraints.Pattern(regexp = "[a-zA-Z0-9_-]+") String uri) { + this.uri = uri; + } + + public String getUri() { + return uri; + } + } } diff --git a/java/ql/test/query-tests/security/CWE-918/options b/java/ql/test/query-tests/security/CWE-918/options index 78a6c15024a..6b6efaeca54 100644 --- a/java/ql/test/query-tests/security/CWE-918/options +++ b/java/ql/test/query-tests/security/CWE-918/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/springframework-5.8.x:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/:${testdir}/../../../stubs/cargo:${testdir}/../../../stubs/javafx-web:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/apache-http-5:${testdir}/../../../stubs/playframework-2.6.x:${testdir}/../../../stubs/jaxws-api-2.0:${testdir}/../../../stubs/apache-cxf +//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/javax-validation-constraints:${testdir}/../../../stubs/springframework-5.8.x:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/:${testdir}/../../../stubs/cargo:${testdir}/../../../stubs/javafx-web:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/apache-http-5:${testdir}/../../../stubs/playframework-2.6.x:${testdir}/../../../stubs/jaxws-api-2.0:${testdir}/../../../stubs/apache-cxf diff --git a/java/ql/test/stubs/javax-validation-constraints/javax/validation/Constraint.java b/java/ql/test/stubs/javax-validation-constraints/javax/validation/Constraint.java new file mode 100644 index 00000000000..5ad2617b19c --- /dev/null +++ b/java/ql/test/stubs/javax-validation-constraints/javax/validation/Constraint.java @@ -0,0 +1,88 @@ +/* + * Bean Validation API + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package javax.validation; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Marks an annotation as being a Bean Validation constraint. + *

+ * A given constraint annotation must be annotated by a {@code @Constraint} + * annotation which refers to its list of constraint validation implementations. + *

+ * Each constraint annotation must host the following attributes: + *

    + *
  • {@code String message() default [...];} which should default to an error + * message key made of the fully-qualified class name of the constraint followed by + * {@code .message}. For example {@code "{com.acme.constraints.NotSafe.message}"}
  • + *
  • {@code Class[] groups() default {};} for user to customize the targeted + * groups
  • + *
  • {@code Class[] payload() default {};} for + * extensibility purposes
  • + *
+ *

+ * When building a constraint that is both generic and cross-parameter, the constraint + * annotation must host the {@code validationAppliesTo()} property. + * A constraint is generic if it targets the annotated element and is cross-parameter if + * it targets the array of parameters of a method or constructor. + *

+ *     ConstraintTarget validationAppliesTo() default ConstraintTarget.IMPLICIT;
+ * 
+ * This property allows the constraint user to choose whether the constraint + * targets the return type of the executable or its array of parameters. + * + * A constraint is both generic and cross-parameter if + *
    + *
  • two kinds of {@code ConstraintValidator}s are attached to the + * constraint, one targeting {@link ValidationTarget#ANNOTATED_ELEMENT} + * and one targeting {@link ValidationTarget#PARAMETERS},
  • + *
  • or if a {@code ConstraintValidator} targets both + * {@code ANNOTATED_ELEMENT} and {@code PARAMETERS}.
  • + *
+ * + * Such dual constraints are rare. See {@link SupportedValidationTarget} for more info. + *

+ * Here is an example of constraint definition: + *

+ * @Documented
+ * @Constraint(validatedBy = OrderNumberValidator.class)
+ * @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
+ * @Retention(RUNTIME)
+ * public @interface OrderNumber {
+ *     String message() default "{com.acme.constraint.OrderNumber.message}";
+ *     Class<?>[] groups() default {};
+ *     Class<? extends Payload>[] payload() default {};
+ * }
+ * 
+ * + * @author Emmanuel Bernard + * @author Gavin King + * @author Hardy Ferentschik + */ +@Documented +@Target({ ANNOTATION_TYPE }) +@Retention(RUNTIME) +public @interface Constraint { + + /** + * {@link ConstraintValidator} classes implementing the constraint. The given classes + * must reference distinct target types for a given {@link ValidationTarget}. If two + * {@code ConstraintValidator}s refer to the same type, an exception will occur. + *

+ * At most one {@code ConstraintValidator} targeting the array of parameters of + * methods or constructors (aka cross-parameter) is accepted. If two or more + * are present, an exception will occur. + * + * @return array of {@code ConstraintValidator} classes implementing the constraint + */ + Class[] validatedBy(); +} diff --git a/java/ql/test/stubs/javax-validation-constraints/javax/validation/Payload.java b/java/ql/test/stubs/javax-validation-constraints/javax/validation/Payload.java new file mode 100644 index 00000000000..12c2760d34d --- /dev/null +++ b/java/ql/test/stubs/javax-validation-constraints/javax/validation/Payload.java @@ -0,0 +1,23 @@ +/* + * Bean Validation API + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package javax.validation; + +/** + * Payload type that can be attached to a given + * constraint declaration. + *

+ * Payloads are typically used to carry on metadata information + * consumed by a validation client. + *

+ * With the exception of the {@link Unwrapping} payload types, the use of payloads is not + * considered portable. + * + * @author Emmanuel Bernard + * @author Gerhard Petracek + */ +public interface Payload { +} diff --git a/java/ql/test/stubs/javax-validation-constraints/javax/validation/constraints/Pattern.java b/java/ql/test/stubs/javax-validation-constraints/javax/validation/constraints/Pattern.java new file mode 100644 index 00000000000..0f3191fe0d9 --- /dev/null +++ b/java/ql/test/stubs/javax-validation-constraints/javax/validation/constraints/Pattern.java @@ -0,0 +1,148 @@ +/* + * Bean Validation API + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package javax.validation.constraints; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.constraints.Pattern.List; + +/** + * The annotated {@code CharSequence} must match the specified regular expression. + * The regular expression follows the Java regular expression conventions + * see {@link java.util.regex.Pattern}. + *

+ * Accepts {@code CharSequence}. {@code null} elements are considered valid. + * + * @author Emmanuel Bernard + */ +@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) +@Retention(RUNTIME) +@Repeatable(List.class) +@Documented +@Constraint(validatedBy = { }) +public @interface Pattern { + + /** + * @return the regular expression to match + */ + String regexp(); + + /** + * @return array of {@code Flag}s considered when resolving the regular expression + */ + Flag[] flags() default { }; + + /** + * @return the error message template + */ + String message() default "{javax.validation.constraints.Pattern.message}"; + + /** + * @return the groups the constraint belongs to + */ + Class[] groups() default { }; + + /** + * @return the payload associated to the constraint + */ + Class[] payload() default { }; + + /** + * Possible Regexp flags. + */ + public static enum Flag { + + /** + * Enables Unix lines mode. + * + * @see java.util.regex.Pattern#UNIX_LINES + */ + UNIX_LINES( java.util.regex.Pattern.UNIX_LINES ), + + /** + * Enables case-insensitive matching. + * + * @see java.util.regex.Pattern#CASE_INSENSITIVE + */ + CASE_INSENSITIVE( java.util.regex.Pattern.CASE_INSENSITIVE ), + + /** + * Permits whitespace and comments in pattern. + * + * @see java.util.regex.Pattern#COMMENTS + */ + COMMENTS( java.util.regex.Pattern.COMMENTS ), + + /** + * Enables multiline mode. + * + * @see java.util.regex.Pattern#MULTILINE + */ + MULTILINE( java.util.regex.Pattern.MULTILINE ), + + /** + * Enables dotall mode. + * + * @see java.util.regex.Pattern#DOTALL + */ + DOTALL( java.util.regex.Pattern.DOTALL ), + + /** + * Enables Unicode-aware case folding. + * + * @see java.util.regex.Pattern#UNICODE_CASE + */ + UNICODE_CASE( java.util.regex.Pattern.UNICODE_CASE ), + + /** + * Enables canonical equivalence. + * + * @see java.util.regex.Pattern#CANON_EQ + */ + CANON_EQ( java.util.regex.Pattern.CANON_EQ ); + + //JDK flag value + private final int value; + + private Flag(int value) { + this.value = value; + } + + /** + * @return flag value as defined in {@link java.util.regex.Pattern} + */ + public int getValue() { + return value; + } + } + + /** + * Defines several {@link Pattern} annotations on the same element. + * + * @see Pattern + */ + @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) + @Retention(RUNTIME) + @Documented + @interface List { + + Pattern[] value(); + } +} diff --git a/javascript/ql/lib/CHANGELOG.md b/javascript/ql/lib/CHANGELOG.md index c599ea0799b..1d872998261 100644 --- a/javascript/ql/lib/CHANGELOG.md +++ b/javascript/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.6.22 + +No user-facing changes. + ## 2.6.21 ### Minor Analysis Improvements diff --git a/javascript/ql/lib/change-notes/released/2.6.22.md b/javascript/ql/lib/change-notes/released/2.6.22.md new file mode 100644 index 00000000000..a8957942645 --- /dev/null +++ b/javascript/ql/lib/change-notes/released/2.6.22.md @@ -0,0 +1,3 @@ +## 2.6.22 + +No user-facing changes. diff --git a/javascript/ql/lib/codeql-pack.release.yml b/javascript/ql/lib/codeql-pack.release.yml index 872f4f9807c..205f738ae8d 100644 --- a/javascript/ql/lib/codeql-pack.release.yml +++ b/javascript/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.6.21 +lastReleaseVersion: 2.6.22 diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index 830994432a5..2415cf3d3b7 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 2.6.22-dev +version: 2.6.23-dev groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/src/CHANGELOG.md b/javascript/ql/src/CHANGELOG.md index 50da6325746..c08f0793935 100644 --- a/javascript/ql/src/CHANGELOG.md +++ b/javascript/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.3.2 + +No user-facing changes. + ## 2.3.1 No user-facing changes. diff --git a/javascript/ql/src/change-notes/released/2.3.2.md b/javascript/ql/src/change-notes/released/2.3.2.md new file mode 100644 index 00000000000..420587fa3dc --- /dev/null +++ b/javascript/ql/src/change-notes/released/2.3.2.md @@ -0,0 +1,3 @@ +## 2.3.2 + +No user-facing changes. diff --git a/javascript/ql/src/codeql-pack.release.yml b/javascript/ql/src/codeql-pack.release.yml index 530699ffecc..f51e9b8563c 100644 --- a/javascript/ql/src/codeql-pack.release.yml +++ b/javascript/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.3.1 +lastReleaseVersion: 2.3.2 diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 8fc055f61e1..1f57b3e99e2 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 2.3.2-dev +version: 2.3.3-dev groups: - javascript - queries diff --git a/misc/bazel/registry/modules/rules_rust/0.68.1.codeql.1/MODULE.bazel b/misc/bazel/registry/modules/rules_rust/0.68.1.codeql.1/MODULE.bazel new file mode 100644 index 00000000000..aedc5a8a242 --- /dev/null +++ b/misc/bazel/registry/modules/rules_rust/0.68.1.codeql.1/MODULE.bazel @@ -0,0 +1,151 @@ +"""bazelbuild/rules_rust""" + +module( + name = "rules_rust", + version = "0.68.1.codeql.1", +) + +############################################################################### +## Core +############################################################################### + +bazel_dep(name = "bazel_features", version = "1.32.0") +bazel_dep(name = "bazel_skylib", version = "1.8.2") +bazel_dep(name = "platforms", version = "1.0.0") +bazel_dep(name = "rules_cc", version = "0.2.4") +bazel_dep(name = "rules_license", version = "1.0.0") +bazel_dep(name = "rules_shell", version = "0.6.1") +bazel_dep(name = "apple_support", version = "1.24.1", repo_name = "build_bazel_apple_support") + +internal_deps = use_extension("//rust/private:internal_extensions.bzl", "i") +use_repo( + internal_deps, + "rrra", + "rrra__anyhow-1.0.71", + "rrra__camino-1.1.9", + "rrra__clap-4.3.11", + "rrra__env_logger-0.10.0", + "rrra__itertools-0.11.0", + "rrra__log-0.4.19", + "rrra__serde-1.0.171", + "rrra__serde_json-1.0.102", + "rules_rust_tinyjson", +) + +cargo_internal_deps = use_extension("//cargo/private:internal_extensions.bzl", "i") +use_repo( + cargo_internal_deps, + "rrc", + "rrc__cargo-util-schemas-0.3.1", + "rrc__cargo_toml-0.20.5", + "rrc__pathdiff-0.1.0", + "rrc__semver-1.0.25", + "rrc__toml-0.8.20", +) + +rust = use_extension("//rust:extensions.bzl", "rust") +rust.toolchain(edition = "2021") +use_repo(rust, "rust_toolchains") + +register_toolchains( + "@rust_toolchains//:all", +) + +rust_host_tools = use_extension("//rust:extensions.bzl", "rust_host_tools") +rust_host_tools.host_tools( + name = "rust_host_tools", +) +use_repo( + rust_host_tools, + "rust_host_tools", +) + +rust_test = use_extension("//test:test_extensions.bzl", "rust_test", dev_dependency = True) +use_repo( + rust_test, + "buildkite_config", + "generated_inputs_in_external_repo", + "libc", + "rtra", + "rtra__serde-1.0.228", + "rtra__serde_json-1.0.145", + "rtvsc", + "rtvsc__serde-1.0.228", + "rtvsc__serde_json-1.0.145", + "rules_rust_test_load_arbitrary_tool", + "rules_rust_toolchain_test_target_json", +) + +bazel_dep(name = "rules_python", version = "0.40.0", dev_dependency = True) +bazel_dep(name = "rules_testing", version = "0.7.0", dev_dependency = True) +bazel_dep(name = "bazel_ci_rules", version = "1.0.0", dev_dependency = True) + +############################################################################### +## Crate Universe +############################################################################### + +crate_universe_internal_deps = use_extension( + "//crate_universe/private:internal_extensions.bzl", + "cu", +) +use_repo( + crate_universe_internal_deps, + "cargo_bazel.buildifier-darwin-amd64", + "cargo_bazel.buildifier-darwin-arm64", + "cargo_bazel.buildifier-linux-amd64", + "cargo_bazel.buildifier-linux-arm64", + "cargo_bazel.buildifier-windows-amd64.exe", + "cui", + "cui__anyhow-1.0.98", + "cui__camino-1.1.9", + "cui__cargo-lock-10.1.0", + "cui__cargo-platform-0.1.9", + "cui__cargo_metadata-0.19.2", + "cui__cargo_toml-0.22.1", + "cui__cfg-expr-0.18.0", + "cui__clap-4.5.37", + "cui__crates-index-3.7.0", + "cui__glob-0.3.2", + "cui__hex-0.4.3", + "cui__indoc-2.0.6", + "cui__itertools-0.14.0", + "cui__maplit-1.0.2", + "cui__normpath-1.3.0", + "cui__once_cell-1.21.3", + "cui__pathdiff-0.2.3", + "cui__regex-1.11.1", + "cui__semver-1.0.26", + "cui__serde-1.0.219", + "cui__serde_json-1.0.140", + "cui__serde_starlark-0.1.17", + "cui__sha2-0.10.8", + "cui__spdx-0.10.8", + "cui__tempfile-3.19.1", + "cui__tera-1.20.0", + "cui__textwrap-0.16.2", + "cui__toml-0.8.21", + "cui__tracing-0.1.41", + "cui__tracing-subscriber-0.3.19", + "cui__url-2.5.4", + "cui__walkdir-2.5.0", +) + +crate_universe_internal_non_repro_deps = use_extension( + "//crate_universe/private:internal_extensions.bzl", + "cu_nr", +) +use_repo( + crate_universe_internal_non_repro_deps, + "cargo_bazel_bootstrap", +) + +crate_universe_internal_dev_deps = use_extension( + "//crate_universe/private:internal_extensions.bzl", + "cu_dev", + dev_dependency = True, +) +use_repo( + crate_universe_internal_dev_deps, + "cross_rs", + "cross_rs_host_bin", +) diff --git a/misc/bazel/registry/modules/rules_rust/0.68.1.codeql.1/patches/include_rmeta_in_stdlib.patch b/misc/bazel/registry/modules/rules_rust/0.68.1.codeql.1/patches/include_rmeta_in_stdlib.patch new file mode 100644 index 00000000000..3707cb51b63 --- /dev/null +++ b/misc/bazel/registry/modules/rules_rust/0.68.1.codeql.1/patches/include_rmeta_in_stdlib.patch @@ -0,0 +1,12 @@ +diff --git a/rust/private/repository_utils.bzl b/rust/private/repository_utils.bzl +index 05b741947..f88074af6 100644 +--- a/rust/private/repository_utils.bzl ++++ b/rust/private/repository_utils.bzl +@@ -280,6 +280,7 @@ rust_stdlib_filegroup( + srcs = glob( + [ + "lib/rustlib/{target_triple}/lib/*.rlib", ++ "lib/rustlib/{target_triple}/lib/*.rmeta", + "lib/rustlib/{target_triple}/lib/*{dylib_ext}*", + "lib/rustlib/{target_triple}/lib/*{staticlib_ext}", + "lib/rustlib/{target_triple}/lib/self-contained/**", diff --git a/misc/bazel/registry/modules/rules_rust/0.68.1.codeql.1/source.json b/misc/bazel/registry/modules/rules_rust/0.68.1.codeql.1/source.json new file mode 100644 index 00000000000..6048521ce2f --- /dev/null +++ b/misc/bazel/registry/modules/rules_rust/0.68.1.codeql.1/source.json @@ -0,0 +1,9 @@ +{ + "integrity": "sha256-yKqAbPYGZnmsI0YyQe6ArWkiZdrQRl9RERy74wuJA1I=", + "strip_prefix": "", + "url": "https://github.com/bazelbuild/rules_rust/releases/download/0.68.1/rules_rust-0.68.1.tar.gz", + "patches": { + "include_rmeta_in_stdlib.patch": "sha256-7n8XHpfkLUMEbRG6lKqdhLWydsWlRRG+Ywkxk6LvY9c=" + }, + "patch_strip": 1 +} diff --git a/misc/bazel/registry/modules/rules_rust/metadata.json b/misc/bazel/registry/modules/rules_rust/metadata.json new file mode 100644 index 00000000000..deffe6f6dfa --- /dev/null +++ b/misc/bazel/registry/modules/rules_rust/metadata.json @@ -0,0 +1,11 @@ +{ + "homepage": "https://github.com/bazelbuild/rules_rust", + "maintainers": [], + "repository": [ + "github:bazelbuild/rules_rust" + ], + "versions": [ + "0.68.1.codeql.1" + ], + "yanked_versions": {} +} diff --git a/misc/suite-helpers/CHANGELOG.md b/misc/suite-helpers/CHANGELOG.md index 0d796d32439..2a81d5f40ba 100644 --- a/misc/suite-helpers/CHANGELOG.md +++ b/misc/suite-helpers/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/misc/suite-helpers/change-notes/released/1.0.42.md b/misc/suite-helpers/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/misc/suite-helpers/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/misc/suite-helpers/codeql-pack.release.yml b/misc/suite-helpers/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/misc/suite-helpers/codeql-pack.release.yml +++ b/misc/suite-helpers/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index 28a63301e69..48e31175a00 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/suite-helpers -version: 1.0.42-dev +version: 1.0.43-dev groups: shared warnOnImplicitThis: true diff --git a/python/ql/lib/CHANGELOG.md b/python/ql/lib/CHANGELOG.md index a273dc2628b..76d2adf3a03 100644 --- a/python/ql/lib/CHANGELOG.md +++ b/python/ql/lib/CHANGELOG.md @@ -1,3 +1,14 @@ +## 6.1.1 + +### Minor Analysis Improvements + +* Added request forgery sink models for the Azure SDK. +* Made it so that models-as-data sinks with the kind `request-forgery` contribute to the class `Http::Client::Request` which represents HTTP client requests. + +### Bug Fixes + +- Using `=` as a fill character in a format specifier (e.g `f"{x:=^20}"`) now no longer results in a syntax error during parsing. + ## 6.1.0 ### New Features diff --git a/python/ql/lib/change-notes/2025-09-30-azure_ssrf_models.md b/python/ql/lib/change-notes/2025-09-30-azure_ssrf_models.md deleted file mode 100644 index 283b703a438..00000000000 --- a/python/ql/lib/change-notes/2025-09-30-azure_ssrf_models.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -category: minorAnalysis ---- -* Added request forgery sink models for the Azure SDK. -* Made it so that models-as-data sinks with the kind `request-forgery` contribute to the class `Http::Client::Request` which represents HTTP client requests. \ No newline at end of file diff --git a/python/ql/lib/change-notes/2026-02-05-fix-format-fill-character-misparse.md b/python/ql/lib/change-notes/2026-02-05-fix-format-fill-character-misparse.md deleted file mode 100644 index 8c0bd18c4dc..00000000000 --- a/python/ql/lib/change-notes/2026-02-05-fix-format-fill-character-misparse.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -category: fix ---- - -- Using `=` as a fill character in a format specifier (e.g `f"{x:=^20}"`) now no longer results in a syntax error during parsing. diff --git a/python/ql/lib/change-notes/2026-02-09-ssrf_test_case_cleanup_and_new_ssrf_barriers.md b/python/ql/lib/change-notes/2026-02-09-ssrf_test_case_cleanup_and_new_ssrf_barriers.md new file mode 100644 index 00000000000..c3b4194e7b8 --- /dev/null +++ b/python/ql/lib/change-notes/2026-02-09-ssrf_test_case_cleanup_and_new_ssrf_barriers.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added new full SSRF sanitization barrier from the new AntiSSRF library. \ No newline at end of file diff --git a/python/ql/lib/change-notes/released/6.1.1.md b/python/ql/lib/change-notes/released/6.1.1.md new file mode 100644 index 00000000000..ca4d1bf4684 --- /dev/null +++ b/python/ql/lib/change-notes/released/6.1.1.md @@ -0,0 +1,10 @@ +## 6.1.1 + +### Minor Analysis Improvements + +* Added request forgery sink models for the Azure SDK. +* Made it so that models-as-data sinks with the kind `request-forgery` contribute to the class `Http::Client::Request` which represents HTTP client requests. + +### Bug Fixes + +- Using `=` as a fill character in a format specifier (e.g `f"{x:=^20}"`) now no longer results in a syntax error during parsing. diff --git a/python/ql/lib/codeql-pack.release.yml b/python/ql/lib/codeql-pack.release.yml index 22247782f3e..54acf3e5e47 100644 --- a/python/ql/lib/codeql-pack.release.yml +++ b/python/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 6.1.0 +lastReleaseVersion: 6.1.1 diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 1ead7adb605..36b8813f8de 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 6.1.1-dev +version: 6.1.2-dev groups: python dbscheme: semmlecode.python.dbscheme extractor: python diff --git a/python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryCustomizations.qll index 274e7ee57ad..3fb260e425d 100644 --- a/python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryCustomizations.qll @@ -176,4 +176,36 @@ module ServerSideRequestForgery { strNode = [call.getArg(0), call.getArgByName("string")] ) } + + /** A validation of a URI using the `AntiSSRF` library, considered as a full-ssrf sanitizer. */ + private class UriValidator extends FullUrlControlSanitizer { + UriValidator() { this = DataFlow::BarrierGuard::getABarrierNode() } + } + + import semmle.python.dataflow.new.internal.DataFlowPublic + + private predicate uri_validator(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) { + exists(DataFlow::CallCfgNode call, string funcs | + funcs in ["in_domain", "in_azure_keyvault_domain", "in_azure_storage_domain"] and + call = API::moduleImport("AntiSSRF").getMember("URIValidator").getMember(funcs).getACall() and + call.getArg(0).asCfgNode() = node + | + // validator call directly (e.g., if URIValidator.in_domain(...) ) + g = call.asCfgNode() and + branch = true + or + // validator used in a comparison + exists(Cmpop op, Node n, ControlFlowNode l | + n.getALocalSource() = call and g.(CompareNode).operands(n.asCfgNode(), op, l) + | + // validator == true or validator == false or validator is True or validator is False + (op instanceof Eq or op instanceof Is) and + branch = l.getNode().(BooleanLiteral).booleanValue() + or + // validator != false or validator != true or validator is not True or validator is not False + (op instanceof NotEq or op instanceof IsNot) and + branch = l.getNode().(BooleanLiteral).booleanValue().booleanNot() + ) + ) + } } diff --git a/python/ql/src/CHANGELOG.md b/python/ql/src/CHANGELOG.md index 3f9a869decc..a68b2d3b8db 100644 --- a/python/ql/src/CHANGELOG.md +++ b/python/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.7.7 + +No user-facing changes. + ## 1.7.6 No user-facing changes. diff --git a/python/ql/src/change-notes/released/1.7.7.md b/python/ql/src/change-notes/released/1.7.7.md new file mode 100644 index 00000000000..e1a2f3e1d9a --- /dev/null +++ b/python/ql/src/change-notes/released/1.7.7.md @@ -0,0 +1,3 @@ +## 1.7.7 + +No user-facing changes. diff --git a/python/ql/src/codeql-pack.release.yml b/python/ql/src/codeql-pack.release.yml index 1f68518dba9..df4010bd267 100644 --- a/python/ql/src/codeql-pack.release.yml +++ b/python/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.7.6 +lastReleaseVersion: 1.7.7 diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index e6de4a768bf..c6b7d29f631 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 1.7.7-dev +version: 1.7.8-dev groups: - python - queries diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected index 33970318461..7434eca6978 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected @@ -1,156 +1,263 @@ +#select +| full_partial_test.py:11:5:11:28 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:11:18:11:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:15:5:15:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:15:18:15:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:22:5:22:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:22:18:22:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:27:5:27:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:27:18:27:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:47:5:47:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:47:18:47:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:51:5:51:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:55:5:55:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:55:18:55:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:59:5:59:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:59:18:59:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:63:5:63:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:63:18:63:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:72:5:72:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:72:18:72:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:76:5:76:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:89:5:89:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:93:5:93:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:93:18:93:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:97:5:97:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:97:18:97:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:16:5:16:59 | ControlFlowNode for SecretClient() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:16:28:16:35 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:18:5:18:43 | ControlFlowNode for Attribute() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:18:35:18:42 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:20:5:20:35 | ControlFlowNode for KeyClient() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:20:15:20:22 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:22:5:22:85 | ControlFlowNode for Attribute() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:22:54:22:61 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:25:5:25:104 | ControlFlowNode for download_blob_from_url() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:25:37:25:44 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:15:5:15:36 | ControlFlowNode for Attribute() | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:15:5:15:36 | ControlFlowNode for Attribute() | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:15:25:15:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:21:5:21:36 | ControlFlowNode for Attribute() | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:19:27:19:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:21:5:21:36 | ControlFlowNode for Attribute() | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:21:9:21:63 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:21:32:21:39 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:37:9:37:60 | ControlFlowNode for KeyClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:37:29:37:36 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:53:9:53:47 | ControlFlowNode for Attribute() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:53:39:53:46 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:64:9:64:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:64:32:64:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:71:9:71:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:71:32:71:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:74:9:74:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:74:32:74:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:79:9:79:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:79:32:79:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:87:9:87:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:87:32:87:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:90:9:90:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:90:32:90:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:95:9:95:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:95:32:95:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:102:9:102:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:102:32:102:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:107:9:107:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:107:32:107:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:110:9:110:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:110:32:110:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:115:9:115:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:115:32:115:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:122:9:122:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:122:32:122:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:125:9:125:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:125:32:125:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:132:9:132:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:132:32:132:34 | ControlFlowNode for url | The full URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_requests.py:9:5:9:28 | ControlFlowNode for Attribute() | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:9:18:9:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_requests.py:17:5:17:27 | ControlFlowNode for Attribute() | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:17:17:17:26 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_requests.py:22:5:22:44 | ControlFlowNode for Attribute() | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:22:34:22:43 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | edges | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | ControlFlowNode for request | provenance | | | full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | provenance | | -| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:12:5:12:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:18:5:18:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:22:5:22:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:41:18:41:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:66:18:66:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:83:18:83:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:11:18:11:27 | ControlFlowNode for user_input | provenance | | +| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:13:5:13:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:20:5:20:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:25:5:25:7 | ControlFlowNode for url | provenance | | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:12:5:12:7 | ControlFlowNode for url | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:18:5:18:7 | ControlFlowNode for url | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:22:5:22:7 | ControlFlowNode for url | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:41:5:41:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:44:5:44:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:47:5:47:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:50:5:50:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:53:5:53:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:41:5:41:7 | ControlFlowNode for url | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:44:5:44:7 | ControlFlowNode for url | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:47:5:47:7 | ControlFlowNode for url | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:50:5:50:7 | ControlFlowNode for url | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:53:5:53:7 | ControlFlowNode for url | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:57:5:57:14 | ControlFlowNode for user_input | full_partial_test.py:61:5:61:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:57:5:57:14 | ControlFlowNode for user_input | full_partial_test.py:64:5:64:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:5:57:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:61:5:61:7 | ControlFlowNode for url | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:64:5:64:7 | ControlFlowNode for url | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | full_partial_test.py:75:5:75:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | full_partial_test.py:78:5:78:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | full_partial_test.py:81:5:81:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:75:5:75:7 | ControlFlowNode for url | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:78:5:78:7 | ControlFlowNode for url | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:81:5:81:7 | ControlFlowNode for url | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | provenance | | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:7:19:7:25 | ControlFlowNode for request | provenance | | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for request | test_azure_client.py:10:18:10:24 | ControlFlowNode for request | provenance | | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for request | test_azure_client.py:11:19:11:25 | ControlFlowNode for request | provenance | | -| test_azure_client.py:10:18:10:24 | ControlFlowNode for request | test_azure_client.py:11:5:11:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | -| test_azure_client.py:11:5:11:15 | ControlFlowNode for user_input2 | test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | provenance | | -| test_azure_client.py:11:19:11:25 | ControlFlowNode for request | test_azure_client.py:11:5:11:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:17:32:17:39 | ControlFlowNode for full_url | provenance | Sink:MaD:15 | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:19:39:19:46 | ControlFlowNode for full_url | provenance | Sink:MaD:38 | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:21:19:21:26 | ControlFlowNode for full_url | provenance | Sink:MaD:14 | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:23:58:23:65 | ControlFlowNode for full_url | provenance | Sink:MaD:26 | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:32:18:32:25 | ControlFlowNode for full_url | provenance | Sink:MaD:27 | -| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | ControlFlowNode for request | provenance | | -| test_http_client.py:1:26:1:32 | ControlFlowNode for request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | provenance | | -| test_http_client.py:1:26:1:32 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | provenance | | +| full_partial_test.py:13:5:13:7 | ControlFlowNode for url | full_partial_test.py:15:18:15:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:20:5:20:7 | ControlFlowNode for url | full_partial_test.py:22:18:22:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:25:5:25:7 | ControlFlowNode for url | full_partial_test.py:27:18:27:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:45:5:45:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:49:5:49:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:53:5:53:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:57:5:57:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:61:5:61:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:18:41:24 | ControlFlowNode for request | full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:45:5:45:7 | ControlFlowNode for url | full_partial_test.py:47:18:47:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:49:5:49:7 | ControlFlowNode for url | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:53:5:53:7 | ControlFlowNode for url | full_partial_test.py:55:18:55:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:57:5:57:7 | ControlFlowNode for url | full_partial_test.py:59:18:59:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:61:5:61:7 | ControlFlowNode for url | full_partial_test.py:63:18:63:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:66:5:66:14 | ControlFlowNode for user_input | full_partial_test.py:70:5:70:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:66:5:66:14 | ControlFlowNode for user_input | full_partial_test.py:74:5:74:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:66:18:66:24 | ControlFlowNode for request | full_partial_test.py:66:5:66:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:70:5:70:7 | ControlFlowNode for url | full_partial_test.py:72:18:72:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:74:5:74:7 | ControlFlowNode for url | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | full_partial_test.py:87:5:87:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | full_partial_test.py:91:5:91:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | full_partial_test.py:95:5:95:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:83:18:83:24 | ControlFlowNode for request | full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:87:5:87:7 | ControlFlowNode for url | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:91:5:91:7 | ControlFlowNode for url | full_partial_test.py:93:18:93:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:95:5:95:7 | ControlFlowNode for url | full_partial_test.py:97:18:97:20 | ControlFlowNode for url | provenance | | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:6:19:6:25 | ControlFlowNode for request | provenance | | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for request | test_azure_client.py:9:18:9:24 | ControlFlowNode for request | provenance | | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for request | test_azure_client.py:10:19:10:25 | ControlFlowNode for request | provenance | | +| test_azure_client.py:9:18:9:24 | ControlFlowNode for request | test_azure_client.py:10:5:10:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_azure_client.py:10:5:10:15 | ControlFlowNode for user_input2 | test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | provenance | | +| test_azure_client.py:10:19:10:25 | ControlFlowNode for request | test_azure_client.py:10:5:10:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:16:28:16:35 | ControlFlowNode for full_url | provenance | Sink:MaD:2 | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:18:35:18:42 | ControlFlowNode for full_url | provenance | Sink:MaD:4 | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:20:15:20:22 | ControlFlowNode for full_url | provenance | Sink:MaD:1 | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:22:54:22:61 | ControlFlowNode for full_url | provenance | Sink:MaD:3 | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:25:37:25:44 | ControlFlowNode for full_url | provenance | Sink:MaD:5 | +| test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:1:19:1:25 | ControlFlowNode for request | provenance | | +| test_http_client.py:1:19:1:25 | ControlFlowNode for request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | provenance | | +| test_http_client.py:1:19:1:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | provenance | | | test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | provenance | | -| test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | provenance | | -| test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | provenance | | +| test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:19:27:19:37 | ControlFlowNode for unsafe_host | provenance | | +| test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:28:27:28:37 | ControlFlowNode for unsafe_host | provenance | | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | provenance | AdditionalTaintStep | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | provenance | AdditionalTaintStep | -| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | provenance | | -| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | provenance | | -| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | provenance | | +| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:15:25:15:35 | ControlFlowNode for unsafe_path | provenance | | +| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | provenance | | +| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:34:25:34:35 | ControlFlowNode for unsafe_path | provenance | | | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | provenance | AdditionalTaintStep | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:5:19:5:25 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:8:18:8:24 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:9:19:9:25 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:24:18:24:24 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:25:19:25:25 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:40:18:40:24 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:41:19:41:25 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:57:18:57:24 | ControlFlowNode for request | provenance | | +| test_path_validation.py:8:18:8:24 | ControlFlowNode for request | test_path_validation.py:9:5:9:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:9:5:9:15 | ControlFlowNode for user_input2 | test_path_validation.py:11:5:11:12 | ControlFlowNode for full_url | provenance | | +| test_path_validation.py:9:19:9:25 | ControlFlowNode for request | test_path_validation.py:9:5:9:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:11:5:11:12 | ControlFlowNode for full_url | test_path_validation.py:21:32:21:39 | ControlFlowNode for full_url | provenance | Sink:MaD:2 | +| test_path_validation.py:24:18:24:24 | ControlFlowNode for request | test_path_validation.py:25:5:25:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:25:5:25:15 | ControlFlowNode for user_input2 | test_path_validation.py:27:5:27:12 | ControlFlowNode for full_url | provenance | | +| test_path_validation.py:25:19:25:25 | ControlFlowNode for request | test_path_validation.py:25:5:25:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:27:5:27:12 | ControlFlowNode for full_url | test_path_validation.py:37:29:37:36 | ControlFlowNode for full_url | provenance | Sink:MaD:1 | +| test_path_validation.py:40:18:40:24 | ControlFlowNode for request | test_path_validation.py:41:5:41:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:41:5:41:15 | ControlFlowNode for user_input2 | test_path_validation.py:43:5:43:12 | ControlFlowNode for full_url | provenance | | +| test_path_validation.py:41:19:41:25 | ControlFlowNode for request | test_path_validation.py:41:5:41:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:43:5:43:12 | ControlFlowNode for full_url | test_path_validation.py:53:39:53:46 | ControlFlowNode for full_url | provenance | Sink:MaD:4 | +| test_path_validation.py:57:5:57:14 | ControlFlowNode for user_input | test_path_validation.py:61:5:61:7 | ControlFlowNode for url | provenance | | +| test_path_validation.py:57:18:57:24 | ControlFlowNode for request | test_path_validation.py:57:5:57:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:64:32:64:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:71:32:71:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:74:32:74:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:79:32:79:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:87:32:87:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:90:32:90:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:95:32:95:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:102:32:102:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:107:32:107:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:110:32:110:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:115:32:115:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:122:32:122:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:125:32:125:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:132:32:132:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | ControlFlowNode for request | provenance | | -| test_requests.py:1:19:1:25 | ControlFlowNode for request | test_requests.py:6:18:6:24 | ControlFlowNode for request | provenance | | -| test_requests.py:6:5:6:14 | ControlFlowNode for user_input | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | provenance | | -| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:5:6:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_requests.py:1:19:1:25 | ControlFlowNode for request | test_requests.py:7:18:7:24 | ControlFlowNode for request | provenance | | +| test_requests.py:1:19:1:25 | ControlFlowNode for request | test_requests.py:14:18:14:24 | ControlFlowNode for request | provenance | | +| test_requests.py:1:19:1:25 | ControlFlowNode for request | test_requests.py:20:18:20:24 | ControlFlowNode for request | provenance | | +| test_requests.py:7:5:7:14 | ControlFlowNode for user_input | test_requests.py:9:18:9:27 | ControlFlowNode for user_input | provenance | | +| test_requests.py:7:18:7:24 | ControlFlowNode for request | test_requests.py:7:5:7:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_requests.py:14:5:14:14 | ControlFlowNode for user_input | test_requests.py:17:17:17:26 | ControlFlowNode for user_input | provenance | | +| test_requests.py:14:18:14:24 | ControlFlowNode for request | test_requests.py:14:5:14:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_requests.py:20:5:20:14 | ControlFlowNode for user_input | test_requests.py:22:34:22:43 | ControlFlowNode for user_input | provenance | | +| test_requests.py:20:18:20:24 | ControlFlowNode for request | test_requests.py:20:5:20:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +models +| 1 | Sink: azure.keyvault.keys.KeyClient!; Call.Argument[0,vault_url:]; request-forgery | +| 2 | Sink: azure.keyvault.secrets.SecretClient!; Call.Argument[0,vault_url:]; request-forgery | +| 3 | Sink: azure.storage.blob.ContainerClient!; Member[from_container_url].Argument[0,container_url:]; request-forgery | +| 4 | Sink: azure.storage.fileshare.ShareFileClient!; Member[from_file_url].Argument[0,file_url:]; request-forgery | +| 5 | Sink: azure; Member[storage].Member[blob].Member[download_blob_from_url].Argument[0,blob_url:]; request-forgery | nodes | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | full_partial_test.py:1:19:1:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:12:5:12:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:18:5:18:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:22:5:22:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:41:5:41:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:44:5:44:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:47:5:47:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:50:5:50:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:11:18:11:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:13:5:13:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:15:18:15:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:20:5:20:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:22:18:22:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:25:5:25:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:27:18:27:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:41:18:41:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:45:5:45:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:47:18:47:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:49:5:49:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:53:5:53:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:57:5:57:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:55:18:55:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:57:5:57:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:59:18:59:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:61:5:61:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:64:5:64:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:75:5:75:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:63:18:63:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:66:5:66:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:66:18:66:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:70:5:70:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:72:18:72:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:74:5:74:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:78:5:78:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:81:5:81:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_azure_client.py:10:18:10:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_azure_client.py:11:5:11:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | -| test_azure_client.py:11:19:11:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:17:32:17:39 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:19:39:19:46 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:21:19:21:26 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:23:58:23:65 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:32:18:32:25 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | -| test_http_client.py:1:26:1:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:83:18:83:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:87:5:87:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:89:18:89:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:91:5:91:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:93:18:93:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:95:5:95:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:97:18:97:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_azure_client.py:9:18:9:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_azure_client.py:10:5:10:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | +| test_azure_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:16:28:16:35 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:18:35:18:42 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:20:15:20:22 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:22:54:22:61 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:25:37:25:44 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:19:1:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | | test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | -| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | -| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | -| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | -| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | -| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | +| test_http_client.py:15:25:15:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | +| test_http_client.py:19:27:19:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | +| test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | +| test_http_client.py:28:27:28:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | +| test_http_client.py:34:25:34:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:8:18:8:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:9:5:9:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | +| test_path_validation.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:11:5:11:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:21:32:21:39 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:24:18:24:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:25:5:25:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | +| test_path_validation.py:25:19:25:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:27:5:27:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:37:29:37:36 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:40:18:40:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:41:5:41:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | +| test_path_validation.py:41:19:41:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:43:5:43:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:53:39:53:46 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:57:5:57:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_path_validation.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:64:32:64:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:71:32:71:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:74:32:74:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:79:32:79:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:87:32:87:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:90:32:90:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:95:32:95:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:102:32:102:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:107:32:107:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:110:32:110:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:115:32:115:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:122:32:122:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:125:32:125:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:132:32:132:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | test_requests.py:1:19:1:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_requests.py:6:5:6:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:7:5:7:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_requests.py:9:18:9:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:14:5:14:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:14:18:14:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_requests.py:17:17:17:26 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:20:5:20:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:20:18:20:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_requests.py:22:34:22:43 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | subpaths -#select -| full_partial_test.py:10:5:10:28 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:13:5:13:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:19:5:19:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:23:5:23:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:42:5:42:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:45:5:45:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:48:5:48:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:51:5:51:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:54:5:54:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:62:5:62:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:65:5:65:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:76:5:76:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:79:5:79:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:82:5:82:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:17:9:17:63 | ControlFlowNode for SecretClient() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:17:32:17:39 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:19:9:19:47 | ControlFlowNode for Attribute() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:19:39:19:46 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:21:9:21:39 | ControlFlowNode for KeyClient() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:21:19:21:26 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:23:9:23:89 | ControlFlowNode for Attribute() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:23:58:23:65 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:31:5:36:5 | ControlFlowNode for download_blob_from_url() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:32:18:32:25 | ControlFlowNode for full_url | The full URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| test_requests.py:8:5:8:28 | ControlFlowNode for Attribute() | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.qlref b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.qlref index 50d53b5f47e..f0a8d1e6b15 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.qlref +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.qlref @@ -1 +1,4 @@ -Security/CWE-918/FullServerSideRequestForgery.ql +query: Security/CWE-918/FullServerSideRequestForgery.ql +postprocess: +- utils/test/InlineExpectationsTestQuery.ql +- utils/test/PrettyPrintModels.ql \ No newline at end of file diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected index bdcac746538..0b875607157 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected @@ -1,124 +1,242 @@ +#select +| full_partial_test.py:80:5:80:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:80:18:80:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:105:5:105:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:105:18:105:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:112:5:112:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:112:18:112:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:119:5:119:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:119:18:119:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:126:5:126:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:126:18:126:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:136:5:136:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:136:18:136:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:143:5:143:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:143:18:143:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:15:5:15:54 | ControlFlowNode for SecretClient() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:15:28:15:30 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:17:5:17:38 | ControlFlowNode for Attribute() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:17:35:17:37 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:19:5:19:30 | ControlFlowNode for KeyClient() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:19:15:19:17 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:21:5:21:80 | ControlFlowNode for Attribute() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:21:54:21:56 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_azure_client.py:24:5:24:100 | ControlFlowNode for download_blob_from_url() | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:24:37:24:39 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:25:5:25:31 | ControlFlowNode for Attribute() | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:19:27:19:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:30:5:30:31 | ControlFlowNode for Attribute() | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:28:27:28:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:34:5:34:36 | ControlFlowNode for Attribute() | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:34:25:34:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on a $@. | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:39:5:39:29 | ControlFlowNode for Attribute() | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:39:25:39:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:44:5:44:29 | ControlFlowNode for Attribute() | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:44:25:44:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:14:9:14:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:14:32:14:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:16:9:16:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:16:32:16:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:19:9:19:63 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:19:32:19:39 | ControlFlowNode for full_url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:30:9:30:55 | ControlFlowNode for KeyClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:30:29:30:31 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:32:9:32:55 | ControlFlowNode for KeyClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:32:29:32:31 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:35:9:35:60 | ControlFlowNode for KeyClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:35:29:35:36 | ControlFlowNode for full_url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:46:9:46:42 | ControlFlowNode for Attribute() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:46:39:46:41 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:48:9:48:42 | ControlFlowNode for Attribute() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:48:39:48:41 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:51:9:51:47 | ControlFlowNode for Attribute() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:51:39:51:46 | ControlFlowNode for full_url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:66:9:66:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:66:32:66:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:69:9:69:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:69:32:69:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:76:9:76:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:76:32:76:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:81:9:81:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:81:32:81:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:85:9:85:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:85:32:85:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:92:9:92:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:92:32:92:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:97:9:97:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:97:32:97:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:100:9:100:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:100:32:100:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:105:9:105:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:105:32:105:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:112:9:112:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:112:32:112:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:117:9:117:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:117:32:117:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:120:9:120:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:120:32:120:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:127:9:127:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:127:32:127:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | +| test_path_validation.py:130:9:130:58 | ControlFlowNode for SecretClient() | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:130:32:130:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | user-provided value | edges | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | ControlFlowNode for request | provenance | | | full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | provenance | | | full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:38:17:38:23 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:72:17:72:23 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | provenance | | -| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | provenance | | -| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:12:5:12:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:18:5:18:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:22:5:22:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:41:18:41:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:42:17:42:23 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:66:18:66:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:67:17:67:23 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:83:18:83:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:84:17:84:23 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:101:18:101:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:108:18:108:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:115:18:115:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:122:18:122:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:129:18:129:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for request | full_partial_test.py:139:18:139:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:11:18:11:27 | ControlFlowNode for user_input | provenance | | +| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:13:5:13:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:20:5:20:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | full_partial_test.py:25:5:25:7 | ControlFlowNode for url | provenance | | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:5:7:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:5:8:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | -| full_partial_test.py:8:5:8:13 | ControlFlowNode for query_val | full_partial_test.py:22:5:22:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:8:5:8:13 | ControlFlowNode for query_val | full_partial_test.py:25:5:25:7 | ControlFlowNode for url | provenance | | | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:8:5:8:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | -| full_partial_test.py:12:5:12:7 | ControlFlowNode for url | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:18:5:18:7 | ControlFlowNode for url | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:22:5:22:7 | ControlFlowNode for url | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:41:5:41:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:44:5:44:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:47:5:47:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:50:5:50:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | full_partial_test.py:53:5:53:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:38:5:38:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | -| full_partial_test.py:38:5:38:13 | ControlFlowNode for query_val | full_partial_test.py:47:5:47:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | full_partial_test.py:38:5:38:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | -| full_partial_test.py:41:5:41:7 | ControlFlowNode for url | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:44:5:44:7 | ControlFlowNode for url | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:47:5:47:7 | ControlFlowNode for url | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:50:5:50:7 | ControlFlowNode for url | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:53:5:53:7 | ControlFlowNode for url | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:57:5:57:14 | ControlFlowNode for user_input | full_partial_test.py:61:5:61:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:57:5:57:14 | ControlFlowNode for user_input | full_partial_test.py:64:5:64:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:57:5:57:14 | ControlFlowNode for user_input | full_partial_test.py:67:5:67:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:5:57:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:58:5:58:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | -| full_partial_test.py:58:5:58:13 | ControlFlowNode for query_val | full_partial_test.py:67:5:67:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:58:5:58:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | -| full_partial_test.py:61:5:61:7 | ControlFlowNode for url | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:64:5:64:7 | ControlFlowNode for url | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:67:5:67:7 | ControlFlowNode for url | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | full_partial_test.py:75:5:75:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | full_partial_test.py:78:5:78:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | full_partial_test.py:81:5:81:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:72:5:72:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | -| full_partial_test.py:72:5:72:13 | ControlFlowNode for query_val | full_partial_test.py:81:5:81:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | full_partial_test.py:72:5:72:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | -| full_partial_test.py:75:5:75:7 | ControlFlowNode for url | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:78:5:78:7 | ControlFlowNode for url | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:81:5:81:7 | ControlFlowNode for url | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:86:5:86:14 | ControlFlowNode for user_input | full_partial_test.py:88:5:88:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:86:5:86:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:88:5:88:7 | ControlFlowNode for url | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:92:5:92:14 | ControlFlowNode for user_input | full_partial_test.py:94:5:94:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:92:18:92:24 | ControlFlowNode for request | full_partial_test.py:92:5:92:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:94:5:94:7 | ControlFlowNode for url | full_partial_test.py:95:18:95:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:98:5:98:14 | ControlFlowNode for user_input | full_partial_test.py:100:5:100:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:98:18:98:24 | ControlFlowNode for request | full_partial_test.py:98:5:98:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:100:5:100:7 | ControlFlowNode for url | full_partial_test.py:101:18:101:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:104:5:104:14 | ControlFlowNode for user_input | full_partial_test.py:106:5:106:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:104:18:104:24 | ControlFlowNode for request | full_partial_test.py:104:5:104:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:106:5:106:7 | ControlFlowNode for url | full_partial_test.py:107:18:107:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:110:5:110:14 | ControlFlowNode for user_input | full_partial_test.py:115:5:115:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:110:18:110:24 | ControlFlowNode for request | full_partial_test.py:110:5:110:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:115:5:115:7 | ControlFlowNode for url | full_partial_test.py:116:18:116:20 | ControlFlowNode for url | provenance | | -| full_partial_test.py:119:5:119:14 | ControlFlowNode for user_input | full_partial_test.py:121:5:121:7 | ControlFlowNode for url | provenance | | -| full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:119:5:119:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| full_partial_test.py:121:5:121:7 | ControlFlowNode for url | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | provenance | | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:7:19:7:25 | ControlFlowNode for request | provenance | | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for request | test_azure_client.py:10:18:10:24 | ControlFlowNode for request | provenance | | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for request | test_azure_client.py:11:19:11:25 | ControlFlowNode for request | provenance | | -| test_azure_client.py:10:5:10:14 | ControlFlowNode for user_input | test_azure_client.py:13:5:13:7 | ControlFlowNode for url | provenance | | -| test_azure_client.py:10:18:10:24 | ControlFlowNode for request | test_azure_client.py:10:5:10:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| test_azure_client.py:10:18:10:24 | ControlFlowNode for request | test_azure_client.py:11:5:11:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | -| test_azure_client.py:11:5:11:15 | ControlFlowNode for user_input2 | test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | provenance | | -| test_azure_client.py:11:19:11:25 | ControlFlowNode for request | test_azure_client.py:11:5:11:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | -| test_azure_client.py:13:5:13:7 | ControlFlowNode for url | test_azure_client.py:16:32:16:34 | ControlFlowNode for url | provenance | Sink:MaD:15 | -| test_azure_client.py:13:5:13:7 | ControlFlowNode for url | test_azure_client.py:18:39:18:41 | ControlFlowNode for url | provenance | Sink:MaD:38 | -| test_azure_client.py:13:5:13:7 | ControlFlowNode for url | test_azure_client.py:20:19:20:21 | ControlFlowNode for url | provenance | Sink:MaD:14 | -| test_azure_client.py:13:5:13:7 | ControlFlowNode for url | test_azure_client.py:22:58:22:60 | ControlFlowNode for url | provenance | Sink:MaD:26 | -| test_azure_client.py:13:5:13:7 | ControlFlowNode for url | test_azure_client.py:26:18:26:20 | ControlFlowNode for url | provenance | Sink:MaD:27 | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:17:32:17:39 | ControlFlowNode for full_url | provenance | Sink:MaD:15 | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:19:39:19:46 | ControlFlowNode for full_url | provenance | Sink:MaD:38 | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:21:19:21:26 | ControlFlowNode for full_url | provenance | Sink:MaD:14 | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:23:58:23:65 | ControlFlowNode for full_url | provenance | Sink:MaD:26 | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | test_azure_client.py:32:18:32:25 | ControlFlowNode for full_url | provenance | Sink:MaD:27 | -| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | ControlFlowNode for request | provenance | | -| test_http_client.py:1:26:1:32 | ControlFlowNode for request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | provenance | | -| test_http_client.py:1:26:1:32 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | provenance | | -| test_http_client.py:1:26:1:32 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request | provenance | | +| full_partial_test.py:13:5:13:7 | ControlFlowNode for url | full_partial_test.py:15:18:15:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:20:5:20:7 | ControlFlowNode for url | full_partial_test.py:22:18:22:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:25:5:25:7 | ControlFlowNode for url | full_partial_test.py:27:18:27:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:45:5:45:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:49:5:49:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:53:5:53:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:57:5:57:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | full_partial_test.py:61:5:61:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:41:18:41:24 | ControlFlowNode for request | full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:41:18:41:24 | ControlFlowNode for request | full_partial_test.py:42:5:42:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | +| full_partial_test.py:42:5:42:13 | ControlFlowNode for query_val | full_partial_test.py:53:5:53:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:42:17:42:23 | ControlFlowNode for request | full_partial_test.py:42:5:42:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | +| full_partial_test.py:45:5:45:7 | ControlFlowNode for url | full_partial_test.py:47:18:47:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:49:5:49:7 | ControlFlowNode for url | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:53:5:53:7 | ControlFlowNode for url | full_partial_test.py:55:18:55:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:57:5:57:7 | ControlFlowNode for url | full_partial_test.py:59:18:59:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:61:5:61:7 | ControlFlowNode for url | full_partial_test.py:63:18:63:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:66:5:66:14 | ControlFlowNode for user_input | full_partial_test.py:70:5:70:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:66:5:66:14 | ControlFlowNode for user_input | full_partial_test.py:74:5:74:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:66:5:66:14 | ControlFlowNode for user_input | full_partial_test.py:78:5:78:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:66:18:66:24 | ControlFlowNode for request | full_partial_test.py:66:5:66:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:66:18:66:24 | ControlFlowNode for request | full_partial_test.py:67:5:67:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | +| full_partial_test.py:67:5:67:13 | ControlFlowNode for query_val | full_partial_test.py:78:5:78:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:67:17:67:23 | ControlFlowNode for request | full_partial_test.py:67:5:67:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | +| full_partial_test.py:70:5:70:7 | ControlFlowNode for url | full_partial_test.py:72:18:72:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:74:5:74:7 | ControlFlowNode for url | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:78:5:78:7 | ControlFlowNode for url | full_partial_test.py:80:18:80:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | full_partial_test.py:87:5:87:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | full_partial_test.py:91:5:91:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | full_partial_test.py:95:5:95:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:83:18:83:24 | ControlFlowNode for request | full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:83:18:83:24 | ControlFlowNode for request | full_partial_test.py:84:5:84:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | +| full_partial_test.py:84:5:84:13 | ControlFlowNode for query_val | full_partial_test.py:95:5:95:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:84:17:84:23 | ControlFlowNode for request | full_partial_test.py:84:5:84:13 | ControlFlowNode for query_val | provenance | AdditionalTaintStep | +| full_partial_test.py:87:5:87:7 | ControlFlowNode for url | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:91:5:91:7 | ControlFlowNode for url | full_partial_test.py:93:18:93:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:95:5:95:7 | ControlFlowNode for url | full_partial_test.py:97:18:97:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:101:5:101:14 | ControlFlowNode for user_input | full_partial_test.py:103:5:103:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:101:18:101:24 | ControlFlowNode for request | full_partial_test.py:101:5:101:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:103:5:103:7 | ControlFlowNode for url | full_partial_test.py:105:18:105:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:108:5:108:14 | ControlFlowNode for user_input | full_partial_test.py:110:5:110:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:108:18:108:24 | ControlFlowNode for request | full_partial_test.py:108:5:108:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:110:5:110:7 | ControlFlowNode for url | full_partial_test.py:112:18:112:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:115:5:115:14 | ControlFlowNode for user_input | full_partial_test.py:117:5:117:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:115:18:115:24 | ControlFlowNode for request | full_partial_test.py:115:5:115:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:117:5:117:7 | ControlFlowNode for url | full_partial_test.py:119:18:119:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:122:5:122:14 | ControlFlowNode for user_input | full_partial_test.py:124:5:124:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:122:18:122:24 | ControlFlowNode for request | full_partial_test.py:122:5:122:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:124:5:124:7 | ControlFlowNode for url | full_partial_test.py:126:18:126:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:129:5:129:14 | ControlFlowNode for user_input | full_partial_test.py:134:5:134:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:129:18:129:24 | ControlFlowNode for request | full_partial_test.py:129:5:129:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:134:5:134:7 | ControlFlowNode for url | full_partial_test.py:136:18:136:20 | ControlFlowNode for url | provenance | | +| full_partial_test.py:139:5:139:14 | ControlFlowNode for user_input | full_partial_test.py:141:5:141:7 | ControlFlowNode for url | provenance | | +| full_partial_test.py:139:18:139:24 | ControlFlowNode for request | full_partial_test.py:139:5:139:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| full_partial_test.py:141:5:141:7 | ControlFlowNode for url | full_partial_test.py:143:18:143:20 | ControlFlowNode for url | provenance | | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | test_azure_client.py:6:19:6:25 | ControlFlowNode for request | provenance | | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for request | test_azure_client.py:9:18:9:24 | ControlFlowNode for request | provenance | | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for request | test_azure_client.py:10:19:10:25 | ControlFlowNode for request | provenance | | +| test_azure_client.py:9:5:9:14 | ControlFlowNode for user_input | test_azure_client.py:12:5:12:7 | ControlFlowNode for url | provenance | | +| test_azure_client.py:9:18:9:24 | ControlFlowNode for request | test_azure_client.py:9:5:9:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_azure_client.py:9:18:9:24 | ControlFlowNode for request | test_azure_client.py:10:5:10:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_azure_client.py:10:5:10:15 | ControlFlowNode for user_input2 | test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | provenance | | +| test_azure_client.py:10:19:10:25 | ControlFlowNode for request | test_azure_client.py:10:5:10:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_azure_client.py:12:5:12:7 | ControlFlowNode for url | test_azure_client.py:15:28:15:30 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_azure_client.py:12:5:12:7 | ControlFlowNode for url | test_azure_client.py:17:35:17:37 | ControlFlowNode for url | provenance | Sink:MaD:4 | +| test_azure_client.py:12:5:12:7 | ControlFlowNode for url | test_azure_client.py:19:15:19:17 | ControlFlowNode for url | provenance | Sink:MaD:1 | +| test_azure_client.py:12:5:12:7 | ControlFlowNode for url | test_azure_client.py:21:54:21:56 | ControlFlowNode for url | provenance | Sink:MaD:3 | +| test_azure_client.py:12:5:12:7 | ControlFlowNode for url | test_azure_client.py:24:37:24:39 | ControlFlowNode for url | provenance | Sink:MaD:5 | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:16:28:16:35 | ControlFlowNode for full_url | provenance | Sink:MaD:2 | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:18:35:18:42 | ControlFlowNode for full_url | provenance | Sink:MaD:4 | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:20:15:20:22 | ControlFlowNode for full_url | provenance | Sink:MaD:1 | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:22:54:22:61 | ControlFlowNode for full_url | provenance | Sink:MaD:3 | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | test_azure_client.py:25:37:25:44 | ControlFlowNode for full_url | provenance | Sink:MaD:5 | +| test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | test_http_client.py:1:19:1:25 | ControlFlowNode for request | provenance | | +| test_http_client.py:1:19:1:25 | ControlFlowNode for request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | provenance | | +| test_http_client.py:1:19:1:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | provenance | | +| test_http_client.py:1:19:1:25 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request | provenance | | | test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | provenance | | -| test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | provenance | | -| test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | provenance | | +| test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:19:27:19:37 | ControlFlowNode for unsafe_host | provenance | | +| test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | test_http_client.py:28:27:28:37 | ControlFlowNode for unsafe_host | provenance | | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | provenance | AdditionalTaintStep | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | provenance | AdditionalTaintStep | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:5:11:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | provenance | | -| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | provenance | | -| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | provenance | | +| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:15:25:15:35 | ControlFlowNode for unsafe_path | provenance | | +| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | provenance | | +| test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | test_http_client.py:34:25:34:35 | ControlFlowNode for unsafe_path | provenance | | | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | provenance | AdditionalTaintStep | | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:5:11:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| test_http_client.py:11:5:11:14 | ControlFlowNode for user_input | test_http_client.py:31:5:31:8 | ControlFlowNode for path | provenance | | -| test_http_client.py:11:5:11:14 | ControlFlowNode for user_input | test_http_client.py:35:5:35:8 | ControlFlowNode for path | provenance | | +| test_http_client.py:11:5:11:14 | ControlFlowNode for user_input | test_http_client.py:36:5:36:8 | ControlFlowNode for path | provenance | | +| test_http_client.py:11:5:11:14 | ControlFlowNode for user_input | test_http_client.py:41:5:41:8 | ControlFlowNode for path | provenance | | | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:11:5:11:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | -| test_http_client.py:31:5:31:8 | ControlFlowNode for path | test_http_client.py:33:25:33:28 | ControlFlowNode for path | provenance | | -| test_http_client.py:35:5:35:8 | ControlFlowNode for path | test_http_client.py:37:25:37:28 | ControlFlowNode for path | provenance | | +| test_http_client.py:36:5:36:8 | ControlFlowNode for path | test_http_client.py:39:25:39:28 | ControlFlowNode for path | provenance | | +| test_http_client.py:41:5:41:8 | ControlFlowNode for path | test_http_client.py:44:25:44:28 | ControlFlowNode for path | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | test_path_validation.py:5:19:5:25 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:8:18:8:24 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:9:19:9:25 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:24:18:24:24 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:25:19:25:25 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:40:18:40:24 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:41:19:41:25 | ControlFlowNode for request | provenance | | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | test_path_validation.py:57:18:57:24 | ControlFlowNode for request | provenance | | +| test_path_validation.py:8:5:8:14 | ControlFlowNode for user_input | test_path_validation.py:10:5:10:7 | ControlFlowNode for url | provenance | | +| test_path_validation.py:8:18:8:24 | ControlFlowNode for request | test_path_validation.py:8:5:8:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_path_validation.py:8:18:8:24 | ControlFlowNode for request | test_path_validation.py:9:5:9:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:9:5:9:15 | ControlFlowNode for user_input2 | test_path_validation.py:11:5:11:12 | ControlFlowNode for full_url | provenance | | +| test_path_validation.py:9:19:9:25 | ControlFlowNode for request | test_path_validation.py:9:5:9:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:10:5:10:7 | ControlFlowNode for url | test_path_validation.py:14:32:14:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:10:5:10:7 | ControlFlowNode for url | test_path_validation.py:16:32:16:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:11:5:11:12 | ControlFlowNode for full_url | test_path_validation.py:19:32:19:39 | ControlFlowNode for full_url | provenance | Sink:MaD:2 | +| test_path_validation.py:11:5:11:12 | ControlFlowNode for full_url | test_path_validation.py:21:32:21:39 | ControlFlowNode for full_url | provenance | Sink:MaD:2 | +| test_path_validation.py:24:5:24:14 | ControlFlowNode for user_input | test_path_validation.py:26:5:26:7 | ControlFlowNode for url | provenance | | +| test_path_validation.py:24:18:24:24 | ControlFlowNode for request | test_path_validation.py:24:5:24:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_path_validation.py:24:18:24:24 | ControlFlowNode for request | test_path_validation.py:25:5:25:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:25:5:25:15 | ControlFlowNode for user_input2 | test_path_validation.py:27:5:27:12 | ControlFlowNode for full_url | provenance | | +| test_path_validation.py:25:19:25:25 | ControlFlowNode for request | test_path_validation.py:25:5:25:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:26:5:26:7 | ControlFlowNode for url | test_path_validation.py:30:29:30:31 | ControlFlowNode for url | provenance | Sink:MaD:1 | +| test_path_validation.py:26:5:26:7 | ControlFlowNode for url | test_path_validation.py:32:29:32:31 | ControlFlowNode for url | provenance | Sink:MaD:1 | +| test_path_validation.py:27:5:27:12 | ControlFlowNode for full_url | test_path_validation.py:35:29:35:36 | ControlFlowNode for full_url | provenance | Sink:MaD:1 | +| test_path_validation.py:27:5:27:12 | ControlFlowNode for full_url | test_path_validation.py:37:29:37:36 | ControlFlowNode for full_url | provenance | Sink:MaD:1 | +| test_path_validation.py:40:5:40:14 | ControlFlowNode for user_input | test_path_validation.py:42:5:42:7 | ControlFlowNode for url | provenance | | +| test_path_validation.py:40:18:40:24 | ControlFlowNode for request | test_path_validation.py:40:5:40:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_path_validation.py:40:18:40:24 | ControlFlowNode for request | test_path_validation.py:41:5:41:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:41:5:41:15 | ControlFlowNode for user_input2 | test_path_validation.py:43:5:43:12 | ControlFlowNode for full_url | provenance | | +| test_path_validation.py:41:19:41:25 | ControlFlowNode for request | test_path_validation.py:41:5:41:15 | ControlFlowNode for user_input2 | provenance | AdditionalTaintStep | +| test_path_validation.py:42:5:42:7 | ControlFlowNode for url | test_path_validation.py:46:39:46:41 | ControlFlowNode for url | provenance | Sink:MaD:4 | +| test_path_validation.py:42:5:42:7 | ControlFlowNode for url | test_path_validation.py:48:39:48:41 | ControlFlowNode for url | provenance | Sink:MaD:4 | +| test_path_validation.py:43:5:43:12 | ControlFlowNode for full_url | test_path_validation.py:51:39:51:46 | ControlFlowNode for full_url | provenance | Sink:MaD:4 | +| test_path_validation.py:43:5:43:12 | ControlFlowNode for full_url | test_path_validation.py:53:39:53:46 | ControlFlowNode for full_url | provenance | Sink:MaD:4 | +| test_path_validation.py:57:5:57:14 | ControlFlowNode for user_input | test_path_validation.py:61:5:61:7 | ControlFlowNode for url | provenance | | +| test_path_validation.py:57:18:57:24 | ControlFlowNode for request | test_path_validation.py:57:5:57:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:64:32:64:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:66:32:66:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:69:32:69:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:71:32:71:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:74:32:74:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:76:32:76:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:79:32:79:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:81:32:81:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:85:32:85:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:87:32:87:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:90:32:90:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:92:32:92:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:95:32:95:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:97:32:97:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:100:32:100:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:102:32:102:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:105:32:105:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:107:32:107:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:110:32:110:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:112:32:112:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:115:32:115:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:117:32:117:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:120:32:120:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:122:32:122:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:125:32:125:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:127:32:127:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:130:32:130:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | test_path_validation.py:132:32:132:34 | ControlFlowNode for url | provenance | Sink:MaD:2 | | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | ControlFlowNode for request | provenance | | -| test_requests.py:1:19:1:25 | ControlFlowNode for request | test_requests.py:6:18:6:24 | ControlFlowNode for request | provenance | | -| test_requests.py:6:5:6:14 | ControlFlowNode for user_input | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | provenance | | -| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:5:6:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_requests.py:1:19:1:25 | ControlFlowNode for request | test_requests.py:7:18:7:24 | ControlFlowNode for request | provenance | | +| test_requests.py:1:19:1:25 | ControlFlowNode for request | test_requests.py:14:18:14:24 | ControlFlowNode for request | provenance | | +| test_requests.py:1:19:1:25 | ControlFlowNode for request | test_requests.py:20:18:20:24 | ControlFlowNode for request | provenance | | +| test_requests.py:7:5:7:14 | ControlFlowNode for user_input | test_requests.py:9:18:9:27 | ControlFlowNode for user_input | provenance | | +| test_requests.py:7:18:7:24 | ControlFlowNode for request | test_requests.py:7:5:7:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_requests.py:14:5:14:14 | ControlFlowNode for user_input | test_requests.py:17:17:17:26 | ControlFlowNode for user_input | provenance | | +| test_requests.py:14:18:14:24 | ControlFlowNode for request | test_requests.py:14:5:14:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +| test_requests.py:20:5:20:14 | ControlFlowNode for user_input | test_requests.py:22:34:22:43 | ControlFlowNode for user_input | provenance | | +| test_requests.py:20:18:20:24 | ControlFlowNode for request | test_requests.py:20:5:20:14 | ControlFlowNode for user_input | provenance | AdditionalTaintStep | +models +| 1 | Sink: azure.keyvault.keys.KeyClient!; Call.Argument[0,vault_url:]; request-forgery | +| 2 | Sink: azure.keyvault.secrets.SecretClient!; Call.Argument[0,vault_url:]; request-forgery | +| 3 | Sink: azure.storage.blob.ContainerClient!; Member[from_container_url].Argument[0,container_url:]; request-forgery | +| 4 | Sink: azure.storage.fileshare.ShareFileClient!; Member[from_file_url].Argument[0,file_url:]; request-forgery | +| 5 | Sink: azure; Member[storage].Member[blob].Member[download_blob_from_url].Argument[0,blob_url:]; request-forgery | nodes | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | full_partial_test.py:1:19:1:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | @@ -126,91 +244,91 @@ nodes | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:8:5:8:13 | ControlFlowNode for query_val | semmle.label | ControlFlowNode for query_val | | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:12:5:12:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:18:5:18:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:22:5:22:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:37:5:37:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:38:5:38:13 | ControlFlowNode for query_val | semmle.label | ControlFlowNode for query_val | -| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:41:5:41:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:44:5:44:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:47:5:47:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:50:5:50:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:11:18:11:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:13:5:13:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:15:18:15:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:20:5:20:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:22:18:22:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:25:5:25:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:27:18:27:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:41:5:41:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:41:18:41:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:42:5:42:13 | ControlFlowNode for query_val | semmle.label | ControlFlowNode for query_val | +| full_partial_test.py:42:17:42:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:45:5:45:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:47:18:47:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:49:5:49:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:53:5:53:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:57:5:57:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:58:5:58:13 | ControlFlowNode for query_val | semmle.label | ControlFlowNode for query_val | -| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:55:18:55:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:57:5:57:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:59:18:59:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:61:5:61:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:64:5:64:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:67:5:67:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:68:18:68:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:71:5:71:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:72:5:72:13 | ControlFlowNode for query_val | semmle.label | ControlFlowNode for query_val | -| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:75:5:75:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:63:18:63:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:66:5:66:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:66:18:66:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:67:5:67:13 | ControlFlowNode for query_val | semmle.label | ControlFlowNode for query_val | +| full_partial_test.py:67:17:67:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:70:5:70:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:72:18:72:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:74:5:74:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:78:5:78:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:81:5:81:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:86:5:86:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:88:5:88:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:80:18:80:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:83:5:83:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:83:18:83:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:84:5:84:13 | ControlFlowNode for query_val | semmle.label | ControlFlowNode for query_val | +| full_partial_test.py:84:17:84:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:87:5:87:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:92:5:92:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:92:18:92:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:94:5:94:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:95:18:95:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:98:5:98:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:98:18:98:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:100:5:100:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:101:18:101:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:104:5:104:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:104:18:104:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:106:5:106:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:107:18:107:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:110:5:110:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:110:18:110:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:115:5:115:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:116:18:116:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:119:5:119:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| full_partial_test.py:119:18:119:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| full_partial_test.py:121:5:121:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| full_partial_test.py:122:18:122:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | -| test_azure_client.py:7:19:7:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_azure_client.py:10:5:10:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| test_azure_client.py:10:18:10:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_azure_client.py:11:5:11:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | -| test_azure_client.py:11:19:11:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_azure_client.py:13:5:13:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| test_azure_client.py:14:5:14:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:16:32:16:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| test_azure_client.py:17:32:17:39 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:18:39:18:41 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| test_azure_client.py:19:39:19:46 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:20:19:20:21 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| test_azure_client.py:21:19:21:26 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:22:58:22:60 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| test_azure_client.py:23:58:23:65 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_azure_client.py:26:18:26:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | -| test_azure_client.py:32:18:32:25 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | -| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | -| test_http_client.py:1:26:1:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:91:5:91:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:93:18:93:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:95:5:95:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:97:18:97:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:101:5:101:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:101:18:101:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:103:5:103:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:105:18:105:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:108:5:108:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:108:18:108:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:110:5:110:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:112:18:112:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:115:5:115:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:115:18:115:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:117:5:117:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:119:18:119:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:122:5:122:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:122:18:122:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:124:5:124:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:126:18:126:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:129:5:129:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:129:18:129:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:134:5:134:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:136:18:136:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:139:5:139:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| full_partial_test.py:139:18:139:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| full_partial_test.py:141:5:141:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| full_partial_test.py:143:18:143:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_azure_client.py:6:19:6:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_azure_client.py:9:5:9:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_azure_client.py:9:18:9:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_azure_client.py:10:5:10:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | +| test_azure_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_azure_client.py:12:5:12:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_azure_client.py:13:5:13:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:15:28:15:30 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_azure_client.py:16:28:16:35 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:17:35:17:37 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_azure_client.py:18:35:18:42 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:19:15:19:17 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_azure_client.py:20:15:20:22 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:21:54:21:56 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_azure_client.py:22:54:22:61 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_azure_client.py:24:37:24:39 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_azure_client.py:25:37:25:44 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_http_client.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:19:1:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:5:9:15 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:10:5:10:15 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | @@ -218,36 +336,87 @@ nodes | test_http_client.py:11:5:11:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | | test_http_client.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | -| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | -| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | -| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | -| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | -| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | -| test_http_client.py:31:5:31:8 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | -| test_http_client.py:33:25:33:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | -| test_http_client.py:35:5:35:8 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | -| test_http_client.py:37:25:37:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test_http_client.py:15:25:15:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | +| test_http_client.py:19:27:19:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | +| test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | +| test_http_client.py:28:27:28:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host | +| test_http_client.py:34:25:34:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | +| test_http_client.py:36:5:36:8 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test_http_client.py:39:25:39:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test_http_client.py:41:5:41:8 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test_http_client.py:44:25:44:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_path_validation.py:5:19:5:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:8:5:8:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_path_validation.py:8:18:8:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:9:5:9:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | +| test_path_validation.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:10:5:10:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:11:5:11:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:14:32:14:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:16:32:16:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:19:32:19:39 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:21:32:21:39 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:24:5:24:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_path_validation.py:24:18:24:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:25:5:25:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | +| test_path_validation.py:25:19:25:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:26:5:26:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:27:5:27:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:30:29:30:31 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:32:29:32:31 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:35:29:35:36 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:37:29:37:36 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:40:5:40:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_path_validation.py:40:18:40:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:41:5:41:15 | ControlFlowNode for user_input2 | semmle.label | ControlFlowNode for user_input2 | +| test_path_validation.py:41:19:41:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:42:5:42:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:43:5:43:12 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:46:39:46:41 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:48:39:48:41 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:51:39:51:46 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:53:39:53:46 | ControlFlowNode for full_url | semmle.label | ControlFlowNode for full_url | +| test_path_validation.py:57:5:57:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_path_validation.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_path_validation.py:61:5:61:7 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:64:32:64:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:66:32:66:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:69:32:69:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:71:32:71:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:74:32:74:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:76:32:76:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:79:32:79:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:81:32:81:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:85:32:85:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:87:32:87:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:90:32:90:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:92:32:92:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:95:32:95:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:97:32:97:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:100:32:100:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:102:32:102:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:105:32:105:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:107:32:107:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:110:32:110:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:112:32:112:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:115:32:115:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:117:32:117:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:120:32:120:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:122:32:122:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:125:32:125:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:127:32:127:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:130:32:130:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_path_validation.py:132:32:132:34 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | test_requests.py:1:19:1:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_requests.py:6:5:6:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | -| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:7:5:7:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_requests.py:9:18:9:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:14:5:14:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:14:18:14:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_requests.py:17:17:17:26 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:20:5:20:14 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | +| test_requests.py:20:18:20:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test_requests.py:22:34:22:43 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | subpaths -#select -| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:89:5:89:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:95:5:95:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:95:18:95:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:101:5:101:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:101:18:101:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:107:5:107:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:107:18:107:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:116:5:116:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:116:18:116:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| full_partial_test.py:122:5:122:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:16:9:16:58 | ControlFlowNode for SecretClient() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:16:32:16:34 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:18:9:18:42 | ControlFlowNode for Attribute() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:18:39:18:41 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:20:9:20:34 | ControlFlowNode for KeyClient() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:20:19:20:21 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:22:9:22:84 | ControlFlowNode for Attribute() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:22:58:22:60 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_azure_client.py:25:5:30:5 | ControlFlowNode for download_blob_from_url() | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | test_azure_client.py:26:18:26:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | test_azure_client.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | -| test_http_client.py:22:5:22:31 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| test_http_client.py:26:5:26:31 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.qlref b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.qlref index 88de9285e5e..1161c990e22 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.qlref +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.qlref @@ -1 +1,4 @@ -Security/CWE-918/PartialServerSideRequestForgery.ql +query: Security/CWE-918/PartialServerSideRequestForgery.ql +postprocess: +- utils/test/InlineExpectationsTestQuery.ql +- utils/test/PrettyPrintModels.ql \ No newline at end of file diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/full_partial_test.py b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/full_partial_test.py index 95ff9d64944..7b7d067b611 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/full_partial_test.py +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/full_partial_test.py @@ -1,4 +1,4 @@ -from flask import request +from flask import request # $ Source import requests import re @@ -7,20 +7,24 @@ def full_ssrf(): user_input = request.args['untrusted_input'] query_val = request.args['query_val'] - requests.get(user_input) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(user_input) # $ Alert[py/full-ssrf] url = "https://" + user_input - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] # although the path `/foo` is added here, this can be circumvented such that the # final URL is `https://evil.com/#/foo" -- since the fragment (#) is not sent to the # server. url = "https://" + user_input + "/foo" - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] # this might seem like a dummy test, but it serves to check how our sanitizers work. url = "https://" + user_input + "/foo?key=" + query_val - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] # taint-steps are added as `fromNode -> toNode`, but when adding a sanitizer it's # currently only possible to so on either `fromNode` or `toNode` (either all edges in @@ -39,19 +43,24 @@ def full_ssrf_format(): # using .format url = "https://{}".format(user_input) - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] url = "https://{}/foo".format(user_input) - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] url = "https://{}/foo?key={}".format(user_input, query_val) - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] url = "https://{x}".format(x=user_input) - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] url = "https://{1}".format(0, user_input) - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] def full_ssrf_percent_format(): user_input = request.args['untrusted_input'] @@ -59,13 +68,16 @@ def full_ssrf_percent_format(): # using %-formatting url = "https://%s" % user_input - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] url = "https://%s/foo" % user_input - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] url = "https://%s/foo/key=%s" % (user_input, query_val) - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full and partial control + requests.get(url) # $ Alert[py/partial-ssrf] $ MISSING: Alert[py/full-ssrf] def full_ssrf_f_strings(): user_input = request.args['untrusted_input'] @@ -73,38 +85,45 @@ def full_ssrf_f_strings(): # using f-strings url = f"https://{user_input}" - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] url = f"https://{user_input}/foo" - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] url = f"https://{user_input}/foo?key={query_val}" - requests.get(url) # NOT OK -- user has full control + # NOT OK -- user has full control + requests.get(url) # $ Alert[py/full-ssrf] def partial_ssrf_1(): user_input = request.args['untrusted_input'] url = "https://example.com/foo?" + user_input - requests.get(url) # NOT OK -- user controls query parameters + # NOT OK -- user controls query parameters + requests.get(url) # $ Alert[py/partial-ssrf] def partial_ssrf_2(): user_input = request.args['untrusted_input'] url = "https://example.com/" + user_input - requests.get(url) # NOT OK -- user controls path + # NOT OK -- user controls path + requests.get(url) # $ Alert[py/partial-ssrf] def partial_ssrf_3(): user_input = request.args['untrusted_input'] url = "https://example.com/" + user_input - requests.get(url) # NOT OK -- user controls path + # NOT OK -- user controls path + requests.get(url) # $ Alert[py/partial-ssrf] def partial_ssrf_4(): user_input = request.args['untrusted_input'] url = "https://example.com/foo#{}".format(user_input) - requests.get(url) # NOT OK -- user contollred fragment + # NOT OK -- user controlled fragment + requests.get(url) # $ Alert[py/partial-ssrf] def partial_ssrf_5(): user_input = request.args['untrusted_input'] @@ -113,20 +132,22 @@ def partial_ssrf_5(): # controlled url = "https://example.com/foo#%s" % user_input - requests.get(url) # NOT OK -- user contollred fragment + # NOT OK -- user controlled fragment + requests.get(url) # $ Alert[py/partial-ssrf] def partial_ssrf_6(): user_input = request.args['untrusted_input'] url = f"https://example.com/foo#{user_input}" - requests.get(url) # NOT OK -- user only controlled fragment + # NOT OK -- user only controlled fragment + requests.get(url) # $ Alert[py/partial-ssrf] def partial_ssrf_7(): user_input = request.args['untrusted_input'] if user_input.isalnum(): url = f"https://example.com/foo#{user_input}" - requests.get(url) # OK - user input can only contain alphanumerical characters + requests.get(url) # OK - user input can only contain alphanumerical characters if user_input.isalpha(): url = f"https://example.com/foo#{user_input}" @@ -154,7 +175,8 @@ def partial_ssrf_7(): if re.fullmatch(r'.*[a-zA-Z0-9]+.*', user_input): url = f"https://example.com/foo#{user_input}" - requests.get(url) # NOT OK, but NOT FOUND - user input can contain arbitrary characters + # NOT OK, but NOT FOUND - user input can contain arbitrary characters + requests.get(url) # $ MISSING: Alert[py/partial-ssrf] if re.match(r'^[a-zA-Z0-9]+$', user_input): @@ -163,7 +185,8 @@ def partial_ssrf_7(): if re.match(r'[a-zA-Z0-9]+', user_input): url = f"https://example.com/foo#{user_input}" - requests.get(url) # NOT OK, but NOT FOUND - user input can contain arbitrary character as a suffix. + # NOT OK, but NOT FOUND - user input can contain arbitrary character as a suffix. + requests.get(url) # $ MISSING: Alert[py/partial-ssrf] reg = re.compile(r'^[a-zA-Z0-9]+$') diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py index d8de2092a2e..ac4ff4d365e 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py @@ -3,8 +3,7 @@ from azure.storage.fileshare import ShareFileClient from azure.keyvault.keys import KeyClient from azure.storage.blob import ContainerClient from azure.storage.blob import download_blob_from_url - -from flask import request +from flask import request # $ Source def azure_sdk_test(credential, output_path): user_input = request.args['untrusted_input'] @@ -13,24 +12,14 @@ def azure_sdk_test(credential, output_path): url = f"https://example.com/foo#{user_input}" full_url = f"https://{user_input2}" # Testing Azure sink - c = SecretClient(vault_url=url, credential=credential)# NOT OK -- user only controlled fragment - c = SecretClient(vault_url=full_url, credential=credential) # NOT OK -- user has full control - c = ShareFileClient.from_file_url(url) # NOT OK -- user only controlled fragment - c = ShareFileClient.from_file_url(full_url) # NOT OK -- user has full control - c = KeyClient(url, credential)# NOT OK -- user only controlled fragment - c = KeyClient(full_url, credential) # NOT OK -- user has full control - c = ContainerClient.from_container_url(container_url=url, credential=credential) # NOT OK -- user only controlled fragment - c = ContainerClient.from_container_url(container_url=full_url, credential=credential) # NOT OK -- user has full control + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + SecretClient(vault_url=full_url, credential=credential) # $ Alert[py/full-ssrf] + ShareFileClient.from_file_url(url) # $ Alert[py/partial-ssrf] + ShareFileClient.from_file_url(full_url) # $ Alert[py/full-ssrf] + KeyClient(url, credential) # $ Alert[py/partial-ssrf] + KeyClient(full_url, credential) # $ Alert[py/full-ssrf] + ContainerClient.from_container_url(container_url=url, credential=credential) # $ Alert[py/partial-ssrf] + ContainerClient.from_container_url(container_url=full_url, credential=credential) # $ Alert[py/full-ssrf] - download_blob_from_url( - blob_url=url, # NOT OK -- user only controlled fragment - output=output_path, - credential=credential, - overwrite=True - ) - download_blob_from_url( - blob_url=full_url, # NOT OK -- user has full control - output=output_path, - credential=credential, - overwrite=True - ) + download_blob_from_url(blob_url=url, output=output_path, credential=credential, overwrite=True ) # $ Alert[py/partial-ssrf] + download_blob_from_url(blob_url=full_url, output=output_path, credential=credential, overwrite=True) # $ Alert[py/full-ssrf] diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_http_client.py b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_http_client.py index c833907d843..da812eb6c54 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_http_client.py +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_http_client.py @@ -1,5 +1,5 @@ -from flask import Flask, request - +from flask import request # $ Source +from flask import Flask from http.client import HTTPConnection app = Flask(__name__) @@ -10,28 +10,35 @@ def ssrf_test(): unsafe_path = request.args["path"] user_input = request.args['untrusted_input'] - conn = HTTPConnection(unsafe_host) - conn.request("GET", unsafe_path) # NOT OK -- user has full control + conn = HTTPConnection(unsafe_host) # $ Sink[py/full-ssrf] + # NOT OK -- user has full control + conn.request("GET", unsafe_path) # $ Alert[py/full-ssrf] - # Full SSRF variant, where there is ALSO made a request with fixed URL on the same + # Full SSRF variant, where there is also a request with fixed URL on the same # connection later on. This should not change anything on the overall SSRF alerts. - conn = HTTPConnection(unsafe_host) - conn.request("GET", unsafe_path) # NOT OK -- user has full control + conn = HTTPConnection(unsafe_host) # $ Sink + # NOT OK -- user has full control + conn.request("GET", unsafe_path) # $ Alert[py/full-ssrf] # partial SSRF on SAME connection - conn.request("GET", "/foo") # NOT OK -- user has control of host + # NOT OK -- user has control of host + conn.request("GET", "/foo") # $ Alert[py/partial-ssrf] # the rest are partial SSRF - conn = HTTPConnection(unsafe_host) - conn.request("GET", "/foo") # NOT OK -- user controlled domain + conn = HTTPConnection(unsafe_host) # $ Sink[py/partial-ssrf] + # NOT OK -- user controlled domain + conn.request("GET", "/foo") # $ Alert[py/partial-ssrf] conn = HTTPConnection("example.com") - conn.request("GET", unsafe_path) # NOT OK -- user controlled path + # NOT OK -- user controlled path + conn.request("GET", unsafe_path) # $ Alert[py/partial-ssrf] path = "foo?" + user_input conn = HTTPConnection("example.com") - conn.request("GET", path) # NOT OK -- user controlled query parameters + # NOT OK -- user controlled query parameters + conn.request("GET", path) # $ Alert[py/partial-ssrf] path = "foo#" + user_input conn = HTTPConnection("example.com") - conn.request("GET", path) # NOT OK -- user controlled fragment + # NOT OK -- user controlled fragment + conn.request("GET", path) # $ Alert[py/partial-ssrf] \ No newline at end of file diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py new file mode 100644 index 00000000000..ce5a6d33833 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py @@ -0,0 +1,132 @@ +from azure.keyvault.secrets import SecretClient +from azure.storage.fileshare import ShareFileClient +from azure.keyvault.keys import KeyClient +from AntiSSRF import URIValidator +from flask import request # $ Source + +def urivalidator_path_in_domain_validation(credential, trusted_domain): + user_input = request.args['untrusted_input'] + user_input2 = request.args['untrusted_input2'] + url = f"https://example.com/foo#{user_input}" + full_url = f"https://{user_input2}" + + if URIValidator.in_domain(url, trusted_domain): + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + if URIValidator.in_domain(full_url, trusted_domain): + SecretClient(vault_url=full_url, credential=credential) # $ Alert[py/partial-ssrf] + else: + SecretClient(vault_url=full_url, credential=credential) # $ Alert[py/full-ssrf] + +def urivalidator_path_in_azure_keyvault_domain_validation(credential): + user_input = request.args['untrusted_input'] + user_input2 = request.args['untrusted_input2'] + url = f"https://example.com/foo#{user_input}" + full_url = f"https://{user_input2}" + + if URIValidator.in_azure_keyvault_domain(url): + KeyClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + else: + KeyClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + if URIValidator.in_azure_keyvault_domain(full_url): + KeyClient(vault_url=full_url, credential=credential) # $ Alert[py/partial-ssrf] + else: + KeyClient(vault_url=full_url, credential=credential) # $ Alert[py/full-ssrf] + +def urivalidator_path_in_azure_storage_domain_validation(credential): + user_input = request.args['untrusted_input'] + user_input2 = request.args['untrusted_input2'] + url = f"https://example.com/foo#{user_input}" + full_url = f"https://{user_input2}" + + if URIValidator.in_azure_storage_domain(url): + ShareFileClient.from_file_url(url) # $ Alert[py/partial-ssrf] + else: + ShareFileClient.from_file_url(url) # $ Alert[py/partial-ssrf] + + if URIValidator.in_azure_storage_domain(full_url): + ShareFileClient.from_file_url(full_url) # $ Alert[py/partial-ssrf] + else: + ShareFileClient.from_file_url(full_url) # $ Alert[py/full-ssrf] + + +def complex_urivalidator_checks(credential, trusted_domain): + user_input = request.args['untrusted_input'] + # Focus on in_domain only here for simplicity + # It is assumed that the logic underlying path checking would apply + # similarly to other validator methods. + url = f"https://{user_input}" + + if not URIValidator.in_domain(url, trusted_domain): + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + if URIValidator.in_domain(url, trusted_domain) and trusted_domain == "example.com": + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + + if not (URIValidator.in_domain(url, trusted_domain) and trusted_domain == "example.com"): + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + if not not not URIValidator.in_domain(url, trusted_domain): + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + + if URIValidator.in_domain(url, trusted_domain) == True: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + + if URIValidator.in_domain(url, trusted_domain) == False: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + if URIValidator.in_domain(url, trusted_domain) != True: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + if URIValidator.in_domain(url, trusted_domain) != False: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + + if URIValidator.in_domain(url, trusted_domain) is True: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + + if URIValidator.in_domain(url, trusted_domain) is False: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + if URIValidator.in_domain(url, trusted_domain) is not True: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + if URIValidator.in_domain(url, trusted_domain) is not False: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + + if not URIValidator.in_domain(url, trusted_domain) is True: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + + if not URIValidator.in_domain(url, trusted_domain) is False: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf] + else: + SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf] \ No newline at end of file diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py index 443f5c3b81f..6489096c969 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py @@ -1,11 +1,51 @@ -from flask import request +from flask import request # $ Source[py/full-ssrf] +from AntiSSRF import AntiSSRFPolicy import requests -def ssrf_test(): +def ssrf_test1(): user_input = request.args['untrusted_input'] - - requests.get(user_input) # NOT OK -- user has full control - + # NOT OK -- user has full control + requests.get(user_input) # $ Alert[py/full-ssrf] # since `requests`` always uses complete URLs, it's not interesting to test more of # the framework directly. See `full_partial_test.py` for different ways to do SSRF. + +def ssrf_test2(): + user_input = request.args['untrusted_input'] + # NOT OK -- user has full control + session = requests.Session() + session.get(user_input) # $ Alert[py/full-ssrf] + +def ssrf_test3(): + user_input = request.args['untrusted_input'] + # NOT OK -- user has full control + requests.request('', user_input) # $ Alert[py/full-ssrf] + +def ssrf_test_with_policy1(): + user_input = request.args['untrusted_input'] + policy = AntiSSRFPolicy() + session = policy.get_antissrf_session() + # OK -- dangerous user input is filtered by AntiSSRFPolicy + session.get(user_input) + +def ssrf_test_with_policy2(): + user_input = request.args['untrusted_input'] + policy = AntiSSRFPolicy() + session = policy.get_antissrf_session() + # overwriting the HTTPAdapter to default requests adapter + # this makes the session unsafe again + session.mount("http://", requests.adapters.HTTPAdapter()) + # NOT OK -- dangerous user input is no longer filtered by AntiSSRFPolicy + # TODO: not currently a scenario we detect. + session.get(user_input) # $ MISSING: Alert[py/full-ssrf] + +def ssrf_test_with_policy3(adapter): + user_input = request.args['untrusted_input'] + policy = AntiSSRFPolicy() + session = policy.get_antissrf_session() + # overwriting the HTTPAdapter to a custom requests adapter + # this could make the session unsafe again + session.mount("http://", adapter) + # NOT OK -- dangerous user input is no longer filtered by AntiSSRFPolicy + # TODO: not currently a scenario we detect. + session.get(user_input) # $ MISSING: Alert[py/full-ssrf] \ No newline at end of file diff --git a/ruby/ql/lib/CHANGELOG.md b/ruby/ql/lib/CHANGELOG.md index 408f2f3144f..063e5f16211 100644 --- a/ruby/ql/lib/CHANGELOG.md +++ b/ruby/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.1.10 + +No user-facing changes. + ## 5.1.9 ### Minor Analysis Improvements diff --git a/ruby/ql/lib/change-notes/released/5.1.10.md b/ruby/ql/lib/change-notes/released/5.1.10.md new file mode 100644 index 00000000000..f22ccf3e6e9 --- /dev/null +++ b/ruby/ql/lib/change-notes/released/5.1.10.md @@ -0,0 +1,3 @@ +## 5.1.10 + +No user-facing changes. diff --git a/ruby/ql/lib/codeql-pack.release.yml b/ruby/ql/lib/codeql-pack.release.yml index f9bf2605261..9198af0dd6c 100644 --- a/ruby/ql/lib/codeql-pack.release.yml +++ b/ruby/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 5.1.9 +lastReleaseVersion: 5.1.10 diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index 824d21e1331..1d14ca0e3d2 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-all -version: 5.1.10-dev +version: 5.1.11-dev groups: ruby extractor: ruby dbscheme: ruby.dbscheme diff --git a/ruby/ql/src/CHANGELOG.md b/ruby/ql/src/CHANGELOG.md index fd5b24f166e..247072967e7 100644 --- a/ruby/ql/src/CHANGELOG.md +++ b/ruby/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.5.7 + +No user-facing changes. + ## 1.5.6 No user-facing changes. diff --git a/ruby/ql/src/change-notes/released/1.5.7.md b/ruby/ql/src/change-notes/released/1.5.7.md new file mode 100644 index 00000000000..c60c55034a6 --- /dev/null +++ b/ruby/ql/src/change-notes/released/1.5.7.md @@ -0,0 +1,3 @@ +## 1.5.7 + +No user-facing changes. diff --git a/ruby/ql/src/codeql-pack.release.yml b/ruby/ql/src/codeql-pack.release.yml index 9a0b3c9461b..227ac5febef 100644 --- a/ruby/ql/src/codeql-pack.release.yml +++ b/ruby/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.5.6 +lastReleaseVersion: 1.5.7 diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml index 63d59fd0faa..b027389bc63 100644 --- a/ruby/ql/src/qlpack.yml +++ b/ruby/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-queries -version: 1.5.7-dev +version: 1.5.8-dev groups: - ruby - queries diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected index 6263cb8919b..0bece506bfb 100644 --- a/ruby/ql/test/library-tests/ast/Ast.expected +++ b/ruby/ql/test/library-tests/ast/Ast.expected @@ -1458,6 +1458,50 @@ control/conditionals.rb: # 67| getBranch/getThen: [StmtSequence] then ... # 68| getBranch/getElse: [StmtSequence] else ... # 69| getStmt: [LocalVariableAccess] c +# 73| getStmt: [IfExpr] if ... +# 73| getCondition: [LogicalAndExpr] ... && ... +# 73| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a +# 73| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] b +# 73| getBranch/getThen: [StmtSequence] then ... +# 74| getStmt: [LocalVariableAccess] c +# 78| getStmt: [IfExpr] if ... +# 78| getCondition: [LogicalAndExpr] ... && ... +# 78| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a +# 79| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] b +# 79| getBranch/getThen: [StmtSequence] then ... +# 81| getStmt: [LocalVariableAccess] c +# 86| getStmt: [IfExpr] if ... +# 86| getCondition: [LocalVariableAccess] a +# 86| getBranch/getThen: [StmtSequence] then ... +# 87| getStmt: [MethodCall] call to and +# 87| getReceiver: [SelfVariableAccess] self +# 87| getArgument: [LocalVariableAccess] b +# 88| getStmt: [MethodCall] call to then +# 88| getReceiver: [SelfVariableAccess] self +# 89| getStmt: [LocalVariableAccess] c +# 102| getStmt: [IfExpr] if ... +# 102| getCondition: [LocalVariableAccess] a +# 102| getBranch/getThen: [StmtSequence] then ... +# 103| getStmt: [MethodCall] call to or +# 103| getReceiver: [SelfVariableAccess] self +# 103| getArgument: [LocalVariableAccess] b +# 104| getStmt: [MethodCall] call to then +# 104| getReceiver: [SelfVariableAccess] self +# 105| getStmt: [LocalVariableAccess] c +# 109| getStmt: [IfExpr] if ... +# 109| getCondition: [LogicalAndExpr] ... && ... +# 109| getAnOperand/getLeftOperand/getReceiver: [LogicalAndExpr] ... && ... +# 109| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a +# 110| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] b +# 111| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] c +# 111| getBranch/getThen: [StmtSequence] then ... +# 113| getStmt: [LocalVariableAccess] d +# 144| getStmt: [IfExpr] if ... +# 144| getCondition: [LogicalAndExpr] ... && ... +# 144| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a +# 145| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] b +# 145| getBranch/getThen: [StmtSequence] then ... +# 147| getStmt: [LocalVariableAccess] c constants/constants.rb: # 1| [Toplevel] constants.rb # 1| getStmt: [ModuleDeclaration] ModuleA @@ -2845,63 +2889,77 @@ operations/operations.rb: # 85| getStmt: [AssignBitwiseXorExpr] ... ^= ... # 85| getAnOperand/getLeftOperand: [LocalVariableAccess] baz # 85| getAnOperand/getRightOperand: [LocalVariableAccess] qux -# 87| getStmt: [ClassDeclaration] X -# 88| getStmt: [AssignExpr] ... = ... -# 88| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x -# 88| getReceiver: [SelfVariableAccess] self -# 88| getAnOperand/getRightOperand: [IntegerLiteral] 1 -# 89| getStmt: [AssignAddExpr] ... += ... -# 89| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x -# 89| getReceiver: [SelfVariableAccess] self -# 89| getAnOperand/getRightOperand: [IntegerLiteral] 2 -# 91| getStmt: [AssignExpr] ... = ... -# 91| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y -# 91| getAnOperand/getRightOperand: [IntegerLiteral] 3 -# 92| getStmt: [AssignDivExpr] ... /= ... -# 92| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y -# 92| getAnOperand/getRightOperand: [IntegerLiteral] 4 -# 95| getStmt: [AssignExpr] ... = ... -# 95| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var -# 95| getAnOperand/getRightOperand: [IntegerLiteral] 5 -# 96| getStmt: [AssignMulExpr] ... *= ... -# 96| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var -# 96| getAnOperand/getRightOperand: [IntegerLiteral] 6 -# 98| getStmt: [AssignExpr] ... = ... -# 98| getAnOperand/getLeftOperand: [ConstantAssignment] CONSTANT1 -# 98| getAnOperand/getRightOperand: [IntegerLiteral] 5 -# 99| getStmt: [AssignAddExpr] ... += ... -# 99| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT2 -# 99| getAnOperand/getRightOperand: [IntegerLiteral] 6 -# 100| getStmt: [AssignLogicalOrExpr] ... ||= ... -# 100| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT3 -# 100| getAnOperand/getRightOperand: [IntegerLiteral] 7 -# 101| getStmt: [AssignLogicalOrExpr] ... ||= ... -# 101| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] MemberConstant -# 101| getScopeExpr: [ConstantReadAccess] Foo -# 101| getAnOperand/getRightOperand: [IntegerLiteral] 8 -# 102| getStmt: [AssignLogicalOrExpr] ... ||= ... -# 102| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] OtherConstant -# 102| getScopeExpr: [MethodCall] call to bar -# 102| getReceiver: [MethodCall] call to foo -# 102| getReceiver: [SelfVariableAccess] self -# 102| getArgument: [IntegerLiteral] 1 -# 102| getAnOperand/getRightOperand: [IntegerLiteral] 7 -# 103| getStmt: [AssignLogicalOrExpr] ... ||= ... -# 103| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT4 -# 103| getAnOperand/getRightOperand: [IntegerLiteral] 7 -# 104| getStmt: [AssignExpr] ... = ... -# 104| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) -# 104| getElement: [ConstantAssignment] FOO -# 104| getElement: [ConstantAssignment] BAR -# 104| getElement: [ConstantAssignment] FOO -# 104| getScopeExpr: [LocalVariableAccess] foo -# 104| getAnOperand/getRightOperand: [ArrayLiteral] [...] -# 104| getElement: [IntegerLiteral] 1 -# 104| getElement: [IntegerLiteral] 2 -# 104| getElement: [IntegerLiteral] 3 -# 106| getStmt: [DivExpr] ... / ... -# 106| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] foo -# 107| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 5 +# 88| getStmt: [AssignExpr] ... = ... +# 88| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 88| getAnOperand/getRightOperand: [LogicalAndExpr] ... && ... +# 88| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a +# 89| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] b +# 95| getStmt: [Method] foo +# 95| getParameter: [SimpleParameter] a +# 95| getDefiningAccess: [LocalVariableAccess] a +# 95| getParameter: [SimpleParameter] b +# 95| getDefiningAccess: [LocalVariableAccess] b +# 96| getStmt: [ReturnStmt] return +# 96| getValue: [LogicalAndExpr] ... && ... +# 96| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a +# 97| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] b +# 107| getStmt: [ClassDeclaration] X +# 108| getStmt: [AssignExpr] ... = ... +# 108| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x +# 108| getReceiver: [SelfVariableAccess] self +# 108| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 109| getStmt: [AssignAddExpr] ... += ... +# 109| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x +# 109| getReceiver: [SelfVariableAccess] self +# 109| getAnOperand/getRightOperand: [IntegerLiteral] 2 +# 111| getStmt: [AssignExpr] ... = ... +# 111| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y +# 111| getAnOperand/getRightOperand: [IntegerLiteral] 3 +# 112| getStmt: [AssignDivExpr] ... /= ... +# 112| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y +# 112| getAnOperand/getRightOperand: [IntegerLiteral] 4 +# 115| getStmt: [AssignExpr] ... = ... +# 115| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var +# 115| getAnOperand/getRightOperand: [IntegerLiteral] 5 +# 116| getStmt: [AssignMulExpr] ... *= ... +# 116| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var +# 116| getAnOperand/getRightOperand: [IntegerLiteral] 6 +# 118| getStmt: [AssignExpr] ... = ... +# 118| getAnOperand/getLeftOperand: [ConstantAssignment] CONSTANT1 +# 118| getAnOperand/getRightOperand: [IntegerLiteral] 5 +# 119| getStmt: [AssignAddExpr] ... += ... +# 119| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT2 +# 119| getAnOperand/getRightOperand: [IntegerLiteral] 6 +# 120| getStmt: [AssignLogicalOrExpr] ... ||= ... +# 120| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT3 +# 120| getAnOperand/getRightOperand: [IntegerLiteral] 7 +# 121| getStmt: [AssignLogicalOrExpr] ... ||= ... +# 121| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] MemberConstant +# 121| getScopeExpr: [ConstantReadAccess] Foo +# 121| getAnOperand/getRightOperand: [IntegerLiteral] 8 +# 122| getStmt: [AssignLogicalOrExpr] ... ||= ... +# 122| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] OtherConstant +# 122| getScopeExpr: [MethodCall] call to bar +# 122| getReceiver: [MethodCall] call to foo +# 122| getReceiver: [SelfVariableAccess] self +# 122| getArgument: [IntegerLiteral] 1 +# 122| getAnOperand/getRightOperand: [IntegerLiteral] 7 +# 123| getStmt: [AssignLogicalOrExpr] ... ||= ... +# 123| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT4 +# 123| getAnOperand/getRightOperand: [IntegerLiteral] 7 +# 124| getStmt: [AssignExpr] ... = ... +# 124| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) +# 124| getElement: [ConstantAssignment] FOO +# 124| getElement: [ConstantAssignment] BAR +# 124| getElement: [ConstantAssignment] FOO +# 124| getScopeExpr: [LocalVariableAccess] foo +# 124| getAnOperand/getRightOperand: [ArrayLiteral] [...] +# 124| getElement: [IntegerLiteral] 1 +# 124| getElement: [IntegerLiteral] 2 +# 124| getElement: [IntegerLiteral] 3 +# 126| getStmt: [DivExpr] ... / ... +# 126| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] foo +# 127| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 5 params/params.rb: # 1| [Toplevel] params.rb # 4| getStmt: [Method] identifier_method_params diff --git a/ruby/ql/test/library-tests/ast/AstDesugar.expected b/ruby/ql/test/library-tests/ast/AstDesugar.expected index 0a1f43b03d5..29443860749 100644 --- a/ruby/ql/test/library-tests/ast/AstDesugar.expected +++ b/ruby/ql/test/library-tests/ast/AstDesugar.expected @@ -965,101 +965,101 @@ operations/operations.rb: # 85| getAnOperand/getRightOperand: [BitwiseXorExpr] ... ^ ... # 85| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] baz # 85| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] qux -# 89| [AssignAddExpr] ... += ... -# 89| getDesugared: [AssignExpr] ... = ... -# 89| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x -# 89| getReceiver: [SelfVariableAccess] self -# 89| getAnOperand/getRightOperand: [AddExpr] ... + ... -# 89| getAnOperand/getLeftOperand/getReceiver: [InstanceVariableAccess] @x -# 89| getReceiver: [SelfVariableAccess] self -# 89| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2 -# 92| [AssignDivExpr] ... /= ... -# 92| getDesugared: [AssignExpr] ... = ... -# 92| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y -# 92| getAnOperand/getRightOperand: [DivExpr] ... / ... -# 92| getAnOperand/getLeftOperand/getReceiver: [ClassVariableAccess] @@y -# 92| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4 -# 96| [AssignMulExpr] ... *= ... -# 96| getDesugared: [AssignExpr] ... = ... -# 96| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var -# 96| getAnOperand/getRightOperand: [MulExpr] ... * ... -# 96| getAnOperand/getLeftOperand/getReceiver: [GlobalVariableAccess] $global_var -# 96| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 6 -# 99| [AssignAddExpr] ... += ... -# 99| getDesugared: [AssignExpr] ... = ... -# 99| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT2 -# 99| getAnOperand/getRightOperand: [AddExpr] ... + ... -# 99| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT2 -# 99| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 6 -# 100| [AssignLogicalOrExpr] ... ||= ... -# 100| getDesugared: [AssignExpr] ... = ... -# 100| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT3 -# 100| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... -# 100| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT3 -# 100| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7 -# 101| [AssignLogicalOrExpr] ... ||= ... -# 101| getDesugared: [StmtSequence] ... -# 101| getStmt: [AssignExpr] ... = ... -# 101| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 -# 101| getAnOperand/getRightOperand: [ConstantReadAccess] Foo -# 101| getStmt: [AssignExpr] ... = ... -# 101| getAnOperand/getLeftOperand: [ConstantAssignment] MemberConstant -# 101| getScopeExpr: [LocalVariableAccess] __synth__0 -# 101| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... -# 101| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] MemberConstant -# 101| getScopeExpr: [LocalVariableAccess] __synth__0 -# 101| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 8 -# 102| [AssignLogicalOrExpr] ... ||= ... -# 102| getDesugared: [StmtSequence] ... -# 102| getStmt: [AssignExpr] ... = ... -# 102| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 -# 102| getAnOperand/getRightOperand: [MethodCall] call to bar -# 102| getReceiver: [MethodCall] call to foo -# 102| getReceiver: [SelfVariableAccess] self -# 102| getArgument: [IntegerLiteral] 1 -# 102| getStmt: [AssignExpr] ... = ... -# 102| getAnOperand/getLeftOperand: [ConstantAssignment] OtherConstant -# 102| getScopeExpr: [LocalVariableAccess] __synth__0 -# 102| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... -# 102| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] OtherConstant -# 102| getScopeExpr: [LocalVariableAccess] __synth__0 -# 102| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7 -# 103| [AssignLogicalOrExpr] ... ||= ... -# 103| getDesugared: [AssignExpr] ... = ... -# 103| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT4 -# 103| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... -# 103| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT4 -# 103| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7 -# 104| [AssignExpr] ... = ... -# 104| getDesugared: [StmtSequence] ... -# 104| getStmt: [AssignExpr] ... = ... -# 104| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2 -# 104| getAnOperand/getRightOperand: [LocalVariableAccess] foo -# 104| getStmt: [AssignExpr] ... = ... -# 104| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__3 -# 104| getAnOperand/getRightOperand: [SplatExpr] * ... -# 104| getAnOperand/getOperand/getReceiver: [ArrayLiteral] [...] -# 104| getDesugared: [MethodCall] call to [] -# 104| getReceiver: [ConstantReadAccess] Array -# 104| getArgument: [IntegerLiteral] 1 -# 104| getArgument: [IntegerLiteral] 2 -# 104| getArgument: [IntegerLiteral] 3 -# 104| getStmt: [AssignExpr] ... = ... -# 104| getAnOperand/getLeftOperand: [ConstantAssignment] FOO -# 104| getAnOperand/getRightOperand: [MethodCall] call to [] -# 104| getReceiver: [LocalVariableAccess] __synth__3 -# 104| getArgument: [IntegerLiteral] 0 -# 104| getStmt: [AssignExpr] ... = ... -# 104| getAnOperand/getLeftOperand: [ConstantAssignment] BAR -# 104| getAnOperand/getRightOperand: [MethodCall] call to [] -# 104| getReceiver: [LocalVariableAccess] __synth__3 -# 104| getArgument: [IntegerLiteral] 1 -# 104| getStmt: [AssignExpr] ... = ... -# 104| getAnOperand/getLeftOperand: [ConstantAssignment] FOO -# 104| getScopeExpr: [LocalVariableAccess] __synth__2 -# 104| getAnOperand/getRightOperand: [MethodCall] call to [] -# 104| getReceiver: [LocalVariableAccess] __synth__3 -# 104| getArgument: [IntegerLiteral] 2 +# 109| [AssignAddExpr] ... += ... +# 109| getDesugared: [AssignExpr] ... = ... +# 109| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x +# 109| getReceiver: [SelfVariableAccess] self +# 109| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 109| getAnOperand/getLeftOperand/getReceiver: [InstanceVariableAccess] @x +# 109| getReceiver: [SelfVariableAccess] self +# 109| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2 +# 112| [AssignDivExpr] ... /= ... +# 112| getDesugared: [AssignExpr] ... = ... +# 112| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y +# 112| getAnOperand/getRightOperand: [DivExpr] ... / ... +# 112| getAnOperand/getLeftOperand/getReceiver: [ClassVariableAccess] @@y +# 112| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4 +# 116| [AssignMulExpr] ... *= ... +# 116| getDesugared: [AssignExpr] ... = ... +# 116| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var +# 116| getAnOperand/getRightOperand: [MulExpr] ... * ... +# 116| getAnOperand/getLeftOperand/getReceiver: [GlobalVariableAccess] $global_var +# 116| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 6 +# 119| [AssignAddExpr] ... += ... +# 119| getDesugared: [AssignExpr] ... = ... +# 119| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT2 +# 119| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 119| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT2 +# 119| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 6 +# 120| [AssignLogicalOrExpr] ... ||= ... +# 120| getDesugared: [AssignExpr] ... = ... +# 120| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT3 +# 120| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... +# 120| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT3 +# 120| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7 +# 121| [AssignLogicalOrExpr] ... ||= ... +# 121| getDesugared: [StmtSequence] ... +# 121| getStmt: [AssignExpr] ... = ... +# 121| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 +# 121| getAnOperand/getRightOperand: [ConstantReadAccess] Foo +# 121| getStmt: [AssignExpr] ... = ... +# 121| getAnOperand/getLeftOperand: [ConstantAssignment] MemberConstant +# 121| getScopeExpr: [LocalVariableAccess] __synth__0 +# 121| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... +# 121| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] MemberConstant +# 121| getScopeExpr: [LocalVariableAccess] __synth__0 +# 121| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 8 +# 122| [AssignLogicalOrExpr] ... ||= ... +# 122| getDesugared: [StmtSequence] ... +# 122| getStmt: [AssignExpr] ... = ... +# 122| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 +# 122| getAnOperand/getRightOperand: [MethodCall] call to bar +# 122| getReceiver: [MethodCall] call to foo +# 122| getReceiver: [SelfVariableAccess] self +# 122| getArgument: [IntegerLiteral] 1 +# 122| getStmt: [AssignExpr] ... = ... +# 122| getAnOperand/getLeftOperand: [ConstantAssignment] OtherConstant +# 122| getScopeExpr: [LocalVariableAccess] __synth__0 +# 122| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... +# 122| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] OtherConstant +# 122| getScopeExpr: [LocalVariableAccess] __synth__0 +# 122| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7 +# 123| [AssignLogicalOrExpr] ... ||= ... +# 123| getDesugared: [AssignExpr] ... = ... +# 123| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT4 +# 123| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... +# 123| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT4 +# 123| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7 +# 124| [AssignExpr] ... = ... +# 124| getDesugared: [StmtSequence] ... +# 124| getStmt: [AssignExpr] ... = ... +# 124| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2 +# 124| getAnOperand/getRightOperand: [LocalVariableAccess] foo +# 124| getStmt: [AssignExpr] ... = ... +# 124| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__3 +# 124| getAnOperand/getRightOperand: [SplatExpr] * ... +# 124| getAnOperand/getOperand/getReceiver: [ArrayLiteral] [...] +# 124| getDesugared: [MethodCall] call to [] +# 124| getReceiver: [ConstantReadAccess] Array +# 124| getArgument: [IntegerLiteral] 1 +# 124| getArgument: [IntegerLiteral] 2 +# 124| getArgument: [IntegerLiteral] 3 +# 124| getStmt: [AssignExpr] ... = ... +# 124| getAnOperand/getLeftOperand: [ConstantAssignment] FOO +# 124| getAnOperand/getRightOperand: [MethodCall] call to [] +# 124| getReceiver: [LocalVariableAccess] __synth__3 +# 124| getArgument: [IntegerLiteral] 0 +# 124| getStmt: [AssignExpr] ... = ... +# 124| getAnOperand/getLeftOperand: [ConstantAssignment] BAR +# 124| getAnOperand/getRightOperand: [MethodCall] call to [] +# 124| getReceiver: [LocalVariableAccess] __synth__3 +# 124| getArgument: [IntegerLiteral] 1 +# 124| getStmt: [AssignExpr] ... = ... +# 124| getAnOperand/getLeftOperand: [ConstantAssignment] FOO +# 124| getScopeExpr: [LocalVariableAccess] __synth__2 +# 124| getAnOperand/getRightOperand: [MethodCall] call to [] +# 124| getReceiver: [LocalVariableAccess] __synth__3 +# 124| getArgument: [IntegerLiteral] 2 params/params.rb: # 8| [HashLiteral] {...} # 8| getDesugared: [MethodCall] call to [] diff --git a/ruby/ql/test/library-tests/ast/TreeSitter.expected b/ruby/ql/test/library-tests/ast/TreeSitter.expected index 04a66cce847..ab7937969d1 100644 --- a/ruby/ql/test/library-tests/ast/TreeSitter.expected +++ b/ruby/ql/test/library-tests/ast/TreeSitter.expected @@ -2962,6 +2962,71 @@ control/conditionals.rb: # 68| 0: [ReservedWord] else # 69| 1: [Identifier] c # 70| 4: [ReservedWord] end +# 73| 17: [If] If +# 73| 0: [ReservedWord] if +# 73| 1: [Binary] Binary +# 73| 0: [Identifier] a +# 73| 1: [ReservedWord] && +# 73| 2: [Identifier] b +# 73| 2: [Then] Then +# 73| 0: [ReservedWord] then +# 74| 1: [Identifier] c +# 75| 3: [ReservedWord] end +# 78| 18: [If] If +# 78| 0: [ReservedWord] if +# 78| 1: [Binary] Binary +# 78| 0: [Identifier] a +# 79| 1: [ReservedWord] && +# 79| 2: [Identifier] b +# 79| 2: [Then] Then +# 80| 0: [ReservedWord] then +# 81| 1: [Identifier] c +# 82| 3: [ReservedWord] end +# 86| 19: [If] If +# 86| 0: [ReservedWord] if +# 86| 1: [Identifier] a +# 86| 2: [Then] Then +# 87| 0: [Call] Call +# 87| 0: [Identifier] and +# 87| 1: [ArgumentList] ArgumentList +# 87| 0: [Identifier] b +# 88| 1: [Identifier] then +# 89| 2: [Identifier] c +# 90| 3: [ReservedWord] end +# 102| 20: [If] If +# 102| 0: [ReservedWord] if +# 102| 1: [Identifier] a +# 102| 2: [Then] Then +# 103| 0: [Call] Call +# 103| 0: [Identifier] or +# 103| 1: [ArgumentList] ArgumentList +# 103| 0: [Identifier] b +# 104| 1: [Identifier] then +# 105| 2: [Identifier] c +# 106| 3: [ReservedWord] end +# 109| 21: [If] If +# 109| 0: [ReservedWord] if +# 109| 1: [Binary] Binary +# 109| 0: [Binary] Binary +# 109| 0: [Identifier] a +# 110| 1: [ReservedWord] && +# 110| 2: [Identifier] b +# 111| 1: [ReservedWord] && +# 111| 2: [Identifier] c +# 111| 2: [Then] Then +# 112| 0: [ReservedWord] then +# 113| 1: [Identifier] d +# 114| 3: [ReservedWord] end +# 144| 22: [If] If +# 144| 0: [ReservedWord] if +# 144| 1: [Binary] Binary +# 144| 0: [Identifier] a +# 144| 1: [ReservedWord] && +# 145| 2: [Identifier] b +# 145| 2: [Then] Then +# 146| 0: [ReservedWord] then +# 147| 1: [Identifier] c +# 148| 3: [ReservedWord] end # 1| [Comment] # Define some variables used below # 9| [Comment] # If expr with no else # 14| [Comment] # If expr with single else @@ -2974,6 +3039,45 @@ control/conditionals.rb: # 57| [Comment] # Ternary if expr # 60| [Comment] # If expr with empty else (treated as no else) # 66| [Comment] # If expr with empty then (treated as no then) +# 72| [Comment] # If expr with `&&` on same line as condition and then +# 77| [Comment] # If expr with `&&` at the start of a separate line before then +# 84| [Comment] # If expr with `and` at the start of a separate line before then +# 85| [Comment] # NOTE: This is not parsed correctly, `and b` is parsed as a call +# 92| [Comment] # If expr with `||` at the start of a separate line before then +# 93| [Comment] # NOTE: This is not parsed correctly due to the leading `||` +# 94| [Comment] # if a +# 95| [Comment] # || b +# 96| [Comment] # then +# 97| [Comment] # c +# 98| [Comment] # end +# 100| [Comment] # If expr with `or` at the start of a separate line before then +# 101| [Comment] # NOTE: This is not parsed correctly, `or b` is parsed as a call +# 108| [Comment] # If expr with repeated && at the start of a separate line before then +# 116| [Comment] # If expr with alternating && and || at the start of lines +# 117| [Comment] # NOTE: This is not parsed correctly due to the leading `||` +# 118| [Comment] # if a +# 119| [Comment] # && b +# 120| [Comment] # || c +# 121| [Comment] # then +# 122| [Comment] # d +# 123| [Comment] # end +# 125| [Comment] # If expr with operator at start of line and parentheses +# 126| [Comment] # NOTE: This is not parsed correctly due to the leading `||` +# 127| [Comment] # if a +# 128| [Comment] # && (b +# 129| [Comment] # || c) +# 130| [Comment] # then +# 131| [Comment] # d +# 132| [Comment] # end +# 134| [Comment] # If expr with operator at start of line and parentheses +# 135| [Comment] # NOTE: This is not parsed correctly due to the leading `||` +# 136| [Comment] # if a +# 137| [Comment] # || (b +# 138| [Comment] # && c) +# 139| [Comment] # then +# 140| [Comment] # d +# 141| [Comment] # end +# 143| [Comment] # If expr with && at end of line control/loops.rb: # 1| [Program] Program # 2| 0: [Assignment] Assignment @@ -5564,100 +5668,125 @@ operations/operations.rb: # 85| 0: [Identifier] baz # 85| 1: [ReservedWord] ^= # 85| 2: [Identifier] qux -# 87| 63: [Class] Class -# 87| 0: [ReservedWord] class -# 87| 1: [Constant] X -# 88| 2: [BodyStatement] BodyStatement -# 88| 0: [Assignment] Assignment -# 88| 0: [InstanceVariable] @x -# 88| 1: [ReservedWord] = -# 88| 2: [Integer] 1 -# 89| 1: [OperatorAssignment] OperatorAssignment -# 89| 0: [InstanceVariable] @x -# 89| 1: [ReservedWord] += -# 89| 2: [Integer] 2 -# 91| 2: [Assignment] Assignment -# 91| 0: [ClassVariable] @@y -# 91| 1: [ReservedWord] = -# 91| 2: [Integer] 3 -# 92| 3: [OperatorAssignment] OperatorAssignment -# 92| 0: [ClassVariable] @@y -# 92| 1: [ReservedWord] /= -# 92| 2: [Integer] 4 -# 93| 3: [ReservedWord] end -# 95| 64: [Assignment] Assignment -# 95| 0: [GlobalVariable] $global_var -# 95| 1: [ReservedWord] = -# 95| 2: [Integer] 5 -# 96| 65: [OperatorAssignment] OperatorAssignment -# 96| 0: [GlobalVariable] $global_var -# 96| 1: [ReservedWord] *= -# 96| 2: [Integer] 6 -# 98| 66: [Assignment] Assignment -# 98| 0: [Constant] CONSTANT1 -# 98| 1: [ReservedWord] = -# 98| 2: [Integer] 5 -# 99| 67: [OperatorAssignment] OperatorAssignment -# 99| 0: [Constant] CONSTANT2 -# 99| 1: [ReservedWord] += -# 99| 2: [Integer] 6 -# 100| 68: [OperatorAssignment] OperatorAssignment -# 100| 0: [Constant] CONSTANT3 -# 100| 1: [ReservedWord] ||= -# 100| 2: [Integer] 7 -# 101| 69: [OperatorAssignment] OperatorAssignment -# 101| 0: [ScopeResolution] ScopeResolution -# 101| 0: [Constant] Foo -# 101| 1: [ReservedWord] :: -# 101| 2: [Constant] MemberConstant -# 101| 1: [ReservedWord] ||= -# 101| 2: [Integer] 8 -# 102| 70: [OperatorAssignment] OperatorAssignment -# 102| 0: [ScopeResolution] ScopeResolution -# 102| 0: [Call] Call -# 102| 0: [Call] Call -# 102| 0: [Identifier] foo -# 102| 1: [ArgumentList] ArgumentList -# 102| 0: [ReservedWord] ( -# 102| 1: [Integer] 1 -# 102| 2: [ReservedWord] ) -# 102| 1: [ReservedWord] . -# 102| 2: [Identifier] bar -# 102| 1: [ReservedWord] :: -# 102| 2: [Constant] OtherConstant -# 102| 1: [ReservedWord] ||= -# 102| 2: [Integer] 7 -# 103| 71: [OperatorAssignment] OperatorAssignment -# 103| 0: [ScopeResolution] ScopeResolution -# 103| 0: [ReservedWord] :: -# 103| 1: [Constant] CONSTANT4 -# 103| 1: [ReservedWord] ||= -# 103| 2: [Integer] 7 -# 104| 72: [Assignment] Assignment -# 104| 0: [LeftAssignmentList] LeftAssignmentList -# 104| 0: [Constant] FOO -# 104| 1: [ReservedWord] , -# 104| 2: [ScopeResolution] ScopeResolution -# 104| 0: [ReservedWord] :: -# 104| 1: [Constant] BAR -# 104| 3: [ReservedWord] , -# 104| 4: [ScopeResolution] ScopeResolution -# 104| 0: [Identifier] foo -# 104| 1: [ReservedWord] :: -# 104| 2: [Constant] FOO -# 104| 1: [ReservedWord] = -# 104| 2: [Array] Array -# 104| 0: [ReservedWord] [ -# 104| 1: [Integer] 1 -# 104| 2: [ReservedWord] , -# 104| 3: [Integer] 2 -# 104| 4: [ReservedWord] , -# 104| 5: [Integer] 3 -# 104| 6: [ReservedWord] ] -# 106| 73: [Binary] Binary -# 106| 0: [Identifier] foo -# 106| 1: [ReservedWord] / -# 107| 2: [Integer] 5 +# 88| 63: [Assignment] Assignment +# 88| 0: [Identifier] foo +# 88| 1: [ReservedWord] = +# 88| 2: [Binary] Binary +# 88| 0: [Identifier] a +# 89| 1: [ReservedWord] && +# 89| 2: [Identifier] b +# 95| 64: [Method] Method +# 95| 0: [ReservedWord] def +# 95| 1: [Identifier] foo +# 95| 2: [MethodParameters] MethodParameters +# 95| 0: [ReservedWord] ( +# 95| 1: [Identifier] a +# 95| 2: [ReservedWord] , +# 95| 3: [Identifier] b +# 95| 4: [ReservedWord] ) +# 96| 3: [BodyStatement] BodyStatement +# 96| 0: [Return] Return +# 96| 0: [ReservedWord] return +# 96| 1: [ArgumentList] ArgumentList +# 96| 0: [Binary] Binary +# 96| 0: [Identifier] a +# 97| 1: [ReservedWord] && +# 97| 2: [Identifier] b +# 98| 4: [ReservedWord] end +# 107| 65: [Class] Class +# 107| 0: [ReservedWord] class +# 107| 1: [Constant] X +# 108| 2: [BodyStatement] BodyStatement +# 108| 0: [Assignment] Assignment +# 108| 0: [InstanceVariable] @x +# 108| 1: [ReservedWord] = +# 108| 2: [Integer] 1 +# 109| 1: [OperatorAssignment] OperatorAssignment +# 109| 0: [InstanceVariable] @x +# 109| 1: [ReservedWord] += +# 109| 2: [Integer] 2 +# 111| 2: [Assignment] Assignment +# 111| 0: [ClassVariable] @@y +# 111| 1: [ReservedWord] = +# 111| 2: [Integer] 3 +# 112| 3: [OperatorAssignment] OperatorAssignment +# 112| 0: [ClassVariable] @@y +# 112| 1: [ReservedWord] /= +# 112| 2: [Integer] 4 +# 113| 3: [ReservedWord] end +# 115| 66: [Assignment] Assignment +# 115| 0: [GlobalVariable] $global_var +# 115| 1: [ReservedWord] = +# 115| 2: [Integer] 5 +# 116| 67: [OperatorAssignment] OperatorAssignment +# 116| 0: [GlobalVariable] $global_var +# 116| 1: [ReservedWord] *= +# 116| 2: [Integer] 6 +# 118| 68: [Assignment] Assignment +# 118| 0: [Constant] CONSTANT1 +# 118| 1: [ReservedWord] = +# 118| 2: [Integer] 5 +# 119| 69: [OperatorAssignment] OperatorAssignment +# 119| 0: [Constant] CONSTANT2 +# 119| 1: [ReservedWord] += +# 119| 2: [Integer] 6 +# 120| 70: [OperatorAssignment] OperatorAssignment +# 120| 0: [Constant] CONSTANT3 +# 120| 1: [ReservedWord] ||= +# 120| 2: [Integer] 7 +# 121| 71: [OperatorAssignment] OperatorAssignment +# 121| 0: [ScopeResolution] ScopeResolution +# 121| 0: [Constant] Foo +# 121| 1: [ReservedWord] :: +# 121| 2: [Constant] MemberConstant +# 121| 1: [ReservedWord] ||= +# 121| 2: [Integer] 8 +# 122| 72: [OperatorAssignment] OperatorAssignment +# 122| 0: [ScopeResolution] ScopeResolution +# 122| 0: [Call] Call +# 122| 0: [Call] Call +# 122| 0: [Identifier] foo +# 122| 1: [ArgumentList] ArgumentList +# 122| 0: [ReservedWord] ( +# 122| 1: [Integer] 1 +# 122| 2: [ReservedWord] ) +# 122| 1: [ReservedWord] . +# 122| 2: [Identifier] bar +# 122| 1: [ReservedWord] :: +# 122| 2: [Constant] OtherConstant +# 122| 1: [ReservedWord] ||= +# 122| 2: [Integer] 7 +# 123| 73: [OperatorAssignment] OperatorAssignment +# 123| 0: [ScopeResolution] ScopeResolution +# 123| 0: [ReservedWord] :: +# 123| 1: [Constant] CONSTANT4 +# 123| 1: [ReservedWord] ||= +# 123| 2: [Integer] 7 +# 124| 74: [Assignment] Assignment +# 124| 0: [LeftAssignmentList] LeftAssignmentList +# 124| 0: [Constant] FOO +# 124| 1: [ReservedWord] , +# 124| 2: [ScopeResolution] ScopeResolution +# 124| 0: [ReservedWord] :: +# 124| 1: [Constant] BAR +# 124| 3: [ReservedWord] , +# 124| 4: [ScopeResolution] ScopeResolution +# 124| 0: [Identifier] foo +# 124| 1: [ReservedWord] :: +# 124| 2: [Constant] FOO +# 124| 1: [ReservedWord] = +# 124| 2: [Array] Array +# 124| 0: [ReservedWord] [ +# 124| 1: [Integer] 1 +# 124| 2: [ReservedWord] , +# 124| 3: [Integer] 2 +# 124| 4: [ReservedWord] , +# 124| 5: [Integer] 3 +# 124| 6: [ReservedWord] ] +# 126| 75: [Binary] Binary +# 126| 0: [Identifier] foo +# 126| 1: [ReservedWord] / +# 127| 2: [Integer] 5 # 1| [Comment] # Start with assignments to all the identifiers used below, so that they are # 2| [Comment] # interpreted as variables. # 22| [Comment] # Unary operations @@ -5670,6 +5799,17 @@ operations/operations.rb: # 68| [Comment] # Arithmetic assign operations # 76| [Comment] # Logical assign operations # 80| [Comment] # Bitwise assign operations +# 87| [Comment] # Assignments with operation at start of line +# 90| [Comment] # NOTE: This is not parsed correctly, `|| b` is dropped +# 91| [Comment] # bar = a +# 92| [Comment] # || b +# 94| [Comment] # Return with `&&` at start of line +# 100| [Comment] # Return with `||` at start of line +# 101| [Comment] # NOTE: This is not parsed correctly, `|| b` is dropped +# 102| [Comment] # def bar(a, b) +# 103| [Comment] # return a +# 104| [Comment] # || b +# 105| [Comment] # end params/params.rb: # 1| [Program] Program # 4| 0: [Method] Method diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected index 283eef73d25..e0ad853ba83 100644 --- a/ruby/ql/test/library-tests/ast/ValueText.expected +++ b/ruby/ql/test/library-tests/ast/ValueText.expected @@ -336,6 +336,19 @@ exprValue | control/conditionals.rb:62:5:62:5 | c | 0 | int | | control/conditionals.rb:67:8:67:8 | b | 0 | int | | control/conditionals.rb:69:5:69:5 | c | 0 | int | +| control/conditionals.rb:73:9:73:9 | b | 0 | int | +| control/conditionals.rb:74:5:74:5 | c | 0 | int | +| control/conditionals.rb:79:8:79:8 | b | 0 | int | +| control/conditionals.rb:81:5:81:5 | c | 0 | int | +| control/conditionals.rb:87:9:87:9 | b | 0 | int | +| control/conditionals.rb:89:5:89:5 | c | 0 | int | +| control/conditionals.rb:103:8:103:8 | b | 0 | int | +| control/conditionals.rb:105:5:105:5 | c | 0 | int | +| control/conditionals.rb:110:8:110:8 | b | 0 | int | +| control/conditionals.rb:111:8:111:8 | c | 0 | int | +| control/conditionals.rb:113:5:113:5 | d | 0 | int | +| control/conditionals.rb:145:5:145:5 | b | 0 | int | +| control/conditionals.rb:147:5:147:5 | c | 0 | int | | control/loops.rb:2:7:2:7 | 0 | 0 | int | | control/loops.rb:3:7:3:7 | 0 | 0 | int | | control/loops.rb:4:5:4:5 | 0 | 0 | int | @@ -908,26 +921,27 @@ exprValue | operations/operations.rb:84:9:84:12 | 0x01 | 1 | int | | operations/operations.rb:85:2:85:4 | baz | 0 | int | | operations/operations.rb:85:9:85:11 | qux | 0 | int | -| operations/operations.rb:88:8:88:8 | 1 | 1 | int | -| operations/operations.rb:89:9:89:9 | 2 | 2 | int | -| operations/operations.rb:91:9:91:9 | 3 | 3 | int | -| operations/operations.rb:92:10:92:10 | 4 | 4 | int | -| operations/operations.rb:95:15:95:15 | 5 | 5 | int | -| operations/operations.rb:96:16:96:16 | 6 | 6 | int | -| operations/operations.rb:98:13:98:13 | 5 | 5 | int | -| operations/operations.rb:99:14:99:14 | 6 | 6 | int | -| operations/operations.rb:100:15:100:15 | 7 | 7 | int | -| operations/operations.rb:101:25:101:25 | 8 | 8 | int | -| operations/operations.rb:102:5:102:5 | 1 | 1 | int | -| operations/operations.rb:102:31:102:31 | 7 | 7 | int | -| operations/operations.rb:103:17:103:17 | 7 | 7 | int | -| operations/operations.rb:104:1:104:3 | 0 | 0 | int | -| operations/operations.rb:104:6:104:10 | 1 | 1 | int | -| operations/operations.rb:104:13:104:20 | 2 | 2 | int | -| operations/operations.rb:104:25:104:25 | 1 | 1 | int | -| operations/operations.rb:104:28:104:28 | 2 | 2 | int | -| operations/operations.rb:104:31:104:31 | 3 | 3 | int | -| operations/operations.rb:107:1:107:1 | 5 | 5 | int | +| operations/operations.rb:89:6:89:6 | b | 0 | int | +| operations/operations.rb:108:8:108:8 | 1 | 1 | int | +| operations/operations.rb:109:9:109:9 | 2 | 2 | int | +| operations/operations.rb:111:9:111:9 | 3 | 3 | int | +| operations/operations.rb:112:10:112:10 | 4 | 4 | int | +| operations/operations.rb:115:15:115:15 | 5 | 5 | int | +| operations/operations.rb:116:16:116:16 | 6 | 6 | int | +| operations/operations.rb:118:13:118:13 | 5 | 5 | int | +| operations/operations.rb:119:14:119:14 | 6 | 6 | int | +| operations/operations.rb:120:15:120:15 | 7 | 7 | int | +| operations/operations.rb:121:25:121:25 | 8 | 8 | int | +| operations/operations.rb:122:5:122:5 | 1 | 1 | int | +| operations/operations.rb:122:31:122:31 | 7 | 7 | int | +| operations/operations.rb:123:17:123:17 | 7 | 7 | int | +| operations/operations.rb:124:1:124:3 | 0 | 0 | int | +| operations/operations.rb:124:6:124:10 | 1 | 1 | int | +| operations/operations.rb:124:13:124:20 | 2 | 2 | int | +| operations/operations.rb:124:25:124:25 | 1 | 1 | int | +| operations/operations.rb:124:28:124:28 | 2 | 2 | int | +| operations/operations.rb:124:31:124:31 | 3 | 3 | int | +| operations/operations.rb:127:1:127:1 | 5 | 5 | int | | params/params.rb:41:46:41:46 | 7 | 7 | int | | params/params.rb:47:19:47:21 | :bar | :bar | symbol | | params/params.rb:47:24:47:24 | 2 | 2 | int | @@ -1257,6 +1271,19 @@ exprCfgNodeValue | control/conditionals.rb:62:5:62:5 | c | 0 | int | | control/conditionals.rb:67:8:67:8 | b | 0 | int | | control/conditionals.rb:69:5:69:5 | c | 0 | int | +| control/conditionals.rb:73:9:73:9 | b | 0 | int | +| control/conditionals.rb:74:5:74:5 | c | 0 | int | +| control/conditionals.rb:79:8:79:8 | b | 0 | int | +| control/conditionals.rb:81:5:81:5 | c | 0 | int | +| control/conditionals.rb:87:9:87:9 | b | 0 | int | +| control/conditionals.rb:89:5:89:5 | c | 0 | int | +| control/conditionals.rb:103:8:103:8 | b | 0 | int | +| control/conditionals.rb:105:5:105:5 | c | 0 | int | +| control/conditionals.rb:110:8:110:8 | b | 0 | int | +| control/conditionals.rb:111:8:111:8 | c | 0 | int | +| control/conditionals.rb:113:5:113:5 | d | 0 | int | +| control/conditionals.rb:145:5:145:5 | b | 0 | int | +| control/conditionals.rb:147:5:147:5 | c | 0 | int | | control/loops.rb:2:7:2:7 | 0 | 0 | int | | control/loops.rb:3:7:3:7 | 0 | 0 | int | | control/loops.rb:4:5:4:5 | 0 | 0 | int | @@ -1828,26 +1855,27 @@ exprCfgNodeValue | operations/operations.rb:84:9:84:12 | 0x01 | 1 | int | | operations/operations.rb:85:2:85:4 | baz | 0 | int | | operations/operations.rb:85:9:85:11 | qux | 0 | int | -| operations/operations.rb:88:8:88:8 | 1 | 1 | int | -| operations/operations.rb:89:9:89:9 | 2 | 2 | int | -| operations/operations.rb:91:9:91:9 | 3 | 3 | int | -| operations/operations.rb:92:10:92:10 | 4 | 4 | int | -| operations/operations.rb:95:15:95:15 | 5 | 5 | int | -| operations/operations.rb:96:16:96:16 | 6 | 6 | int | -| operations/operations.rb:98:13:98:13 | 5 | 5 | int | -| operations/operations.rb:99:14:99:14 | 6 | 6 | int | -| operations/operations.rb:100:15:100:15 | 7 | 7 | int | -| operations/operations.rb:101:25:101:25 | 8 | 8 | int | -| operations/operations.rb:102:5:102:5 | 1 | 1 | int | -| operations/operations.rb:102:31:102:31 | 7 | 7 | int | -| operations/operations.rb:103:17:103:17 | 7 | 7 | int | -| operations/operations.rb:104:1:104:3 | 0 | 0 | int | -| operations/operations.rb:104:6:104:10 | 1 | 1 | int | -| operations/operations.rb:104:13:104:20 | 2 | 2 | int | -| operations/operations.rb:104:25:104:25 | 1 | 1 | int | -| operations/operations.rb:104:28:104:28 | 2 | 2 | int | -| operations/operations.rb:104:31:104:31 | 3 | 3 | int | -| operations/operations.rb:107:1:107:1 | 5 | 5 | int | +| operations/operations.rb:89:6:89:6 | b | 0 | int | +| operations/operations.rb:108:8:108:8 | 1 | 1 | int | +| operations/operations.rb:109:9:109:9 | 2 | 2 | int | +| operations/operations.rb:111:9:111:9 | 3 | 3 | int | +| operations/operations.rb:112:10:112:10 | 4 | 4 | int | +| operations/operations.rb:115:15:115:15 | 5 | 5 | int | +| operations/operations.rb:116:16:116:16 | 6 | 6 | int | +| operations/operations.rb:118:13:118:13 | 5 | 5 | int | +| operations/operations.rb:119:14:119:14 | 6 | 6 | int | +| operations/operations.rb:120:15:120:15 | 7 | 7 | int | +| operations/operations.rb:121:25:121:25 | 8 | 8 | int | +| operations/operations.rb:122:5:122:5 | 1 | 1 | int | +| operations/operations.rb:122:31:122:31 | 7 | 7 | int | +| operations/operations.rb:123:17:123:17 | 7 | 7 | int | +| operations/operations.rb:124:1:124:3 | 0 | 0 | int | +| operations/operations.rb:124:6:124:10 | 1 | 1 | int | +| operations/operations.rb:124:13:124:20 | 2 | 2 | int | +| operations/operations.rb:124:25:124:25 | 1 | 1 | int | +| operations/operations.rb:124:28:124:28 | 2 | 2 | int | +| operations/operations.rb:124:31:124:31 | 3 | 3 | int | +| operations/operations.rb:127:1:127:1 | 5 | 5 | int | | params/params.rb:41:46:41:46 | 7 | 7 | int | | params/params.rb:47:19:47:21 | :bar | :bar | symbol | | params/params.rb:47:24:47:24 | 2 | 2 | int | diff --git a/ruby/ql/test/library-tests/ast/control/ConditionalExpr.expected b/ruby/ql/test/library-tests/ast/control/ConditionalExpr.expected index db7cd1957fb..b2817b6feda 100644 --- a/ruby/ql/test/library-tests/ast/control/ConditionalExpr.expected +++ b/ruby/ql/test/library-tests/ast/control/ConditionalExpr.expected @@ -22,6 +22,12 @@ conditionalExprs | conditionals.rb:61:1:64:3 | if ... | IfExpr | conditionals.rb:61:4:61:8 | ... > ... | conditionals.rb:63:1:63:4 | else ... | false | | conditionals.rb:67:1:70:3 | if ... | IfExpr | conditionals.rb:67:4:67:8 | ... > ... | conditionals.rb:67:10:67:13 | then ... | true | | conditionals.rb:67:1:70:3 | if ... | IfExpr | conditionals.rb:67:4:67:8 | ... > ... | conditionals.rb:68:1:69:5 | else ... | false | +| conditionals.rb:73:1:75:3 | if ... | IfExpr | conditionals.rb:73:4:73:9 | ... && ... | conditionals.rb:73:11:74:5 | then ... | true | +| conditionals.rb:78:1:82:3 | if ... | IfExpr | conditionals.rb:78:4:79:8 | ... && ... | conditionals.rb:79:9:81:5 | then ... | true | +| conditionals.rb:86:1:90:3 | if ... | IfExpr | conditionals.rb:86:4:86:4 | a | conditionals.rb:86:5:89:5 | then ... | true | +| conditionals.rb:102:1:106:3 | if ... | IfExpr | conditionals.rb:102:4:102:4 | a | conditionals.rb:102:5:105:5 | then ... | true | +| conditionals.rb:109:1:114:3 | if ... | IfExpr | conditionals.rb:109:4:111:8 | ... && ... | conditionals.rb:111:9:113:5 | then ... | true | +| conditionals.rb:144:1:148:3 | if ... | IfExpr | conditionals.rb:144:4:145:5 | ... && ... | conditionals.rb:145:6:147:5 | then ... | true | | loops.rb:9:5:9:5 | if ... | IfExpr | loops.rb:9:5:9:5 | ! ... | loops.rb:9:5:9:5 | ... = ... | true | | loops.rb:16:5:16:5 | if ... | IfExpr | loops.rb:16:5:16:5 | ! ... | loops.rb:16:5:16:5 | ... = ... | true | | loops.rb:22:5:22:7 | if ... | IfExpr | loops.rb:22:5:22:7 | ! ... | loops.rb:22:5:22:7 | ... = ... | true | @@ -38,6 +44,12 @@ ifExprs | conditionals.rb:35:1:36:5 | elsif ... | IfExpr | conditionals.rb:35:7:35:12 | ... == ... | conditionals.rb:35:13:36:5 | then ... | (none) | true | | conditionals.rb:61:1:64:3 | if ... | IfExpr | conditionals.rb:61:4:61:8 | ... > ... | conditionals.rb:61:10:62:5 | then ... | else ... | false | | conditionals.rb:67:1:70:3 | if ... | IfExpr | conditionals.rb:67:4:67:8 | ... > ... | conditionals.rb:67:10:67:13 | then ... | else ... | false | +| conditionals.rb:73:1:75:3 | if ... | IfExpr | conditionals.rb:73:4:73:9 | ... && ... | conditionals.rb:73:11:74:5 | then ... | (none) | false | +| conditionals.rb:78:1:82:3 | if ... | IfExpr | conditionals.rb:78:4:79:8 | ... && ... | conditionals.rb:79:9:81:5 | then ... | (none) | false | +| conditionals.rb:86:1:90:3 | if ... | IfExpr | conditionals.rb:86:4:86:4 | a | conditionals.rb:86:5:89:5 | then ... | (none) | false | +| conditionals.rb:102:1:106:3 | if ... | IfExpr | conditionals.rb:102:4:102:4 | a | conditionals.rb:102:5:105:5 | then ... | (none) | false | +| conditionals.rb:109:1:114:3 | if ... | IfExpr | conditionals.rb:109:4:111:8 | ... && ... | conditionals.rb:111:9:113:5 | then ... | (none) | false | +| conditionals.rb:144:1:148:3 | if ... | IfExpr | conditionals.rb:144:4:145:5 | ... && ... | conditionals.rb:145:6:147:5 | then ... | (none) | false | unlessExprs | conditionals.rb:40:1:42:3 | unless ... | UnlessExpr | conditionals.rb:40:8:40:12 | ... > ... | conditionals.rb:40:14:41:5 | then ... | (none) | | conditionals.rb:45:1:49:3 | unless ... | UnlessExpr | conditionals.rb:45:8:45:13 | ... == ... | conditionals.rb:45:14:46:5 | then ... | else ... | diff --git a/ruby/ql/test/library-tests/ast/control/ControlExpr.expected b/ruby/ql/test/library-tests/ast/control/ControlExpr.expected index aaa72ac8027..e84d2608249 100644 --- a/ruby/ql/test/library-tests/ast/control/ControlExpr.expected +++ b/ruby/ql/test/library-tests/ast/control/ControlExpr.expected @@ -28,6 +28,12 @@ | conditionals.rb:58:5:58:25 | ... ? ... : ... | TernaryIfExpr | | conditionals.rb:61:1:64:3 | if ... | IfExpr | | conditionals.rb:67:1:70:3 | if ... | IfExpr | +| conditionals.rb:73:1:75:3 | if ... | IfExpr | +| conditionals.rb:78:1:82:3 | if ... | IfExpr | +| conditionals.rb:86:1:90:3 | if ... | IfExpr | +| conditionals.rb:102:1:106:3 | if ... | IfExpr | +| conditionals.rb:109:1:114:3 | if ... | IfExpr | +| conditionals.rb:144:1:148:3 | if ... | IfExpr | | loops.rb:9:1:12:3 | for ... in ... | ForExpr | | loops.rb:9:5:9:5 | if ... | IfExpr | | loops.rb:16:1:19:3 | for ... in ... | ForExpr | diff --git a/ruby/ql/test/library-tests/ast/control/conditionals.rb b/ruby/ql/test/library-tests/ast/control/conditionals.rb index 85e008f5c1d..b5c63afbc81 100644 --- a/ruby/ql/test/library-tests/ast/control/conditionals.rb +++ b/ruby/ql/test/library-tests/ast/control/conditionals.rb @@ -67,4 +67,82 @@ end if a > b then else c +end + +# If expr with `&&` on same line as condition and then +if a && b then + c +end + +# If expr with `&&` at the start of a separate line before then +if a + && b +then + c +end + +# If expr with `and` at the start of a separate line before then +# NOTE: This is not parsed correctly, `and b` is parsed as a call +if a + and b +then + c +end + +# If expr with `||` at the start of a separate line before then +# NOTE: This is not parsed correctly due to the leading `||` +# if a +# || b +# then +# c +# end + +# If expr with `or` at the start of a separate line before then +# NOTE: This is not parsed correctly, `or b` is parsed as a call +if a + or b +then + c +end + +# If expr with repeated && at the start of a separate line before then +if a + && b + && c +then + d +end + +# If expr with alternating && and || at the start of lines +# NOTE: This is not parsed correctly due to the leading `||` +# if a +# && b +# || c +# then +# d +# end + +# If expr with operator at start of line and parentheses +# NOTE: This is not parsed correctly due to the leading `||` +# if a +# && (b +# || c) +# then +# d +# end + +# If expr with operator at start of line and parentheses +# NOTE: This is not parsed correctly due to the leading `||` +# if a +# || (b +# && c) +# then +# d +# end + +# If expr with && at end of line +if a && + b +then + c end \ No newline at end of file diff --git a/ruby/ql/test/library-tests/ast/operations/assignment.expected b/ruby/ql/test/library-tests/ast/operations/assignment.expected index 5349ebf5cef..54f6a0c00fa 100644 --- a/ruby/ql/test/library-tests/ast/operations/assignment.expected +++ b/ruby/ql/test/library-tests/ast/operations/assignment.expected @@ -43,34 +43,35 @@ assignments | operations.rb:84:2:84:12 | ... \|= ... | \|= | operations.rb:84:2:84:4 | bar | operations.rb:84:9:84:12 | 0x01 | AssignBitwiseOrExpr | | operations.rb:85:2:85:11 | ... = ... | = | operations.rb:85:2:85:4 | baz | operations.rb:85:6:85:7 | ... ^ ... | AssignExpr | | operations.rb:85:2:85:11 | ... ^= ... | ^= | operations.rb:85:2:85:4 | baz | operations.rb:85:9:85:11 | qux | AssignBitwiseXorExpr | -| operations.rb:88:3:88:8 | ... = ... | = | operations.rb:88:3:88:4 | @x | operations.rb:88:8:88:8 | 1 | AssignExpr | -| operations.rb:89:3:89:9 | ... += ... | += | operations.rb:89:3:89:4 | @x | operations.rb:89:9:89:9 | 2 | AssignAddExpr | -| operations.rb:89:3:89:9 | ... = ... | = | operations.rb:89:3:89:4 | @x | operations.rb:89:6:89:7 | ... + ... | AssignExpr | -| operations.rb:91:3:91:9 | ... = ... | = | operations.rb:91:3:91:5 | @@y | operations.rb:91:9:91:9 | 3 | AssignExpr | -| operations.rb:92:3:92:10 | ... /= ... | /= | operations.rb:92:3:92:5 | @@y | operations.rb:92:10:92:10 | 4 | AssignDivExpr | -| operations.rb:92:3:92:10 | ... = ... | = | operations.rb:92:3:92:5 | @@y | operations.rb:92:7:92:8 | ... / ... | AssignExpr | -| operations.rb:95:1:95:15 | ... = ... | = | operations.rb:95:1:95:11 | $global_var | operations.rb:95:15:95:15 | 5 | AssignExpr | -| operations.rb:96:1:96:16 | ... *= ... | *= | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | AssignMulExpr | -| operations.rb:96:1:96:16 | ... = ... | = | operations.rb:96:1:96:11 | $global_var | operations.rb:96:13:96:14 | ... * ... | AssignExpr | -| operations.rb:98:1:98:13 | ... = ... | = | operations.rb:98:1:98:9 | CONSTANT1 | operations.rb:98:13:98:13 | 5 | AssignExpr | -| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AssignAddExpr | -| operations.rb:99:1:99:14 | ... = ... | = | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:11:99:12 | ... + ... | AssignExpr | -| operations.rb:100:1:100:15 | ... = ... | = | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:11:100:13 | ... \|\| ... | AssignExpr | -| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | AssignLogicalOrExpr | -| operations.rb:101:1:101:3 | ... = ... | = | operations.rb:101:1:101:3 | __synth__0 | operations.rb:101:1:101:3 | Foo | AssignExpr | -| operations.rb:101:1:101:25 | ... = ... | = | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:21:101:23 | ... \|\| ... | AssignExpr | -| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | AssignLogicalOrExpr | -| operations.rb:102:1:102:10 | ... = ... | = | operations.rb:102:1:102:10 | __synth__0 | operations.rb:102:1:102:10 | call to bar | AssignExpr | -| operations.rb:102:1:102:31 | ... = ... | = | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:27:102:29 | ... \|\| ... | AssignExpr | -| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | AssignLogicalOrExpr | -| operations.rb:103:1:103:17 | ... = ... | = | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:13:103:15 | ... \|\| ... | AssignExpr | -| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr | -| operations.rb:104:1:104:3 | ... = ... | = | operations.rb:104:1:104:3 | FOO | operations.rb:104:1:104:3 | call to [] | AssignExpr | -| operations.rb:104:1:104:32 | ... = ... | = | operations.rb:104:1:104:20 | (..., ...) | operations.rb:104:24:104:32 | [...] | AssignExpr | -| operations.rb:104:6:104:10 | ... = ... | = | operations.rb:104:6:104:10 | BAR | operations.rb:104:6:104:10 | call to [] | AssignExpr | -| operations.rb:104:13:104:15 | ... = ... | = | operations.rb:104:13:104:15 | __synth__2 | operations.rb:104:13:104:15 | foo | AssignExpr | -| operations.rb:104:13:104:20 | ... = ... | = | operations.rb:104:13:104:20 | FOO | operations.rb:104:13:104:20 | call to [] | AssignExpr | -| operations.rb:104:24:104:32 | ... = ... | = | operations.rb:104:24:104:32 | __synth__3 | operations.rb:104:24:104:32 | * ... | AssignExpr | +| operations.rb:88:1:89:6 | ... = ... | = | operations.rb:88:1:88:3 | foo | operations.rb:88:7:89:6 | ... && ... | AssignExpr | +| operations.rb:108:3:108:8 | ... = ... | = | operations.rb:108:3:108:4 | @x | operations.rb:108:8:108:8 | 1 | AssignExpr | +| operations.rb:109:3:109:9 | ... += ... | += | operations.rb:109:3:109:4 | @x | operations.rb:109:9:109:9 | 2 | AssignAddExpr | +| operations.rb:109:3:109:9 | ... = ... | = | operations.rb:109:3:109:4 | @x | operations.rb:109:6:109:7 | ... + ... | AssignExpr | +| operations.rb:111:3:111:9 | ... = ... | = | operations.rb:111:3:111:5 | @@y | operations.rb:111:9:111:9 | 3 | AssignExpr | +| operations.rb:112:3:112:10 | ... /= ... | /= | operations.rb:112:3:112:5 | @@y | operations.rb:112:10:112:10 | 4 | AssignDivExpr | +| operations.rb:112:3:112:10 | ... = ... | = | operations.rb:112:3:112:5 | @@y | operations.rb:112:7:112:8 | ... / ... | AssignExpr | +| operations.rb:115:1:115:15 | ... = ... | = | operations.rb:115:1:115:11 | $global_var | operations.rb:115:15:115:15 | 5 | AssignExpr | +| operations.rb:116:1:116:16 | ... *= ... | *= | operations.rb:116:1:116:11 | $global_var | operations.rb:116:16:116:16 | 6 | AssignMulExpr | +| operations.rb:116:1:116:16 | ... = ... | = | operations.rb:116:1:116:11 | $global_var | operations.rb:116:13:116:14 | ... * ... | AssignExpr | +| operations.rb:118:1:118:13 | ... = ... | = | operations.rb:118:1:118:9 | CONSTANT1 | operations.rb:118:13:118:13 | 5 | AssignExpr | +| operations.rb:119:1:119:14 | ... += ... | += | operations.rb:119:1:119:9 | CONSTANT2 | operations.rb:119:14:119:14 | 6 | AssignAddExpr | +| operations.rb:119:1:119:14 | ... = ... | = | operations.rb:119:1:119:9 | CONSTANT2 | operations.rb:119:11:119:12 | ... + ... | AssignExpr | +| operations.rb:120:1:120:15 | ... = ... | = | operations.rb:120:1:120:9 | CONSTANT3 | operations.rb:120:11:120:13 | ... \|\| ... | AssignExpr | +| operations.rb:120:1:120:15 | ... \|\|= ... | \|\|= | operations.rb:120:1:120:9 | CONSTANT3 | operations.rb:120:15:120:15 | 7 | AssignLogicalOrExpr | +| operations.rb:121:1:121:3 | ... = ... | = | operations.rb:121:1:121:3 | __synth__0 | operations.rb:121:1:121:3 | Foo | AssignExpr | +| operations.rb:121:1:121:25 | ... = ... | = | operations.rb:121:1:121:19 | MemberConstant | operations.rb:121:21:121:23 | ... \|\| ... | AssignExpr | +| operations.rb:121:1:121:25 | ... \|\|= ... | \|\|= | operations.rb:121:1:121:19 | MemberConstant | operations.rb:121:25:121:25 | 8 | AssignLogicalOrExpr | +| operations.rb:122:1:122:10 | ... = ... | = | operations.rb:122:1:122:10 | __synth__0 | operations.rb:122:1:122:10 | call to bar | AssignExpr | +| operations.rb:122:1:122:31 | ... = ... | = | operations.rb:122:1:122:25 | OtherConstant | operations.rb:122:27:122:29 | ... \|\| ... | AssignExpr | +| operations.rb:122:1:122:31 | ... \|\|= ... | \|\|= | operations.rb:122:1:122:25 | OtherConstant | operations.rb:122:31:122:31 | 7 | AssignLogicalOrExpr | +| operations.rb:123:1:123:17 | ... = ... | = | operations.rb:123:1:123:11 | CONSTANT4 | operations.rb:123:13:123:15 | ... \|\| ... | AssignExpr | +| operations.rb:123:1:123:17 | ... \|\|= ... | \|\|= | operations.rb:123:1:123:11 | CONSTANT4 | operations.rb:123:17:123:17 | 7 | AssignLogicalOrExpr | +| operations.rb:124:1:124:3 | ... = ... | = | operations.rb:124:1:124:3 | FOO | operations.rb:124:1:124:3 | call to [] | AssignExpr | +| operations.rb:124:1:124:32 | ... = ... | = | operations.rb:124:1:124:20 | (..., ...) | operations.rb:124:24:124:32 | [...] | AssignExpr | +| operations.rb:124:6:124:10 | ... = ... | = | operations.rb:124:6:124:10 | BAR | operations.rb:124:6:124:10 | call to [] | AssignExpr | +| operations.rb:124:13:124:15 | ... = ... | = | operations.rb:124:13:124:15 | __synth__2 | operations.rb:124:13:124:15 | foo | AssignExpr | +| operations.rb:124:13:124:20 | ... = ... | = | operations.rb:124:13:124:20 | FOO | operations.rb:124:13:124:20 | call to [] | AssignExpr | +| operations.rb:124:24:124:32 | ... = ... | = | operations.rb:124:24:124:32 | __synth__3 | operations.rb:124:24:124:32 | * ... | AssignExpr | assignOperations | operations.rb:69:1:69:8 | ... += ... | += | operations.rb:69:1:69:1 | x | operations.rb:69:6:69:8 | 128 | AssignAddExpr | | operations.rb:70:1:70:7 | ... -= ... | -= | operations.rb:70:1:70:1 | y | operations.rb:70:6:70:7 | 32 | AssignSubExpr | @@ -85,14 +86,14 @@ assignOperations | operations.rb:83:2:83:12 | ... &= ... | &= | operations.rb:83:2:83:4 | foo | operations.rb:83:9:83:12 | mask | AssignBitwiseAndExpr | | operations.rb:84:2:84:12 | ... \|= ... | \|= | operations.rb:84:2:84:4 | bar | operations.rb:84:9:84:12 | 0x01 | AssignBitwiseOrExpr | | operations.rb:85:2:85:11 | ... ^= ... | ^= | operations.rb:85:2:85:4 | baz | operations.rb:85:9:85:11 | qux | AssignBitwiseXorExpr | -| operations.rb:89:3:89:9 | ... += ... | += | operations.rb:89:3:89:4 | @x | operations.rb:89:9:89:9 | 2 | AssignAddExpr | -| operations.rb:92:3:92:10 | ... /= ... | /= | operations.rb:92:3:92:5 | @@y | operations.rb:92:10:92:10 | 4 | AssignDivExpr | -| operations.rb:96:1:96:16 | ... *= ... | *= | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | AssignMulExpr | -| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AssignAddExpr | -| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | AssignLogicalOrExpr | -| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | AssignLogicalOrExpr | -| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | AssignLogicalOrExpr | -| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr | +| operations.rb:109:3:109:9 | ... += ... | += | operations.rb:109:3:109:4 | @x | operations.rb:109:9:109:9 | 2 | AssignAddExpr | +| operations.rb:112:3:112:10 | ... /= ... | /= | operations.rb:112:3:112:5 | @@y | operations.rb:112:10:112:10 | 4 | AssignDivExpr | +| operations.rb:116:1:116:16 | ... *= ... | *= | operations.rb:116:1:116:11 | $global_var | operations.rb:116:16:116:16 | 6 | AssignMulExpr | +| operations.rb:119:1:119:14 | ... += ... | += | operations.rb:119:1:119:9 | CONSTANT2 | operations.rb:119:14:119:14 | 6 | AssignAddExpr | +| operations.rb:120:1:120:15 | ... \|\|= ... | \|\|= | operations.rb:120:1:120:9 | CONSTANT3 | operations.rb:120:15:120:15 | 7 | AssignLogicalOrExpr | +| operations.rb:121:1:121:25 | ... \|\|= ... | \|\|= | operations.rb:121:1:121:19 | MemberConstant | operations.rb:121:25:121:25 | 8 | AssignLogicalOrExpr | +| operations.rb:122:1:122:31 | ... \|\|= ... | \|\|= | operations.rb:122:1:122:25 | OtherConstant | operations.rb:122:31:122:31 | 7 | AssignLogicalOrExpr | +| operations.rb:123:1:123:17 | ... \|\|= ... | \|\|= | operations.rb:123:1:123:11 | CONSTANT4 | operations.rb:123:17:123:17 | 7 | AssignLogicalOrExpr | assignArithmeticOperations | operations.rb:69:1:69:8 | ... += ... | += | operations.rb:69:1:69:1 | x | operations.rb:69:6:69:8 | 128 | AssignAddExpr | | operations.rb:70:1:70:7 | ... -= ... | -= | operations.rb:70:1:70:1 | y | operations.rb:70:6:70:7 | 32 | AssignSubExpr | @@ -100,17 +101,17 @@ assignArithmeticOperations | operations.rb:72:1:72:6 | ... /= ... | /= | operations.rb:72:1:72:1 | b | operations.rb:72:6:72:6 | 4 | AssignDivExpr | | operations.rb:73:1:73:6 | ... %= ... | %= | operations.rb:73:1:73:1 | z | operations.rb:73:6:73:6 | 2 | AssignModuloExpr | | operations.rb:74:1:74:11 | ... **= ... | **= | operations.rb:74:1:74:3 | foo | operations.rb:74:9:74:11 | bar | AssignExponentExpr | -| operations.rb:89:3:89:9 | ... += ... | += | operations.rb:89:3:89:4 | @x | operations.rb:89:9:89:9 | 2 | AssignAddExpr | -| operations.rb:92:3:92:10 | ... /= ... | /= | operations.rb:92:3:92:5 | @@y | operations.rb:92:10:92:10 | 4 | AssignDivExpr | -| operations.rb:96:1:96:16 | ... *= ... | *= | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | AssignMulExpr | -| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AssignAddExpr | +| operations.rb:109:3:109:9 | ... += ... | += | operations.rb:109:3:109:4 | @x | operations.rb:109:9:109:9 | 2 | AssignAddExpr | +| operations.rb:112:3:112:10 | ... /= ... | /= | operations.rb:112:3:112:5 | @@y | operations.rb:112:10:112:10 | 4 | AssignDivExpr | +| operations.rb:116:1:116:16 | ... *= ... | *= | operations.rb:116:1:116:11 | $global_var | operations.rb:116:16:116:16 | 6 | AssignMulExpr | +| operations.rb:119:1:119:14 | ... += ... | += | operations.rb:119:1:119:9 | CONSTANT2 | operations.rb:119:14:119:14 | 6 | AssignAddExpr | assignLogicalOperations | operations.rb:77:2:77:8 | ... &&= ... | &&= | operations.rb:77:2:77:2 | x | operations.rb:77:8:77:8 | y | AssignLogicalAndExpr | | operations.rb:78:2:78:8 | ... \|\|= ... | \|\|= | operations.rb:78:2:78:2 | a | operations.rb:78:8:78:8 | b | AssignLogicalOrExpr | -| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | AssignLogicalOrExpr | -| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | AssignLogicalOrExpr | -| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | AssignLogicalOrExpr | -| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr | +| operations.rb:120:1:120:15 | ... \|\|= ... | \|\|= | operations.rb:120:1:120:9 | CONSTANT3 | operations.rb:120:15:120:15 | 7 | AssignLogicalOrExpr | +| operations.rb:121:1:121:25 | ... \|\|= ... | \|\|= | operations.rb:121:1:121:19 | MemberConstant | operations.rb:121:25:121:25 | 8 | AssignLogicalOrExpr | +| operations.rb:122:1:122:31 | ... \|\|= ... | \|\|= | operations.rb:122:1:122:25 | OtherConstant | operations.rb:122:31:122:31 | 7 | AssignLogicalOrExpr | +| operations.rb:123:1:123:17 | ... \|\|= ... | \|\|= | operations.rb:123:1:123:11 | CONSTANT4 | operations.rb:123:17:123:17 | 7 | AssignLogicalOrExpr | assignBitwiseOperations | operations.rb:81:2:81:8 | ... <<= ... | <<= | operations.rb:81:2:81:2 | x | operations.rb:81:8:81:8 | 2 | AssignLShiftExpr | | operations.rb:82:2:82:8 | ... >>= ... | >>= | operations.rb:82:2:82:2 | y | operations.rb:82:8:82:8 | 3 | AssignRShiftExpr | diff --git a/ruby/ql/test/library-tests/ast/operations/binary.expected b/ruby/ql/test/library-tests/ast/operations/binary.expected index 2b632384663..3f29a82a2c4 100644 --- a/ruby/ql/test/library-tests/ast/operations/binary.expected +++ b/ruby/ql/test/library-tests/ast/operations/binary.expected @@ -37,15 +37,17 @@ binaryOperations | operations.rb:83:6:83:7 | ... & ... | & | operations.rb:83:2:83:4 | foo | operations.rb:83:9:83:12 | mask | BitwiseAndExpr | | operations.rb:84:6:84:7 | ... \| ... | \| | operations.rb:84:2:84:4 | bar | operations.rb:84:9:84:12 | 0x01 | BitwiseOrExpr | | operations.rb:85:6:85:7 | ... ^ ... | ^ | operations.rb:85:2:85:4 | baz | operations.rb:85:9:85:11 | qux | BitwiseXorExpr | -| operations.rb:89:6:89:7 | ... + ... | + | operations.rb:89:3:89:4 | @x | operations.rb:89:9:89:9 | 2 | AddExpr | -| operations.rb:92:7:92:8 | ... / ... | / | operations.rb:92:3:92:5 | @@y | operations.rb:92:10:92:10 | 4 | DivExpr | -| operations.rb:96:13:96:14 | ... * ... | * | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | MulExpr | -| operations.rb:99:11:99:12 | ... + ... | + | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AddExpr | -| operations.rb:100:11:100:13 | ... \|\| ... | \|\| | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | LogicalOrExpr | -| operations.rb:101:21:101:23 | ... \|\| ... | \|\| | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | LogicalOrExpr | -| operations.rb:102:27:102:29 | ... \|\| ... | \|\| | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | LogicalOrExpr | -| operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | LogicalOrExpr | -| operations.rb:106:1:107:1 | ... / ... | / | operations.rb:106:1:106:3 | foo | operations.rb:107:1:107:1 | 5 | DivExpr | +| operations.rb:88:7:89:6 | ... && ... | && | operations.rb:88:7:88:7 | a | operations.rb:89:6:89:6 | b | LogicalAndExpr | +| operations.rb:96:10:97:8 | ... && ... | && | operations.rb:96:10:96:10 | a | operations.rb:97:8:97:8 | b | LogicalAndExpr | +| operations.rb:109:6:109:7 | ... + ... | + | operations.rb:109:3:109:4 | @x | operations.rb:109:9:109:9 | 2 | AddExpr | +| operations.rb:112:7:112:8 | ... / ... | / | operations.rb:112:3:112:5 | @@y | operations.rb:112:10:112:10 | 4 | DivExpr | +| operations.rb:116:13:116:14 | ... * ... | * | operations.rb:116:1:116:11 | $global_var | operations.rb:116:16:116:16 | 6 | MulExpr | +| operations.rb:119:11:119:12 | ... + ... | + | operations.rb:119:1:119:9 | CONSTANT2 | operations.rb:119:14:119:14 | 6 | AddExpr | +| operations.rb:120:11:120:13 | ... \|\| ... | \|\| | operations.rb:120:1:120:9 | CONSTANT3 | operations.rb:120:15:120:15 | 7 | LogicalOrExpr | +| operations.rb:121:21:121:23 | ... \|\| ... | \|\| | operations.rb:121:1:121:19 | MemberConstant | operations.rb:121:25:121:25 | 8 | LogicalOrExpr | +| operations.rb:122:27:122:29 | ... \|\| ... | \|\| | operations.rb:122:1:122:25 | OtherConstant | operations.rb:122:31:122:31 | 7 | LogicalOrExpr | +| operations.rb:123:13:123:15 | ... \|\| ... | \|\| | operations.rb:123:1:123:11 | CONSTANT4 | operations.rb:123:17:123:17 | 7 | LogicalOrExpr | +| operations.rb:126:1:127:1 | ... / ... | / | operations.rb:126:1:126:3 | foo | operations.rb:127:1:127:1 | 5 | DivExpr | binaryArithmeticOperations | operations.rb:32:1:32:7 | ... + ... | + | operations.rb:32:1:32:1 | w | operations.rb:32:5:32:7 | 234 | AddExpr | | operations.rb:33:1:33:6 | ... - ... | - | operations.rb:33:1:33:1 | x | operations.rb:33:5:33:6 | 17 | SubExpr | @@ -59,11 +61,11 @@ binaryArithmeticOperations | operations.rb:72:3:72:4 | ... / ... | / | operations.rb:72:1:72:1 | b | operations.rb:72:6:72:6 | 4 | DivExpr | | operations.rb:73:3:73:4 | ... % ... | % | operations.rb:73:1:73:1 | z | operations.rb:73:6:73:6 | 2 | ModuloExpr | | operations.rb:74:5:74:7 | ... ** ... | ** | operations.rb:74:1:74:3 | foo | operations.rb:74:9:74:11 | bar | ExponentExpr | -| operations.rb:89:6:89:7 | ... + ... | + | operations.rb:89:3:89:4 | @x | operations.rb:89:9:89:9 | 2 | AddExpr | -| operations.rb:92:7:92:8 | ... / ... | / | operations.rb:92:3:92:5 | @@y | operations.rb:92:10:92:10 | 4 | DivExpr | -| operations.rb:96:13:96:14 | ... * ... | * | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | MulExpr | -| operations.rb:99:11:99:12 | ... + ... | + | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AddExpr | -| operations.rb:106:1:107:1 | ... / ... | / | operations.rb:106:1:106:3 | foo | operations.rb:107:1:107:1 | 5 | DivExpr | +| operations.rb:109:6:109:7 | ... + ... | + | operations.rb:109:3:109:4 | @x | operations.rb:109:9:109:9 | 2 | AddExpr | +| operations.rb:112:7:112:8 | ... / ... | / | operations.rb:112:3:112:5 | @@y | operations.rb:112:10:112:10 | 4 | DivExpr | +| operations.rb:116:13:116:14 | ... * ... | * | operations.rb:116:1:116:11 | $global_var | operations.rb:116:16:116:16 | 6 | MulExpr | +| operations.rb:119:11:119:12 | ... + ... | + | operations.rb:119:1:119:9 | CONSTANT2 | operations.rb:119:14:119:14 | 6 | AddExpr | +| operations.rb:126:1:127:1 | ... / ... | / | operations.rb:126:1:126:3 | foo | operations.rb:127:1:127:1 | 5 | DivExpr | binaryLogicalOperations | operations.rb:40:1:40:10 | ... && ... | && | operations.rb:40:1:40:3 | foo | operations.rb:40:8:40:10 | bar | LogicalAndExpr | | operations.rb:41:1:41:11 | ... and ... | and | operations.rb:41:1:41:3 | baz | operations.rb:41:9:41:11 | qux | LogicalAndExpr | @@ -71,10 +73,12 @@ binaryLogicalOperations | operations.rb:43:1:43:6 | ... \|\| ... | \|\| | operations.rb:43:1:43:1 | x | operations.rb:43:6:43:6 | y | LogicalOrExpr | | operations.rb:77:4:77:6 | ... && ... | && | operations.rb:77:2:77:2 | x | operations.rb:77:8:77:8 | y | LogicalAndExpr | | operations.rb:78:4:78:6 | ... \|\| ... | \|\| | operations.rb:78:2:78:2 | a | operations.rb:78:8:78:8 | b | LogicalOrExpr | -| operations.rb:100:11:100:13 | ... \|\| ... | \|\| | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | LogicalOrExpr | -| operations.rb:101:21:101:23 | ... \|\| ... | \|\| | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | LogicalOrExpr | -| operations.rb:102:27:102:29 | ... \|\| ... | \|\| | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | LogicalOrExpr | -| operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | LogicalOrExpr | +| operations.rb:88:7:89:6 | ... && ... | && | operations.rb:88:7:88:7 | a | operations.rb:89:6:89:6 | b | LogicalAndExpr | +| operations.rb:96:10:97:8 | ... && ... | && | operations.rb:96:10:96:10 | a | operations.rb:97:8:97:8 | b | LogicalAndExpr | +| operations.rb:120:11:120:13 | ... \|\| ... | \|\| | operations.rb:120:1:120:9 | CONSTANT3 | operations.rb:120:15:120:15 | 7 | LogicalOrExpr | +| operations.rb:121:21:121:23 | ... \|\| ... | \|\| | operations.rb:121:1:121:19 | MemberConstant | operations.rb:121:25:121:25 | 8 | LogicalOrExpr | +| operations.rb:122:27:122:29 | ... \|\| ... | \|\| | operations.rb:122:1:122:25 | OtherConstant | operations.rb:122:31:122:31 | 7 | LogicalOrExpr | +| operations.rb:123:13:123:15 | ... \|\| ... | \|\| | operations.rb:123:1:123:11 | CONSTANT4 | operations.rb:123:17:123:17 | 7 | LogicalOrExpr | binaryBitwiseOperations | operations.rb:46:1:46:6 | ... << ... | << | operations.rb:46:1:46:1 | x | operations.rb:46:6:46:6 | 3 | LShiftExpr | | operations.rb:47:1:47:7 | ... >> ... | >> | operations.rb:47:1:47:1 | y | operations.rb:47:6:47:7 | 16 | RShiftExpr | diff --git a/ruby/ql/test/library-tests/ast/operations/operation.expected b/ruby/ql/test/library-tests/ast/operations/operation.expected index 29abf236af6..7f7833f707d 100644 --- a/ruby/ql/test/library-tests/ast/operations/operation.expected +++ b/ruby/ql/test/library-tests/ast/operations/operation.expected @@ -170,78 +170,84 @@ | operations.rb:85:2:85:11 | ... ^= ... | ^= | operations.rb:85:9:85:11 | qux | AssignBitwiseXorExpr | | operations.rb:85:6:85:7 | ... ^ ... | ^ | operations.rb:85:2:85:4 | baz | BitwiseXorExpr | | operations.rb:85:6:85:7 | ... ^ ... | ^ | operations.rb:85:9:85:11 | qux | BitwiseXorExpr | -| operations.rb:88:3:88:8 | ... = ... | = | operations.rb:88:3:88:4 | @x | AssignExpr | -| operations.rb:88:3:88:8 | ... = ... | = | operations.rb:88:8:88:8 | 1 | AssignExpr | -| operations.rb:89:3:89:9 | ... += ... | += | operations.rb:89:3:89:4 | @x | AssignAddExpr | -| operations.rb:89:3:89:9 | ... += ... | += | operations.rb:89:9:89:9 | 2 | AssignAddExpr | -| operations.rb:89:3:89:9 | ... = ... | = | operations.rb:89:3:89:4 | @x | AssignExpr | -| operations.rb:89:3:89:9 | ... = ... | = | operations.rb:89:6:89:7 | ... + ... | AssignExpr | -| operations.rb:89:6:89:7 | ... + ... | + | operations.rb:89:3:89:4 | @x | AddExpr | -| operations.rb:89:6:89:7 | ... + ... | + | operations.rb:89:9:89:9 | 2 | AddExpr | -| operations.rb:91:3:91:9 | ... = ... | = | operations.rb:91:3:91:5 | @@y | AssignExpr | -| operations.rb:91:3:91:9 | ... = ... | = | operations.rb:91:9:91:9 | 3 | AssignExpr | -| operations.rb:92:3:92:10 | ... /= ... | /= | operations.rb:92:3:92:5 | @@y | AssignDivExpr | -| operations.rb:92:3:92:10 | ... /= ... | /= | operations.rb:92:10:92:10 | 4 | AssignDivExpr | -| operations.rb:92:3:92:10 | ... = ... | = | operations.rb:92:3:92:5 | @@y | AssignExpr | -| operations.rb:92:3:92:10 | ... = ... | = | operations.rb:92:7:92:8 | ... / ... | AssignExpr | -| operations.rb:92:7:92:8 | ... / ... | / | operations.rb:92:3:92:5 | @@y | DivExpr | -| operations.rb:92:7:92:8 | ... / ... | / | operations.rb:92:10:92:10 | 4 | DivExpr | -| operations.rb:95:1:95:15 | ... = ... | = | operations.rb:95:1:95:11 | $global_var | AssignExpr | -| operations.rb:95:1:95:15 | ... = ... | = | operations.rb:95:15:95:15 | 5 | AssignExpr | -| operations.rb:96:1:96:16 | ... *= ... | *= | operations.rb:96:1:96:11 | $global_var | AssignMulExpr | -| operations.rb:96:1:96:16 | ... *= ... | *= | operations.rb:96:16:96:16 | 6 | AssignMulExpr | -| operations.rb:96:1:96:16 | ... = ... | = | operations.rb:96:1:96:11 | $global_var | AssignExpr | -| operations.rb:96:1:96:16 | ... = ... | = | operations.rb:96:13:96:14 | ... * ... | AssignExpr | -| operations.rb:96:13:96:14 | ... * ... | * | operations.rb:96:1:96:11 | $global_var | MulExpr | -| operations.rb:96:13:96:14 | ... * ... | * | operations.rb:96:16:96:16 | 6 | MulExpr | -| operations.rb:98:1:98:13 | ... = ... | = | operations.rb:98:1:98:9 | CONSTANT1 | AssignExpr | -| operations.rb:98:1:98:13 | ... = ... | = | operations.rb:98:13:98:13 | 5 | AssignExpr | -| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:1:99:9 | CONSTANT2 | AssignAddExpr | -| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:14:99:14 | 6 | AssignAddExpr | -| operations.rb:99:1:99:14 | ... = ... | = | operations.rb:99:1:99:9 | CONSTANT2 | AssignExpr | -| operations.rb:99:1:99:14 | ... = ... | = | operations.rb:99:11:99:12 | ... + ... | AssignExpr | -| operations.rb:99:11:99:12 | ... + ... | + | operations.rb:99:1:99:9 | CONSTANT2 | AddExpr | -| operations.rb:99:11:99:12 | ... + ... | + | operations.rb:99:14:99:14 | 6 | AddExpr | -| operations.rb:100:1:100:15 | ... = ... | = | operations.rb:100:1:100:9 | CONSTANT3 | AssignExpr | -| operations.rb:100:1:100:15 | ... = ... | = | operations.rb:100:11:100:13 | ... \|\| ... | AssignExpr | -| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:1:100:9 | CONSTANT3 | AssignLogicalOrExpr | -| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:15:100:15 | 7 | AssignLogicalOrExpr | -| operations.rb:100:11:100:13 | ... \|\| ... | \|\| | operations.rb:100:1:100:9 | CONSTANT3 | LogicalOrExpr | -| operations.rb:100:11:100:13 | ... \|\| ... | \|\| | operations.rb:100:15:100:15 | 7 | LogicalOrExpr | -| operations.rb:101:1:101:3 | ... = ... | = | operations.rb:101:1:101:3 | Foo | AssignExpr | -| operations.rb:101:1:101:3 | ... = ... | = | operations.rb:101:1:101:3 | __synth__0 | AssignExpr | -| operations.rb:101:1:101:25 | ... = ... | = | operations.rb:101:1:101:19 | MemberConstant | AssignExpr | -| operations.rb:101:1:101:25 | ... = ... | = | operations.rb:101:21:101:23 | ... \|\| ... | AssignExpr | -| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:1:101:19 | MemberConstant | AssignLogicalOrExpr | -| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:25:101:25 | 8 | AssignLogicalOrExpr | -| operations.rb:101:21:101:23 | ... \|\| ... | \|\| | operations.rb:101:1:101:19 | MemberConstant | LogicalOrExpr | -| operations.rb:101:21:101:23 | ... \|\| ... | \|\| | operations.rb:101:25:101:25 | 8 | LogicalOrExpr | -| operations.rb:102:1:102:10 | ... = ... | = | operations.rb:102:1:102:10 | __synth__0 | AssignExpr | -| operations.rb:102:1:102:10 | ... = ... | = | operations.rb:102:1:102:10 | call to bar | AssignExpr | -| operations.rb:102:1:102:31 | ... = ... | = | operations.rb:102:1:102:25 | OtherConstant | AssignExpr | -| operations.rb:102:1:102:31 | ... = ... | = | operations.rb:102:27:102:29 | ... \|\| ... | AssignExpr | -| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:1:102:25 | OtherConstant | AssignLogicalOrExpr | -| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:31:102:31 | 7 | AssignLogicalOrExpr | -| operations.rb:102:27:102:29 | ... \|\| ... | \|\| | operations.rb:102:1:102:25 | OtherConstant | LogicalOrExpr | -| operations.rb:102:27:102:29 | ... \|\| ... | \|\| | operations.rb:102:31:102:31 | 7 | LogicalOrExpr | -| operations.rb:103:1:103:17 | ... = ... | = | operations.rb:103:1:103:11 | CONSTANT4 | AssignExpr | -| operations.rb:103:1:103:17 | ... = ... | = | operations.rb:103:13:103:15 | ... \|\| ... | AssignExpr | -| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:1:103:11 | CONSTANT4 | AssignLogicalOrExpr | -| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr | -| operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:1:103:11 | CONSTANT4 | LogicalOrExpr | -| operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:17:103:17 | 7 | LogicalOrExpr | -| operations.rb:104:1:104:3 | ... = ... | = | operations.rb:104:1:104:3 | FOO | AssignExpr | -| operations.rb:104:1:104:3 | ... = ... | = | operations.rb:104:1:104:3 | call to [] | AssignExpr | -| operations.rb:104:1:104:32 | ... = ... | = | operations.rb:104:1:104:20 | (..., ...) | AssignExpr | -| operations.rb:104:1:104:32 | ... = ... | = | operations.rb:104:24:104:32 | [...] | AssignExpr | -| operations.rb:104:6:104:10 | ... = ... | = | operations.rb:104:6:104:10 | BAR | AssignExpr | -| operations.rb:104:6:104:10 | ... = ... | = | operations.rb:104:6:104:10 | call to [] | AssignExpr | -| operations.rb:104:13:104:15 | ... = ... | = | operations.rb:104:13:104:15 | __synth__2 | AssignExpr | -| operations.rb:104:13:104:15 | ... = ... | = | operations.rb:104:13:104:15 | foo | AssignExpr | -| operations.rb:104:13:104:20 | ... = ... | = | operations.rb:104:13:104:20 | FOO | AssignExpr | -| operations.rb:104:13:104:20 | ... = ... | = | operations.rb:104:13:104:20 | call to [] | AssignExpr | -| operations.rb:104:24:104:32 | * ... | * | operations.rb:104:24:104:32 | [...] | SplatExpr | -| operations.rb:104:24:104:32 | ... = ... | = | operations.rb:104:24:104:32 | * ... | AssignExpr | -| operations.rb:104:24:104:32 | ... = ... | = | operations.rb:104:24:104:32 | __synth__3 | AssignExpr | -| operations.rb:106:1:107:1 | ... / ... | / | operations.rb:106:1:106:3 | foo | DivExpr | -| operations.rb:106:1:107:1 | ... / ... | / | operations.rb:107:1:107:1 | 5 | DivExpr | +| operations.rb:88:1:89:6 | ... = ... | = | operations.rb:88:1:88:3 | foo | AssignExpr | +| operations.rb:88:1:89:6 | ... = ... | = | operations.rb:88:7:89:6 | ... && ... | AssignExpr | +| operations.rb:88:7:89:6 | ... && ... | && | operations.rb:88:7:88:7 | a | LogicalAndExpr | +| operations.rb:88:7:89:6 | ... && ... | && | operations.rb:89:6:89:6 | b | LogicalAndExpr | +| operations.rb:96:10:97:8 | ... && ... | && | operations.rb:96:10:96:10 | a | LogicalAndExpr | +| operations.rb:96:10:97:8 | ... && ... | && | operations.rb:97:8:97:8 | b | LogicalAndExpr | +| operations.rb:108:3:108:8 | ... = ... | = | operations.rb:108:3:108:4 | @x | AssignExpr | +| operations.rb:108:3:108:8 | ... = ... | = | operations.rb:108:8:108:8 | 1 | AssignExpr | +| operations.rb:109:3:109:9 | ... += ... | += | operations.rb:109:3:109:4 | @x | AssignAddExpr | +| operations.rb:109:3:109:9 | ... += ... | += | operations.rb:109:9:109:9 | 2 | AssignAddExpr | +| operations.rb:109:3:109:9 | ... = ... | = | operations.rb:109:3:109:4 | @x | AssignExpr | +| operations.rb:109:3:109:9 | ... = ... | = | operations.rb:109:6:109:7 | ... + ... | AssignExpr | +| operations.rb:109:6:109:7 | ... + ... | + | operations.rb:109:3:109:4 | @x | AddExpr | +| operations.rb:109:6:109:7 | ... + ... | + | operations.rb:109:9:109:9 | 2 | AddExpr | +| operations.rb:111:3:111:9 | ... = ... | = | operations.rb:111:3:111:5 | @@y | AssignExpr | +| operations.rb:111:3:111:9 | ... = ... | = | operations.rb:111:9:111:9 | 3 | AssignExpr | +| operations.rb:112:3:112:10 | ... /= ... | /= | operations.rb:112:3:112:5 | @@y | AssignDivExpr | +| operations.rb:112:3:112:10 | ... /= ... | /= | operations.rb:112:10:112:10 | 4 | AssignDivExpr | +| operations.rb:112:3:112:10 | ... = ... | = | operations.rb:112:3:112:5 | @@y | AssignExpr | +| operations.rb:112:3:112:10 | ... = ... | = | operations.rb:112:7:112:8 | ... / ... | AssignExpr | +| operations.rb:112:7:112:8 | ... / ... | / | operations.rb:112:3:112:5 | @@y | DivExpr | +| operations.rb:112:7:112:8 | ... / ... | / | operations.rb:112:10:112:10 | 4 | DivExpr | +| operations.rb:115:1:115:15 | ... = ... | = | operations.rb:115:1:115:11 | $global_var | AssignExpr | +| operations.rb:115:1:115:15 | ... = ... | = | operations.rb:115:15:115:15 | 5 | AssignExpr | +| operations.rb:116:1:116:16 | ... *= ... | *= | operations.rb:116:1:116:11 | $global_var | AssignMulExpr | +| operations.rb:116:1:116:16 | ... *= ... | *= | operations.rb:116:16:116:16 | 6 | AssignMulExpr | +| operations.rb:116:1:116:16 | ... = ... | = | operations.rb:116:1:116:11 | $global_var | AssignExpr | +| operations.rb:116:1:116:16 | ... = ... | = | operations.rb:116:13:116:14 | ... * ... | AssignExpr | +| operations.rb:116:13:116:14 | ... * ... | * | operations.rb:116:1:116:11 | $global_var | MulExpr | +| operations.rb:116:13:116:14 | ... * ... | * | operations.rb:116:16:116:16 | 6 | MulExpr | +| operations.rb:118:1:118:13 | ... = ... | = | operations.rb:118:1:118:9 | CONSTANT1 | AssignExpr | +| operations.rb:118:1:118:13 | ... = ... | = | operations.rb:118:13:118:13 | 5 | AssignExpr | +| operations.rb:119:1:119:14 | ... += ... | += | operations.rb:119:1:119:9 | CONSTANT2 | AssignAddExpr | +| operations.rb:119:1:119:14 | ... += ... | += | operations.rb:119:14:119:14 | 6 | AssignAddExpr | +| operations.rb:119:1:119:14 | ... = ... | = | operations.rb:119:1:119:9 | CONSTANT2 | AssignExpr | +| operations.rb:119:1:119:14 | ... = ... | = | operations.rb:119:11:119:12 | ... + ... | AssignExpr | +| operations.rb:119:11:119:12 | ... + ... | + | operations.rb:119:1:119:9 | CONSTANT2 | AddExpr | +| operations.rb:119:11:119:12 | ... + ... | + | operations.rb:119:14:119:14 | 6 | AddExpr | +| operations.rb:120:1:120:15 | ... = ... | = | operations.rb:120:1:120:9 | CONSTANT3 | AssignExpr | +| operations.rb:120:1:120:15 | ... = ... | = | operations.rb:120:11:120:13 | ... \|\| ... | AssignExpr | +| operations.rb:120:1:120:15 | ... \|\|= ... | \|\|= | operations.rb:120:1:120:9 | CONSTANT3 | AssignLogicalOrExpr | +| operations.rb:120:1:120:15 | ... \|\|= ... | \|\|= | operations.rb:120:15:120:15 | 7 | AssignLogicalOrExpr | +| operations.rb:120:11:120:13 | ... \|\| ... | \|\| | operations.rb:120:1:120:9 | CONSTANT3 | LogicalOrExpr | +| operations.rb:120:11:120:13 | ... \|\| ... | \|\| | operations.rb:120:15:120:15 | 7 | LogicalOrExpr | +| operations.rb:121:1:121:3 | ... = ... | = | operations.rb:121:1:121:3 | Foo | AssignExpr | +| operations.rb:121:1:121:3 | ... = ... | = | operations.rb:121:1:121:3 | __synth__0 | AssignExpr | +| operations.rb:121:1:121:25 | ... = ... | = | operations.rb:121:1:121:19 | MemberConstant | AssignExpr | +| operations.rb:121:1:121:25 | ... = ... | = | operations.rb:121:21:121:23 | ... \|\| ... | AssignExpr | +| operations.rb:121:1:121:25 | ... \|\|= ... | \|\|= | operations.rb:121:1:121:19 | MemberConstant | AssignLogicalOrExpr | +| operations.rb:121:1:121:25 | ... \|\|= ... | \|\|= | operations.rb:121:25:121:25 | 8 | AssignLogicalOrExpr | +| operations.rb:121:21:121:23 | ... \|\| ... | \|\| | operations.rb:121:1:121:19 | MemberConstant | LogicalOrExpr | +| operations.rb:121:21:121:23 | ... \|\| ... | \|\| | operations.rb:121:25:121:25 | 8 | LogicalOrExpr | +| operations.rb:122:1:122:10 | ... = ... | = | operations.rb:122:1:122:10 | __synth__0 | AssignExpr | +| operations.rb:122:1:122:10 | ... = ... | = | operations.rb:122:1:122:10 | call to bar | AssignExpr | +| operations.rb:122:1:122:31 | ... = ... | = | operations.rb:122:1:122:25 | OtherConstant | AssignExpr | +| operations.rb:122:1:122:31 | ... = ... | = | operations.rb:122:27:122:29 | ... \|\| ... | AssignExpr | +| operations.rb:122:1:122:31 | ... \|\|= ... | \|\|= | operations.rb:122:1:122:25 | OtherConstant | AssignLogicalOrExpr | +| operations.rb:122:1:122:31 | ... \|\|= ... | \|\|= | operations.rb:122:31:122:31 | 7 | AssignLogicalOrExpr | +| operations.rb:122:27:122:29 | ... \|\| ... | \|\| | operations.rb:122:1:122:25 | OtherConstant | LogicalOrExpr | +| operations.rb:122:27:122:29 | ... \|\| ... | \|\| | operations.rb:122:31:122:31 | 7 | LogicalOrExpr | +| operations.rb:123:1:123:17 | ... = ... | = | operations.rb:123:1:123:11 | CONSTANT4 | AssignExpr | +| operations.rb:123:1:123:17 | ... = ... | = | operations.rb:123:13:123:15 | ... \|\| ... | AssignExpr | +| operations.rb:123:1:123:17 | ... \|\|= ... | \|\|= | operations.rb:123:1:123:11 | CONSTANT4 | AssignLogicalOrExpr | +| operations.rb:123:1:123:17 | ... \|\|= ... | \|\|= | operations.rb:123:17:123:17 | 7 | AssignLogicalOrExpr | +| operations.rb:123:13:123:15 | ... \|\| ... | \|\| | operations.rb:123:1:123:11 | CONSTANT4 | LogicalOrExpr | +| operations.rb:123:13:123:15 | ... \|\| ... | \|\| | operations.rb:123:17:123:17 | 7 | LogicalOrExpr | +| operations.rb:124:1:124:3 | ... = ... | = | operations.rb:124:1:124:3 | FOO | AssignExpr | +| operations.rb:124:1:124:3 | ... = ... | = | operations.rb:124:1:124:3 | call to [] | AssignExpr | +| operations.rb:124:1:124:32 | ... = ... | = | operations.rb:124:1:124:20 | (..., ...) | AssignExpr | +| operations.rb:124:1:124:32 | ... = ... | = | operations.rb:124:24:124:32 | [...] | AssignExpr | +| operations.rb:124:6:124:10 | ... = ... | = | operations.rb:124:6:124:10 | BAR | AssignExpr | +| operations.rb:124:6:124:10 | ... = ... | = | operations.rb:124:6:124:10 | call to [] | AssignExpr | +| operations.rb:124:13:124:15 | ... = ... | = | operations.rb:124:13:124:15 | __synth__2 | AssignExpr | +| operations.rb:124:13:124:15 | ... = ... | = | operations.rb:124:13:124:15 | foo | AssignExpr | +| operations.rb:124:13:124:20 | ... = ... | = | operations.rb:124:13:124:20 | FOO | AssignExpr | +| operations.rb:124:13:124:20 | ... = ... | = | operations.rb:124:13:124:20 | call to [] | AssignExpr | +| operations.rb:124:24:124:32 | * ... | * | operations.rb:124:24:124:32 | [...] | SplatExpr | +| operations.rb:124:24:124:32 | ... = ... | = | operations.rb:124:24:124:32 | * ... | AssignExpr | +| operations.rb:124:24:124:32 | ... = ... | = | operations.rb:124:24:124:32 | __synth__3 | AssignExpr | +| operations.rb:126:1:127:1 | ... / ... | / | operations.rb:126:1:126:3 | foo | DivExpr | +| operations.rb:126:1:127:1 | ... / ... | / | operations.rb:127:1:127:1 | 5 | DivExpr | diff --git a/ruby/ql/test/library-tests/ast/operations/operations.rb b/ruby/ql/test/library-tests/ast/operations/operations.rb index cee2acedc70..93ddc39d638 100644 --- a/ruby/ql/test/library-tests/ast/operations/operations.rb +++ b/ruby/ql/test/library-tests/ast/operations/operations.rb @@ -84,6 +84,26 @@ foo **= bar bar |= 0x01 baz ^= qux +# Assignments with operation at start of line +foo = a + && b +# NOTE: This is not parsed correctly, `|| b` is dropped +# bar = a +# || b + +# Return with `&&` at start of line +def foo(a, b) + return a + && b +end + +# Return with `||` at start of line +# NOTE: This is not parsed correctly, `|| b` is dropped +# def bar(a, b) +# return a +# || b +# end + class X @x = 1 @x += 2 diff --git a/ruby/ql/test/library-tests/ast/operations/unary.expected b/ruby/ql/test/library-tests/ast/operations/unary.expected index 43c23fff031..2ea6dcf0768 100644 --- a/ruby/ql/test/library-tests/ast/operations/unary.expected +++ b/ruby/ql/test/library-tests/ast/operations/unary.expected @@ -7,7 +7,7 @@ unaryOperations | operations.rb:28:1:28:12 | defined? ... | defined? | operations.rb:28:10:28:12 | foo | DefinedExpr | | operations.rb:29:20:29:23 | * ... | * | operations.rb:29:21:29:23 | [...] | SplatExpr | | operations.rb:29:31:29:42 | ** ... | ** | operations.rb:29:33:29:42 | {...} | HashSplatExpr | -| operations.rb:104:24:104:32 | * ... | * | operations.rb:104:24:104:32 | [...] | SplatExpr | +| operations.rb:124:24:124:32 | * ... | * | operations.rb:124:24:124:32 | [...] | SplatExpr | unaryLogicalOperations | operations.rb:23:1:23:2 | ! ... | ! | operations.rb:23:2:23:2 | a | NotExpr | | operations.rb:24:1:24:5 | not ... | not | operations.rb:24:5:24:5 | b | NotExpr | diff --git a/rust/ql/lib/CHANGELOG.md b/rust/ql/lib/CHANGELOG.md index b913efd02f0..3887b67b4df 100644 --- a/rust/ql/lib/CHANGELOG.md +++ b/rust/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.6 + +No user-facing changes. + ## 0.2.5 ### Minor Analysis Improvements diff --git a/rust/ql/lib/change-notes/released/0.2.6.md b/rust/ql/lib/change-notes/released/0.2.6.md new file mode 100644 index 00000000000..edaefe75481 --- /dev/null +++ b/rust/ql/lib/change-notes/released/0.2.6.md @@ -0,0 +1,3 @@ +## 0.2.6 + +No user-facing changes. diff --git a/rust/ql/lib/codeql-pack.release.yml b/rust/ql/lib/codeql-pack.release.yml index 211454ed306..248dd0f4594 100644 --- a/rust/ql/lib/codeql-pack.release.yml +++ b/rust/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.2.5 +lastReleaseVersion: 0.2.6 diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 432608f6f9d..76c15485bb9 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -107,7 +107,7 @@ class SuccessorKind extends TSuccessorKind { } pragma[nomagic] -private ItemNode getAChildSuccessor(ItemNode item, string name, SuccessorKind kind) { +private ItemNode getAChildSuccessor0(ItemNode item, string name, SuccessorKind kind) { item = result.getImmediateParent() and name = result.getName() and // Associated items in `impl` and `trait` blocks are handled elsewhere @@ -116,7 +116,7 @@ private ItemNode getAChildSuccessor(ItemNode item, string name, SuccessorKind ki if result instanceof TypeParam then kind.isInternal() else - if result.isPublic() + if result.isPublic() or item instanceof SourceFile then kind.isBoth() else kind.isInternal() or @@ -130,6 +130,41 @@ private ItemNode getAChildSuccessor(ItemNode item, string name, SuccessorKind ki result = item } +pragma[nomagic] +private NamedItemNode getANamedNonModuleChildSuccessor( + ItemNode item, string name, Namespace ns, int startline, int startcolumn, int endline, + int endcolumn +) { + result.getLocation().hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and + result = getAChildSuccessor0(item, name, _) and + ns = result.getNamespace() and + not result instanceof ModuleItemNode +} + +pragma[nomagic] +private ItemNode getAChildSuccessor(ItemNode item, string name, SuccessorKind kind) { + result = getAChildSuccessor0(item, name, kind) and + // In valid Rust code, there cannot be multiple children with the same name and namespace, + // but to safeguard against combinatorial explosions in invalid code, we always pick the + // last child, except for modules, where we take the union. + ( + not result instanceof NamedItemNode + or + result instanceof ModuleItemNode + or + exists(Namespace ns | + result = + max(NamedItemNode i, int startline, int startcolumn, int endline, int endcolumn | + i = + getANamedNonModuleChildSuccessor(item, name, ns, startline, startcolumn, endline, + endcolumn) + | + i order by startline, startcolumn, endline, endcolumn + ) + ) + ) +} + private module UseOption = Option; private class UseOption = UseOption::Option; @@ -288,10 +323,6 @@ abstract class ItemNode extends Locatable { cached ItemNode getASuccessor(string name, SuccessorKind kind, UseOption useOpt) { Stages::PathResolutionStage::ref() and - sourceFileEdge(this, name, result) and - kind.isBoth() and - useOpt.isNone() - or result = getAChildSuccessor(this, name, kind) and useOpt.isNone() or @@ -471,6 +502,8 @@ abstract class ItemNode extends Locatable { Location getLocation() { result = super.getLocation() } } +abstract class NamedItemNode extends ItemNode { } + abstract class TypeItemNode extends ItemNode { } /** A module or a source file. */ @@ -509,7 +542,7 @@ private class SourceFileItemNode extends ModuleLikeNode instanceof SourceFile { override string getCanonicalPath(Crate c) { none() } } -class CrateItemNode extends ItemNode instanceof Crate { +class CrateItemNode extends NamedItemNode instanceof Crate { /** * Gets the source file that defines this crate. */ @@ -565,7 +598,7 @@ class CrateItemNode extends ItemNode instanceof Crate { override string getCanonicalPath(Crate c) { c = this and result = Crate.super.getName() } } -class ExternCrateItemNode extends ItemNode instanceof ExternCrate { +class ExternCrateItemNode extends NamedItemNode instanceof ExternCrate { override string getName() { result = super.getRename().getName().getText() or @@ -573,7 +606,7 @@ class ExternCrateItemNode extends ItemNode instanceof ExternCrate { result = super.getIdentifier().getText() } - override Namespace getNamespace() { none() } + override Namespace getNamespace() { result.isType() } override Visibility getVisibility() { result = ExternCrate.super.getVisibility() } @@ -587,7 +620,7 @@ class ExternCrateItemNode extends ItemNode instanceof ExternCrate { } /** An item that can occur in a trait or an `impl` block. */ -abstract private class AssocItemNode extends ItemNode instanceof AssocItem { +abstract private class AssocItemNode extends NamedItemNode instanceof AssocItem { /** Holds if this associated item has an implementation. */ abstract predicate hasImplementation(); @@ -626,7 +659,7 @@ private class ConstItemNode extends AssocItemNode instanceof Const { override TypeParam getTypeParam(int i) { none() } } -private class TypeItemTypeItemNode extends TypeItemNode instanceof TypeItem { +private class TypeItemTypeItemNode extends NamedItemNode, TypeItemNode instanceof TypeItem { override string getName() { result = TypeItem.super.getName().getText() } override Namespace getNamespace() { result.isType() } @@ -659,7 +692,7 @@ private class TypeItemTypeItemNode extends TypeItemNode instanceof TypeItem { } /** An item that can be referenced with arguments. */ -abstract class ParameterizableItemNode extends ItemNode { +abstract class ParameterizableItemNode extends NamedItemNode { /** Gets the arity this item. */ abstract int getArity(); } @@ -911,7 +944,7 @@ private class ImplTraitTypeReprItemNodeImpl extends ImplTraitTypeReprItemNode { ItemNode resolveABoundCand() { result = resolvePathCand(this.getABoundPath()) } } -private class ModuleItemNode extends ModuleLikeNode instanceof Module { +private class ModuleItemNode extends NamedItemNode, ModuleLikeNode instanceof Module { override string getName() { result = Module.super.getName().getText() } override Namespace getNamespace() { result.isType() } @@ -929,7 +962,7 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module { ( exists(SourceFile f | fileImport(this, f) and - sourceFileEdge(f, _, child) + child = getAChildSuccessor(f, _, _) ) or this = child.getImmediateParent() @@ -1001,7 +1034,7 @@ private class StructItemNode extends TypeItemTypeItemNode, ParameterizableItemNo } } -final class TraitItemNode extends ImplOrTraitItemNode, TypeItemNode instanceof Trait { +final class TraitItemNode extends ImplOrTraitItemNode, NamedItemNode, TypeItemNode instanceof Trait { pragma[nomagic] Path getABoundPath() { result = super.getATypeBound().getTypeRepr().(PathTypeRepr).getPath() } @@ -1126,7 +1159,7 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr { pragma[nomagic] private Path getWherePredPath(WherePred wp) { result = wp.getTypeRepr().(PathTypeRepr).getPath() } -final class TypeParamItemNode extends TypeItemNode instanceof TypeParam { +final class TypeParamItemNode extends NamedItemNode, TypeItemNode instanceof TypeParam { /** Gets a where predicate for this type parameter, if any */ pragma[nomagic] private WherePred getAWherePred() { @@ -1214,7 +1247,7 @@ final private class TypeParamItemNodeImpl extends TypeParamItemNode instanceof T ItemNode resolveABoundCand() { result = resolvePathCand(this.getABoundPathCand()) } } -abstract private class MacroItemNode extends ItemNode { +abstract private class MacroItemNode extends NamedItemNode { override Namespace getNamespace() { result.isMacro() } override TypeParam getTypeParam(int i) { none() } @@ -1256,12 +1289,6 @@ private class MacroDefItemNode extends MacroItemNode instanceof MacroDef { override Attr getAnAttr() { result = MacroDef.super.getAnAttr() } } -/** Holds if `item` has the name `name` and is a top-level item inside `f`. */ -private predicate sourceFileEdge(SourceFile f, string name, ItemNode item) { - item = f.(ItemNode).getADescendant() and - name = item.getName() -} - /** Holds if `f` is available as `mod name;` inside `folder`. */ pragma[nomagic] private predicate fileModule(SourceFile f, string name, Folder folder) { diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll index aeb186c0cdc..74d8385bdf2 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll @@ -419,14 +419,21 @@ module ArgsAreInstantiationsOf { private module ArgIsInstantiationOfToIndex = ArgIsInstantiationOf; + pragma[nomagic] + private predicate argIsInstantiationOf( + Input::Call call, FunctionPosition pos, ImplOrTraitItemNode i, Function f, int rnk + ) { + ArgIsInstantiationOfToIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and + toCheckRanked(i, f, _, pos, rnk) + } + pragma[nomagic] private predicate argsAreInstantiationsOfToIndex( Input::Call call, ImplOrTraitItemNode i, Function f, int rnk ) { exists(FunctionPosition pos | - ArgIsInstantiationOfToIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and - call.hasTargetCand(i, f) and - toCheckRanked(i, f, _, pos, rnk) + argIsInstantiationOf(call, pos, i, f, rnk) and + call.hasTargetCand(i, f) | rnk = 0 or diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index ed365d60c46..a4812ad0878 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -2683,6 +2683,21 @@ private predicate inferMethodCallType = * "calls" to tuple variants and tuple structs. */ private module NonMethodResolution { + pragma[nomagic] + private predicate traitFunctionResolutionDependsOnArgument0( + TraitItemNode trait, NonMethodFunction traitFunction, FunctionPosition pos, ImplItemNode impl, + NonMethodFunction implFunction, TypePath path, TypeParameter traitTp + ) { + implFunction = impl.getAnAssocItem() and + implFunction.implements(traitFunction) and + FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos, path, traitTp) and + ( + traitTp = TSelfTypeParameter(trait) + or + FunctionOverloading::functionResolutionDependsOnArgument(impl, implFunction, traitTp, pos) + ) + } + /** * Holds if resolving the function `implFunction` in `impl` requires inspecting * the type of applied _arguments_ or possibly knowing the return type. @@ -2699,13 +2714,44 @@ private module NonMethodResolution { TraitItemNode trait, NonMethodFunction traitFunction, FunctionPosition pos, ImplItemNode impl, NonMethodFunction implFunction, TypePath path, TypeParameter traitTp ) { - implFunction = impl.getAnAssocItem() and - implFunction.implements(traitFunction) and - FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos, path, traitTp) and - ( - traitTp = TSelfTypeParameter(trait) + traitFunctionResolutionDependsOnArgument0(trait, traitFunction, pos, impl, implFunction, path, + traitTp) and + // Exclude functions where we cannot resolve all relevant type mentions; this allows + // for blanket implementations to be applied in those cases + forall(TypeParameter traitTp0 | + traitFunctionResolutionDependsOnArgument0(trait, traitFunction, _, impl, implFunction, _, + traitTp0) + | + exists(FunctionPosition pos0, TypePath path0 | + traitFunctionResolutionDependsOnArgument0(trait, traitFunction, pos0, impl, implFunction, + path0, traitTp0) and + exists(getAssocFunctionTypeInclNonMethodSelfAt(implFunction, impl, pos0, path0)) + ) + ) + } + + /** + * Holds if `f` inside `i` either implements trait function `traitFunction` inside `trait` + * or is equal to `traitFunction`, and the type of `f` at `pos` and `path` is `t`, which + * corresponds to the `Self` type parameter of `trait`. + */ + pragma[nomagic] + private predicate traitFunctionHasSelfType( + TraitItemNode trait, NonMethodFunction traitFunction, FunctionPosition pos, TypePath path, + Type t, ImplOrTraitItemNode i, NonMethodFunction f + ) { + exists(ImplItemNode impl, NonMethodFunction implFunction, AssocFunctionType aft | + traitFunctionResolutionDependsOnArgument(trait, traitFunction, pos, impl, implFunction, path, + TSelfTypeParameter(trait)) and + aft.appliesTo(f, i, pos) and + t = aft.getTypeAt(path) + | + i = trait and + f = traitFunction or - FunctionOverloading::functionResolutionDependsOnArgument(impl, implFunction, traitTp, pos) + i = impl and + f = implFunction and + not BlanketImplementation::isBlanketLike(i, _, _) ) } @@ -2862,10 +2908,25 @@ private module NonMethodResolution { predicate hasNoCompatibleNonBlanketTarget() { this.resolveCallTargetBlanketLikeCand(_, _, _, _) and not exists(this.resolveCallTargetViaPathResolution()) and - forall(ImplOrTraitItemNode i, Function f | - this.(NonMethodArgsAreInstantiationsOfNonBlanketInput::Call).hasTargetCand(i, f) - | + forall(ImplOrTraitItemNode i, Function f | f = this.resolveCallTargetNonBlanketCand(i) | NonMethodArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f) + ) and + ( + not this.hasTraitResolved(_, _) + or + exists( + TraitItemNode trait, NonMethodFunction resolved, FunctionPosition pos, TypePath path, + Type t + | + this.(NonMethodArgsAreInstantiationsOfNonBlanketInput::Call) + .hasTraitResolvedSelfType(trait, resolved, pos, path, t) + | + forall(ImplOrTraitItemNode i, Function f | + traitFunctionHasSelfType(trait, resolved, pos, path, t, i, f) + | + NonMethodArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f) + ) + ) ) } @@ -3008,29 +3069,30 @@ private module NonMethodResolution { result = getArgType(this, pos, path, _) } + /** + * Holds if this call is of the form `Trait::function(args)`, and the type at `pos` and + * `path` matches the `Self` type parameter of `Trait`. + */ + pragma[nomagic] + predicate hasTraitResolvedSelfType( + TraitItemNode trait, NonMethodFunction function, FunctionPosition pos, TypePath path, Type t + ) { + this.hasTraitResolved(trait, function) and + FunctionOverloading::traitTypeParameterOccurrence(trait, function, _, pos, path, + TSelfTypeParameter(trait)) and + t = substituteLookupTraits(this.getArgType(pos, path)) and + t != TUnknownType() + } + predicate hasTargetCand(ImplOrTraitItemNode i, Function f) { f = this.resolveCallTargetNonBlanketCand(i) or - exists(TraitItemNode trait, NonMethodFunction resolved, ImplItemNode i1, Function f1 | - this.hasTraitResolved(trait, resolved) and - traitFunctionResolutionDependsOnArgument(trait, resolved, _, i1, f1, _, _) and - not BlanketImplementation::isBlanketLike(i, _, _) + exists( + TraitItemNode trait, NonMethodFunction resolved, FunctionPosition pos, TypePath path, + Type t | - f = resolved and - i = trait - or - f = f1 and - i = i1 and - // Exclude functions where we cannot resolve all relevant type mentions; this allows - // for blanket implementations to be applied in those cases - forall(TypeParameter traitTp | - traitFunctionResolutionDependsOnArgument(trait, resolved, _, i1, f1, _, traitTp) - | - exists(FunctionPosition pos, TypePath path | - traitFunctionResolutionDependsOnArgument(trait, resolved, pos, i1, f1, path, traitTp) and - exists(getAssocFunctionTypeInclNonMethodSelfAt(f, i, pos, path)) - ) - ) + this.hasTraitResolvedSelfType(trait, resolved, pos, path, t) and + traitFunctionHasSelfType(trait, resolved, pos, path, t, i, f) ) } } diff --git a/rust/ql/lib/qlpack.yml b/rust/ql/lib/qlpack.yml index d87089914d3..f7428ef1087 100644 --- a/rust/ql/lib/qlpack.yml +++ b/rust/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/rust-all -version: 0.2.6-dev +version: 0.2.7-dev groups: rust extractor: rust dbscheme: rust.dbscheme diff --git a/rust/ql/src/CHANGELOG.md b/rust/ql/src/CHANGELOG.md index fe96ab5baad..72f10e760fc 100644 --- a/rust/ql/src/CHANGELOG.md +++ b/rust/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.27 + +No user-facing changes. + ## 0.1.26 No user-facing changes. diff --git a/rust/ql/src/change-notes/released/0.1.27.md b/rust/ql/src/change-notes/released/0.1.27.md new file mode 100644 index 00000000000..3e409381bd9 --- /dev/null +++ b/rust/ql/src/change-notes/released/0.1.27.md @@ -0,0 +1,3 @@ +## 0.1.27 + +No user-facing changes. diff --git a/rust/ql/src/codeql-pack.release.yml b/rust/ql/src/codeql-pack.release.yml index e2396c0532f..35535ba43d5 100644 --- a/rust/ql/src/codeql-pack.release.yml +++ b/rust/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.1.26 +lastReleaseVersion: 0.1.27 diff --git a/rust/ql/src/qlpack.yml b/rust/ql/src/qlpack.yml index 850f67e18a8..21011bd93d5 100644 --- a/rust/ql/src/qlpack.yml +++ b/rust/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/rust-queries -version: 0.1.27-dev +version: 0.1.28-dev groups: - rust - queries diff --git a/rust/ql/test/library-tests/path-resolution/invalid/main.rs b/rust/ql/test/library-tests/path-resolution/invalid/main.rs new file mode 100644 index 00000000000..b58fcb2d934 --- /dev/null +++ b/rust/ql/test/library-tests/path-resolution/invalid/main.rs @@ -0,0 +1,6 @@ +// The code in this file is not valid Rust code + +struct A; // A1 +struct A; // A2 + +fn f(x: A) {} // $ item=A2 (the latter occurence takes precedence) diff --git a/rust/ql/test/library-tests/path-resolution/invalid/options.yml b/rust/ql/test/library-tests/path-resolution/invalid/options.yml new file mode 100644 index 00000000000..cf148dd35f8 --- /dev/null +++ b/rust/ql/test/library-tests/path-resolution/invalid/options.yml @@ -0,0 +1 @@ +qltest_cargo_check: false diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.expected b/rust/ql/test/library-tests/path-resolution/path-resolution.expected index 153d80db4cc..e85bb7876da 100644 --- a/rust/ql/test/library-tests/path-resolution/path-resolution.expected +++ b/rust/ql/test/library-tests/path-resolution/path-resolution.expected @@ -51,6 +51,7 @@ mod | my/nested.rs:1:1:17:1 | mod nested1 | | my/nested.rs:2:5:11:5 | mod nested2 | resolvePath +| invalid/main.rs:6:9:6:9 | A | invalid/main.rs:3:11:4:9 | struct A | | main.rs:4:8:4:9 | my | main.rs:1:1:1:7 | mod my | | main.rs:4:14:4:17 | self | main.rs:1:1:1:7 | mod my | | main.rs:6:5:6:6 | my | main.rs:1:1:1:7 | mod my | diff --git a/shared/concepts/CHANGELOG.md b/shared/concepts/CHANGELOG.md index 29dba07c365..933fc5e7cd9 100644 --- a/shared/concepts/CHANGELOG.md +++ b/shared/concepts/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.16 + +No user-facing changes. + ## 0.0.15 No user-facing changes. diff --git a/shared/concepts/change-notes/released/0.0.16.md b/shared/concepts/change-notes/released/0.0.16.md new file mode 100644 index 00000000000..62b5521ea01 --- /dev/null +++ b/shared/concepts/change-notes/released/0.0.16.md @@ -0,0 +1,3 @@ +## 0.0.16 + +No user-facing changes. diff --git a/shared/concepts/codeql-pack.release.yml b/shared/concepts/codeql-pack.release.yml index dff35216fc6..a49f7be4cff 100644 --- a/shared/concepts/codeql-pack.release.yml +++ b/shared/concepts/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.15 +lastReleaseVersion: 0.0.16 diff --git a/shared/concepts/qlpack.yml b/shared/concepts/qlpack.yml index 4cfa6918d19..240ee962cfd 100644 --- a/shared/concepts/qlpack.yml +++ b/shared/concepts/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/concepts -version: 0.0.16-dev +version: 0.0.17-dev groups: shared library: true dependencies: diff --git a/shared/controlflow/CHANGELOG.md b/shared/controlflow/CHANGELOG.md index 1fd69b562a6..88666b4ad28 100644 --- a/shared/controlflow/CHANGELOG.md +++ b/shared/controlflow/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.26 + +No user-facing changes. + ## 2.0.25 No user-facing changes. diff --git a/shared/controlflow/change-notes/released/2.0.26.md b/shared/controlflow/change-notes/released/2.0.26.md new file mode 100644 index 00000000000..9b1fe95f577 --- /dev/null +++ b/shared/controlflow/change-notes/released/2.0.26.md @@ -0,0 +1,3 @@ +## 2.0.26 + +No user-facing changes. diff --git a/shared/controlflow/codeql-pack.release.yml b/shared/controlflow/codeql-pack.release.yml index f54d8620118..63d57bef481 100644 --- a/shared/controlflow/codeql-pack.release.yml +++ b/shared/controlflow/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.0.25 +lastReleaseVersion: 2.0.26 diff --git a/shared/controlflow/qlpack.yml b/shared/controlflow/qlpack.yml index 5ed22593368..6ae58a799e6 100644 --- a/shared/controlflow/qlpack.yml +++ b/shared/controlflow/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/controlflow -version: 2.0.26-dev +version: 2.0.27-dev groups: shared library: true dependencies: diff --git a/shared/dataflow/CHANGELOG.md b/shared/dataflow/CHANGELOG.md index 49857928ffe..f9d35bda41d 100644 --- a/shared/dataflow/CHANGELOG.md +++ b/shared/dataflow/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.26 + +No user-facing changes. + ## 2.0.25 No user-facing changes. diff --git a/shared/dataflow/change-notes/released/2.0.26.md b/shared/dataflow/change-notes/released/2.0.26.md new file mode 100644 index 00000000000..9b1fe95f577 --- /dev/null +++ b/shared/dataflow/change-notes/released/2.0.26.md @@ -0,0 +1,3 @@ +## 2.0.26 + +No user-facing changes. diff --git a/shared/dataflow/codeql-pack.release.yml b/shared/dataflow/codeql-pack.release.yml index f54d8620118..63d57bef481 100644 --- a/shared/dataflow/codeql-pack.release.yml +++ b/shared/dataflow/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.0.25 +lastReleaseVersion: 2.0.26 diff --git a/shared/dataflow/qlpack.yml b/shared/dataflow/qlpack.yml index de23fe3e38b..d16d8379bbb 100644 --- a/shared/dataflow/qlpack.yml +++ b/shared/dataflow/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/dataflow -version: 2.0.26-dev +version: 2.0.27-dev groups: shared library: true dependencies: diff --git a/shared/mad/CHANGELOG.md b/shared/mad/CHANGELOG.md index bc1ee96895c..7fe382ef31d 100644 --- a/shared/mad/CHANGELOG.md +++ b/shared/mad/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/shared/mad/change-notes/released/1.0.42.md b/shared/mad/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/shared/mad/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/shared/mad/codeql-pack.release.yml b/shared/mad/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/shared/mad/codeql-pack.release.yml +++ b/shared/mad/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/shared/mad/qlpack.yml b/shared/mad/qlpack.yml index e1b46e5427c..9adf5d48ad5 100644 --- a/shared/mad/qlpack.yml +++ b/shared/mad/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/mad -version: 1.0.42-dev +version: 1.0.43-dev groups: shared library: true dependencies: diff --git a/shared/quantum/CHANGELOG.md b/shared/quantum/CHANGELOG.md index d5252bfc0c4..7ac497bdb32 100644 --- a/shared/quantum/CHANGELOG.md +++ b/shared/quantum/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.20 + +No user-facing changes. + ## 0.0.19 No user-facing changes. diff --git a/shared/quantum/change-notes/released/0.0.20.md b/shared/quantum/change-notes/released/0.0.20.md new file mode 100644 index 00000000000..98daf20a59a --- /dev/null +++ b/shared/quantum/change-notes/released/0.0.20.md @@ -0,0 +1,3 @@ +## 0.0.20 + +No user-facing changes. diff --git a/shared/quantum/codeql-pack.release.yml b/shared/quantum/codeql-pack.release.yml index f406319f372..d2e86745bca 100644 --- a/shared/quantum/codeql-pack.release.yml +++ b/shared/quantum/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.19 +lastReleaseVersion: 0.0.20 diff --git a/shared/quantum/qlpack.yml b/shared/quantum/qlpack.yml index d3129461a49..91774b4db2d 100644 --- a/shared/quantum/qlpack.yml +++ b/shared/quantum/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/quantum -version: 0.0.20-dev +version: 0.0.21-dev groups: shared library: true dependencies: diff --git a/shared/rangeanalysis/CHANGELOG.md b/shared/rangeanalysis/CHANGELOG.md index 3dde8baa4b0..56497c3d31e 100644 --- a/shared/rangeanalysis/CHANGELOG.md +++ b/shared/rangeanalysis/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/shared/rangeanalysis/change-notes/released/1.0.42.md b/shared/rangeanalysis/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/shared/rangeanalysis/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/shared/rangeanalysis/codeql-pack.release.yml b/shared/rangeanalysis/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/shared/rangeanalysis/codeql-pack.release.yml +++ b/shared/rangeanalysis/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/shared/rangeanalysis/qlpack.yml b/shared/rangeanalysis/qlpack.yml index be9c067d84e..a5e5998c4a7 100644 --- a/shared/rangeanalysis/qlpack.yml +++ b/shared/rangeanalysis/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/rangeanalysis -version: 1.0.42-dev +version: 1.0.43-dev groups: shared library: true dependencies: diff --git a/shared/regex/CHANGELOG.md b/shared/regex/CHANGELOG.md index 2e3dacffd92..48478854251 100644 --- a/shared/regex/CHANGELOG.md +++ b/shared/regex/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/shared/regex/change-notes/released/1.0.42.md b/shared/regex/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/shared/regex/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/shared/regex/codeql-pack.release.yml b/shared/regex/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/shared/regex/codeql-pack.release.yml +++ b/shared/regex/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/shared/regex/qlpack.yml b/shared/regex/qlpack.yml index 93baefe6d78..2dd53258318 100644 --- a/shared/regex/qlpack.yml +++ b/shared/regex/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/regex -version: 1.0.42-dev +version: 1.0.43-dev groups: shared library: true dependencies: diff --git a/shared/ssa/CHANGELOG.md b/shared/ssa/CHANGELOG.md index 62c6ce297f9..49bac05febb 100644 --- a/shared/ssa/CHANGELOG.md +++ b/shared/ssa/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.18 + +No user-facing changes. + ## 2.0.17 No user-facing changes. diff --git a/shared/ssa/change-notes/released/2.0.18.md b/shared/ssa/change-notes/released/2.0.18.md new file mode 100644 index 00000000000..11e398dac31 --- /dev/null +++ b/shared/ssa/change-notes/released/2.0.18.md @@ -0,0 +1,3 @@ +## 2.0.18 + +No user-facing changes. diff --git a/shared/ssa/codeql-pack.release.yml b/shared/ssa/codeql-pack.release.yml index a5f7c15c020..16342205c73 100644 --- a/shared/ssa/codeql-pack.release.yml +++ b/shared/ssa/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.0.17 +lastReleaseVersion: 2.0.18 diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml index d5e6d266097..5e567790cfe 100644 --- a/shared/ssa/qlpack.yml +++ b/shared/ssa/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ssa -version: 2.0.18-dev +version: 2.0.19-dev groups: shared library: true dependencies: diff --git a/shared/threat-models/CHANGELOG.md b/shared/threat-models/CHANGELOG.md index d0c8171cdf6..e91058f491a 100644 --- a/shared/threat-models/CHANGELOG.md +++ b/shared/threat-models/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/shared/threat-models/change-notes/released/1.0.42.md b/shared/threat-models/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/shared/threat-models/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/shared/threat-models/codeql-pack.release.yml b/shared/threat-models/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/shared/threat-models/codeql-pack.release.yml +++ b/shared/threat-models/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/shared/threat-models/qlpack.yml b/shared/threat-models/qlpack.yml index 0ed1decf1d0..65539cd3c1b 100644 --- a/shared/threat-models/qlpack.yml +++ b/shared/threat-models/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/threat-models -version: 1.0.42-dev +version: 1.0.43-dev library: true groups: shared dataExtensions: diff --git a/shared/tutorial/CHANGELOG.md b/shared/tutorial/CHANGELOG.md index 83380772573..4ecb5dcd241 100644 --- a/shared/tutorial/CHANGELOG.md +++ b/shared/tutorial/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/shared/tutorial/change-notes/released/1.0.42.md b/shared/tutorial/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/shared/tutorial/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/shared/tutorial/codeql-pack.release.yml b/shared/tutorial/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/shared/tutorial/codeql-pack.release.yml +++ b/shared/tutorial/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/shared/tutorial/qlpack.yml b/shared/tutorial/qlpack.yml index 1e937c1f860..d632d0426b4 100644 --- a/shared/tutorial/qlpack.yml +++ b/shared/tutorial/qlpack.yml @@ -1,7 +1,7 @@ name: codeql/tutorial description: Library for the CodeQL detective tutorials, helping new users learn to write CodeQL queries. -version: 1.0.42-dev +version: 1.0.43-dev groups: shared library: true warnOnImplicitThis: true diff --git a/shared/typeflow/CHANGELOG.md b/shared/typeflow/CHANGELOG.md index caecb313a31..176ba027afe 100644 --- a/shared/typeflow/CHANGELOG.md +++ b/shared/typeflow/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/shared/typeflow/change-notes/released/1.0.42.md b/shared/typeflow/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/shared/typeflow/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/shared/typeflow/codeql-pack.release.yml b/shared/typeflow/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/shared/typeflow/codeql-pack.release.yml +++ b/shared/typeflow/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/shared/typeflow/qlpack.yml b/shared/typeflow/qlpack.yml index f40dd352f6e..19f16908768 100644 --- a/shared/typeflow/qlpack.yml +++ b/shared/typeflow/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typeflow -version: 1.0.42-dev +version: 1.0.43-dev groups: shared library: true dependencies: diff --git a/shared/typeinference/CHANGELOG.md b/shared/typeinference/CHANGELOG.md index 356c331b5df..4d23ebe8abb 100644 --- a/shared/typeinference/CHANGELOG.md +++ b/shared/typeinference/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.23 + +No user-facing changes. + ## 0.0.22 No user-facing changes. diff --git a/shared/typeinference/change-notes/released/0.0.23.md b/shared/typeinference/change-notes/released/0.0.23.md new file mode 100644 index 00000000000..e89a1284bb8 --- /dev/null +++ b/shared/typeinference/change-notes/released/0.0.23.md @@ -0,0 +1,3 @@ +## 0.0.23 + +No user-facing changes. diff --git a/shared/typeinference/codeql-pack.release.yml b/shared/typeinference/codeql-pack.release.yml index 11aaa2243f5..cc2195603d8 100644 --- a/shared/typeinference/codeql-pack.release.yml +++ b/shared/typeinference/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.22 +lastReleaseVersion: 0.0.23 diff --git a/shared/typeinference/qlpack.yml b/shared/typeinference/qlpack.yml index 927036035b5..cd15cfac986 100644 --- a/shared/typeinference/qlpack.yml +++ b/shared/typeinference/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typeinference -version: 0.0.23-dev +version: 0.0.24-dev groups: shared library: true dependencies: diff --git a/shared/typetracking/CHANGELOG.md b/shared/typetracking/CHANGELOG.md index 8504089f872..d5ca15b5be7 100644 --- a/shared/typetracking/CHANGELOG.md +++ b/shared/typetracking/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.26 + +No user-facing changes. + ## 2.0.25 No user-facing changes. diff --git a/shared/typetracking/change-notes/released/2.0.26.md b/shared/typetracking/change-notes/released/2.0.26.md new file mode 100644 index 00000000000..9b1fe95f577 --- /dev/null +++ b/shared/typetracking/change-notes/released/2.0.26.md @@ -0,0 +1,3 @@ +## 2.0.26 + +No user-facing changes. diff --git a/shared/typetracking/codeql-pack.release.yml b/shared/typetracking/codeql-pack.release.yml index f54d8620118..63d57bef481 100644 --- a/shared/typetracking/codeql-pack.release.yml +++ b/shared/typetracking/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.0.25 +lastReleaseVersion: 2.0.26 diff --git a/shared/typetracking/qlpack.yml b/shared/typetracking/qlpack.yml index fcaed606ded..41e4b42ff3b 100644 --- a/shared/typetracking/qlpack.yml +++ b/shared/typetracking/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typetracking -version: 2.0.26-dev +version: 2.0.27-dev groups: shared library: true dependencies: diff --git a/shared/typos/CHANGELOG.md b/shared/typos/CHANGELOG.md index cfbec562b14..9e886726714 100644 --- a/shared/typos/CHANGELOG.md +++ b/shared/typos/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/shared/typos/change-notes/released/1.0.42.md b/shared/typos/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/shared/typos/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/shared/typos/codeql-pack.release.yml b/shared/typos/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/shared/typos/codeql-pack.release.yml +++ b/shared/typos/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml index de131d17f6b..cf3df223c88 100644 --- a/shared/typos/qlpack.yml +++ b/shared/typos/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typos -version: 1.0.42-dev +version: 1.0.43-dev groups: shared library: true warnOnImplicitThis: true diff --git a/shared/util/CHANGELOG.md b/shared/util/CHANGELOG.md index 904aa45e034..de6fbcff12f 100644 --- a/shared/util/CHANGELOG.md +++ b/shared/util/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.29 + +No user-facing changes. + ## 2.0.28 No user-facing changes. diff --git a/shared/util/change-notes/released/2.0.29.md b/shared/util/change-notes/released/2.0.29.md new file mode 100644 index 00000000000..c8e5d5c3d05 --- /dev/null +++ b/shared/util/change-notes/released/2.0.29.md @@ -0,0 +1,3 @@ +## 2.0.29 + +No user-facing changes. diff --git a/shared/util/codeql-pack.release.yml b/shared/util/codeql-pack.release.yml index ec5bd6ba369..1425cb159e4 100644 --- a/shared/util/codeql-pack.release.yml +++ b/shared/util/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.0.28 +lastReleaseVersion: 2.0.29 diff --git a/shared/util/qlpack.yml b/shared/util/qlpack.yml index def146658c0..18d1315e0da 100644 --- a/shared/util/qlpack.yml +++ b/shared/util/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/util -version: 2.0.29-dev +version: 2.0.30-dev groups: shared library: true dependencies: null diff --git a/shared/xml/CHANGELOG.md b/shared/xml/CHANGELOG.md index 7a85ea45c7b..c642973980d 100644 --- a/shared/xml/CHANGELOG.md +++ b/shared/xml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/shared/xml/change-notes/released/1.0.42.md b/shared/xml/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/shared/xml/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/shared/xml/codeql-pack.release.yml b/shared/xml/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/shared/xml/codeql-pack.release.yml +++ b/shared/xml/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/shared/xml/qlpack.yml b/shared/xml/qlpack.yml index d12cff34fbe..63b5786ba44 100644 --- a/shared/xml/qlpack.yml +++ b/shared/xml/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/xml -version: 1.0.42-dev +version: 1.0.43-dev groups: shared library: true dependencies: diff --git a/shared/yaml/CHANGELOG.md b/shared/yaml/CHANGELOG.md index 78b636e0288..b2c9cee85a6 100644 --- a/shared/yaml/CHANGELOG.md +++ b/shared/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.42 + +No user-facing changes. + ## 1.0.41 No user-facing changes. diff --git a/shared/yaml/change-notes/released/1.0.42.md b/shared/yaml/change-notes/released/1.0.42.md new file mode 100644 index 00000000000..821c38854a2 --- /dev/null +++ b/shared/yaml/change-notes/released/1.0.42.md @@ -0,0 +1,3 @@ +## 1.0.42 + +No user-facing changes. diff --git a/shared/yaml/codeql-pack.release.yml b/shared/yaml/codeql-pack.release.yml index d496eab6eb9..53e8667626a 100644 --- a/shared/yaml/codeql-pack.release.yml +++ b/shared/yaml/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.41 +lastReleaseVersion: 1.0.42 diff --git a/shared/yaml/qlpack.yml b/shared/yaml/qlpack.yml index 5ba88d4abdb..1ecff982de7 100644 --- a/shared/yaml/qlpack.yml +++ b/shared/yaml/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/yaml -version: 1.0.42-dev +version: 1.0.43-dev groups: shared library: true warnOnImplicitThis: true diff --git a/swift/ql/lib/CHANGELOG.md b/swift/ql/lib/CHANGELOG.md index f4fe2159e07..65446a02bf3 100644 --- a/swift/ql/lib/CHANGELOG.md +++ b/swift/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.2.2 + +No user-facing changes. + ## 6.2.1 ### Minor Analysis Improvements diff --git a/swift/ql/lib/change-notes/released/6.2.2.md b/swift/ql/lib/change-notes/released/6.2.2.md new file mode 100644 index 00000000000..769c4987cc0 --- /dev/null +++ b/swift/ql/lib/change-notes/released/6.2.2.md @@ -0,0 +1,3 @@ +## 6.2.2 + +No user-facing changes. diff --git a/swift/ql/lib/codeql-pack.release.yml b/swift/ql/lib/codeql-pack.release.yml index 8e36085279d..0d8f9cf7547 100644 --- a/swift/ql/lib/codeql-pack.release.yml +++ b/swift/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 6.2.1 +lastReleaseVersion: 6.2.2 diff --git a/swift/ql/lib/qlpack.yml b/swift/ql/lib/qlpack.yml index 157e1334212..da06170849b 100644 --- a/swift/ql/lib/qlpack.yml +++ b/swift/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/swift-all -version: 6.2.2-dev +version: 6.2.3-dev groups: swift extractor: swift dbscheme: swift.dbscheme diff --git a/swift/ql/src/CHANGELOG.md b/swift/ql/src/CHANGELOG.md index bf6367cf668..0b3d34fc0f5 100644 --- a/swift/ql/src/CHANGELOG.md +++ b/swift/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.16 + +No user-facing changes. + ## 1.2.15 No user-facing changes. diff --git a/swift/ql/src/change-notes/released/1.2.16.md b/swift/ql/src/change-notes/released/1.2.16.md new file mode 100644 index 00000000000..2cba5480d4e --- /dev/null +++ b/swift/ql/src/change-notes/released/1.2.16.md @@ -0,0 +1,3 @@ +## 1.2.16 + +No user-facing changes. diff --git a/swift/ql/src/codeql-pack.release.yml b/swift/ql/src/codeql-pack.release.yml index df8980e5dd2..11aa69f2d7a 100644 --- a/swift/ql/src/codeql-pack.release.yml +++ b/swift/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.2.15 +lastReleaseVersion: 1.2.16 diff --git a/swift/ql/src/qlpack.yml b/swift/ql/src/qlpack.yml index bdac35f35b2..58dd667f57b 100644 --- a/swift/ql/src/qlpack.yml +++ b/swift/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/swift-queries -version: 1.2.16-dev +version: 1.2.17-dev groups: - swift - queries