diff --git a/.github/workflows/ruby-build.yml b/.github/workflows/ruby-build.yml index 08e2b0b4ab6..247d6eb4e63 100644 --- a/.github/workflows/ruby-build.yml +++ b/.github/workflows/ruby-build.yml @@ -197,7 +197,7 @@ jobs: - name: Prepare test files shell: bash run: | - echo "import ruby select count(File f)" > "test.ql" + echo "import codeql.ruby.AST select count(File f)" > "test.ql" echo "| 4 |" > "test.expected" echo 'name: sample-tests version: 0.0.0 diff --git a/.github/workflows/swift-codegen.yml b/.github/workflows/swift-codegen.yml index 5700045430d..0ce0cc91c21 100644 --- a/.github/workflows/swift-codegen.yml +++ b/.github/workflows/swift-codegen.yml @@ -4,6 +4,8 @@ on: pull_request: paths: - "swift/**" + - "misc/bazel/**" + - "*.bazel*" - .github/workflows/swift-codegen.yml - .github/actions/fetch-codeql/action.yml branches: diff --git a/.github/workflows/swift-integration-tests.yml b/.github/workflows/swift-integration-tests.yml index 4d4248b64e3..b81969f3502 100644 --- a/.github/workflows/swift-integration-tests.yml +++ b/.github/workflows/swift-integration-tests.yml @@ -4,6 +4,8 @@ on: pull_request: paths: - "swift/**" + - "misc/bazel/**" + - "*.bazel*" - .github/workflows/swift-integration-tests.yml - .github/actions/fetch-codeql/action.yml - codeql-workspace.yml @@ -30,6 +32,14 @@ jobs: - name: Build Swift extractor run: | bazel run //swift:create-extractor-pack + - name: Get Swift version + id: get_swift_version + run: | + VERSION=$(bazel run //swift/extractor -- --version | sed -ne 's/.*version \(\S*\).*/\1/p') + echo "::set-output name=version::$VERSION" + - uses: swift-actions/setup-swift@v1 + with: + swift-version: "${{steps.get_swift_version.outputs.version}}" - name: Run integration tests run: | python integration-tests/runner.py diff --git a/.github/workflows/swift-qltest.yml b/.github/workflows/swift-qltest.yml index 3cbcf629c98..ab74e96cd57 100644 --- a/.github/workflows/swift-qltest.yml +++ b/.github/workflows/swift-qltest.yml @@ -4,6 +4,8 @@ on: pull_request: paths: - "swift/**" + - "misc/bazel/**" + - "*.bazel*" - .github/workflows/swift-qltest.yml - .github/actions/fetch-codeql/action.yml - codeql-workspace.yml diff --git a/CODEOWNERS b/CODEOWNERS index 1754d58af63..d5ec29f0b93 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -30,6 +30,8 @@ # Bazel (excluding BUILD.bazel files) WORKSPACE.bazel @github/codeql-ci-reviewers +.bazelversion @github/codeql-ci-reviewers +.bazelrc @github/codeql-ci-reviewers **/*.bzl @github/codeql-ci-reviewers # Documentation etc diff --git a/config/identical-files.json b/config/identical-files.json index a7c9cc239f2..de7b75c5d48 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -17,6 +17,10 @@ "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll", + "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll", + "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll", + "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll", + "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll", @@ -37,6 +41,7 @@ "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll", + "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll", @@ -48,6 +53,9 @@ "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll", + "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", + "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", + "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll", @@ -68,15 +76,17 @@ "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll", + "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll", "swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplConsistency.qll" ], - "DataFlow Java/C# Flow Summaries": [ + "DataFlow Java/C#/Ruby/Python/Swift Flow Summaries": [ "java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll", "swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll" ], "SsaReadPosition Java/C#": [ @@ -532,7 +542,7 @@ "java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll", "javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll", - "python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/AccessPathSyntax.qll", "swift/ql/lib/codeql/swift/dataflow/internal/AccessPathSyntax.qll" ], "IncompleteUrlSubstringSanitization": [ diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md index 07ef45e843a..6d2dc736630 100644 --- a/cpp/ql/lib/CHANGELOG.md +++ b/cpp/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.5 + ## 0.3.4 ### Deprecated APIs diff --git a/cpp/ql/lib/change-notes/2022-09-12-uppercase.md b/cpp/ql/lib/change-notes/2022-09-12-uppercase.md new file mode 100644 index 00000000000..996861f1c2c --- /dev/null +++ b/cpp/ql/lib/change-notes/2022-09-12-uppercase.md @@ -0,0 +1,5 @@ +--- +category: deprecated +--- +* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide. + The old name still exists as a deprecated alias. \ No newline at end of file diff --git a/cpp/ql/lib/change-notes/released/0.3.5.md b/cpp/ql/lib/change-notes/released/0.3.5.md new file mode 100644 index 00000000000..88b60b4e980 --- /dev/null +++ b/cpp/ql/lib/change-notes/released/0.3.5.md @@ -0,0 +1 @@ +## 0.3.5 diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml index 5ed15c24b9c..468917f2543 100644 --- a/cpp/ql/lib/codeql-pack.release.yml +++ b/cpp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.4 +lastReleaseVersion: 0.3.5 diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll index c3c68b31ed2..2a6066e1b80 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll @@ -1,5 +1,5 @@ -import semmle.code.cpp.ir.dataflow.DataFlow -import semmle.code.cpp.ir.dataflow.DataFlow2 +import experimental.semmle.code.cpp.ir.dataflow.DataFlow +import experimental.semmle.code.cpp.ir.dataflow.DataFlow2 module ProductFlow { abstract class Configuration extends string { @@ -11,14 +11,43 @@ module ProductFlow { * * `source1` and `source2` must belong to the same callable. */ - abstract predicate isSourcePair(DataFlow::Node source1, DataFlow::Node source2); + predicate isSourcePair(DataFlow::Node source1, DataFlow::Node source2) { none() } + + /** + * Holds if `(source1, source2)` is a relevant data flow source with initial states `state1` + * and `state2`, respectively. + * + * `source1` and `source2` must belong to the same callable. + */ + predicate isSourcePair( + DataFlow::Node source1, string state1, DataFlow::Node source2, string state2 + ) { + state1 = "" and + state2 = "" and + this.isSourcePair(source1, source2) + } /** * Holds if `(sink1, sink2)` is a relevant data flow sink. * * `sink1` and `sink2` must belong to the same callable. */ - abstract predicate isSinkPair(DataFlow::Node sink1, DataFlow::Node sink2); + predicate isSinkPair(DataFlow::Node sink1, DataFlow::Node sink2) { none() } + + /** + * Holds if `(sink1, sink2)` is a relevant data flow sink with final states `state1` + * and `state2`, respectively. + * + * `sink1` and `sink2` must belong to the same callable. + */ + predicate isSinkPair( + DataFlow::Node sink1, DataFlow::FlowState state1, DataFlow::Node sink2, + DataFlow::FlowState state2 + ) { + state1 = "" and + state2 = "" and + this.isSinkPair(sink1, sink2) + } predicate hasFlowPath( DataFlow::PathNode source1, DataFlow2::PathNode source2, DataFlow::PathNode sink1, @@ -34,28 +63,28 @@ module ProductFlow { class Conf1 extends DataFlow::Configuration { Conf1() { this = "Conf1" } - override predicate isSource(DataFlow::Node source) { - exists(Configuration conf | conf.isSourcePair(source, _)) + override predicate isSource(DataFlow::Node source, string state) { + exists(Configuration conf | conf.isSourcePair(source, state, _, _)) } - override predicate isSink(DataFlow::Node sink) { - exists(Configuration conf | conf.isSinkPair(sink, _)) + override predicate isSink(DataFlow::Node sink, string state) { + exists(Configuration conf | conf.isSinkPair(sink, state, _, _)) } } class Conf2 extends DataFlow2::Configuration { Conf2() { this = "Conf2" } - override predicate isSource(DataFlow::Node source) { + override predicate isSource(DataFlow::Node source, string state) { exists(Configuration conf, DataFlow::Node source1 | - conf.isSourcePair(source1, source) and + conf.isSourcePair(source1, _, source, state) and any(Conf1 c).hasFlow(source1, _) ) } - override predicate isSink(DataFlow::Node sink) { + override predicate isSink(DataFlow::Node sink, string state) { exists(Configuration conf, DataFlow::Node sink1 | - conf.isSinkPair(sink1, sink) and any(Conf1 c).hasFlow(_, sink1) + conf.isSinkPair(sink1, _, sink, state) and any(Conf1 c).hasFlow(_, sink1) ) } } @@ -65,7 +94,7 @@ module ProductFlow { Configuration conf, DataFlow::PathNode source1, DataFlow2::PathNode source2, DataFlow::PathNode node1, DataFlow2::PathNode node2 ) { - conf.isSourcePair(node1.getNode(), node2.getNode()) and + conf.isSourcePair(node1.getNode(), _, node2.getNode(), _) and node1 = source1 and node2 = source2 or @@ -128,7 +157,7 @@ module ProductFlow { ) { exists(DataFlow::PathNode mid1, DataFlow2::PathNode mid2 | reachableInterprocEntry(conf, source1, source2, mid1, mid2) and - conf.isSinkPair(sink1.getNode(), sink2.getNode()) and + conf.isSinkPair(sink1.getNode(), _, sink2.getNode(), _) and localPathStep1*(mid1, sink1) and localPathStep2*(mid2, sink2) ) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index e6ce1ada8d4..bf937b6de31 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration { } override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { - (this.isSink(node) or this.isAdditionalTaintStep(node, _)) and + ( + this.isSink(node) or + this.isSink(node, _) or + this.isAdditionalTaintStep(node, _) or + this.isAdditionalTaintStep(node, _, _, _) + ) and defaultImplicitTaintRead(node, c) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index e6ce1ada8d4..bf937b6de31 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration { } override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { - (this.isSink(node) or this.isAdditionalTaintStep(node, _)) and + ( + this.isSink(node) or + this.isSink(node, _) or + this.isAdditionalTaintStep(node, _) or + this.isAdditionalTaintStep(node, _, _, _) + ) and defaultImplicitTaintRead(node, c) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll index e6ce1ada8d4..bf937b6de31 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll @@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration { } override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { - (this.isSink(node) or this.isAdditionalTaintStep(node, _)) and + ( + this.isSink(node) or + this.isSink(node, _) or + this.isAdditionalTaintStep(node, _) or + this.isAdditionalTaintStep(node, _, _, _) + ) and defaultImplicitTaintRead(node, c) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/Bound.qll b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/Bound.qll index eba5c9b4464..abff447ca87 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/Bound.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/Bound.qll @@ -28,6 +28,10 @@ private newtype TBound = i.(LoadInstruction).getSourceAddress() instanceof FieldAddressInstruction or i.getAUse() instanceof ArgumentOperand + or + i instanceof PointerArithmeticInstruction + or + i.getAUse() instanceof AddressOperand ) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExpr.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExpr.qll index 8aeb15cab12..2ea958931da 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExpr.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExpr.qll @@ -178,11 +178,11 @@ class SemRelationalExpr extends SemBinaryExpr { } class SemAddExpr extends SemBinaryExpr { - SemAddExpr() { opcode instanceof Opcode::Add } + SemAddExpr() { opcode instanceof Opcode::Add or opcode instanceof Opcode::PointerAdd } } class SemSubExpr extends SemBinaryExpr { - SemSubExpr() { opcode instanceof Opcode::Sub } + SemSubExpr() { opcode instanceof Opcode::Sub or opcode instanceof Opcode::PointerSub } } class SemMulExpr extends SemBinaryExpr { diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticOpcode.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticOpcode.qll index 304d299dfba..bb56da71f73 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticOpcode.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticOpcode.qll @@ -65,10 +65,18 @@ module Opcode { override string toString() { result = "Add" } } + class PointerAdd extends Opcode, TPointerAdd { + override string toString() { result = "PointerAdd" } + } + class Sub extends Opcode, TSub { override string toString() { result = "Sub" } } + class PointerSub extends Opcode, TPointerSub { + override string toString() { result = "PointerSub" } + } + class Mul extends Opcode, TMul { override string toString() { result = "Mul" } } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll index c2c83e4332d..4953b994c8e 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll @@ -223,7 +223,9 @@ private SemGuard boundFlowCond( else resultIsStrict = testIsTrue.booleanNot() ) and ( - if getTrackedTypeForSsaVariable(v) instanceof SemIntegerType + if + getTrackedTypeForSsaVariable(v) instanceof SemIntegerType or + getTrackedTypeForSsaVariable(v) instanceof SemAddressType then upper = true and strengthen = -1 or diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index d9ea8ca4e6a..432fe263feb 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 0.3.5-dev +version: 0.3.6-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll index 1c75529be00..873a3c635f8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll @@ -1,2 +1,2 @@ -private import SSAConstruction as SSA -import SSA::SsaConsistency +private import SSAConstruction as Ssa +import Ssa::SsaConsistency diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 901735069c0..21c03e176a5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -1135,7 +1135,7 @@ deprecated module SSAConsistency = SsaConsistency; * These predicates are all just aliases for predicates defined in the `Cached` module. This ensures * that all of SSA construction will be evaluated in the same stage. */ -module SSA { +module Ssa { class MemoryLocation = Alias::MemoryLocation; predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2; @@ -1144,3 +1144,6 @@ module SSA { predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1; } + +/** DEPRECATED: Alias for Ssa */ +deprecated module SSA = Ssa; diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll index b30372a791b..5564a16f215 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll @@ -20,24 +20,24 @@ newtype TInstruction = IRConstruction::Raw::hasInstruction(tag1, tag2) } or TUnaliasedSsaPhiInstruction( - TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation + TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation ) { - UnaliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) + UnaliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation) } or TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { - UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc) + UnaliasedSsa::Ssa::hasUnreachedInstruction(irFunc) } or TAliasedSsaPhiInstruction( - TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation + TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation ) { - AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) + AliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation) } or TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) { - AliasedSsa::SSA::hasChiInstruction(primaryInstruction) + AliasedSsa::Ssa::hasChiInstruction(primaryInstruction) } or TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { - AliasedSsa::SSA::hasUnreachedInstruction(irFunc) + AliasedSsa::Ssa::hasUnreachedInstruction(irFunc) } /** @@ -50,7 +50,7 @@ module UnaliasedSsaInstructions { class TPhiInstruction = TUnaliasedSsaPhiInstruction; TPhiInstruction phiInstruction( - TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation + TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation ) { result = TUnaliasedSsaPhiInstruction(blockStartInstr, memoryLocation) } @@ -83,7 +83,7 @@ module AliasedSsaInstructions { class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction; TPhiInstruction phiInstruction( - TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation + TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation ) { result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll index 1c75529be00..873a3c635f8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll @@ -1,2 +1,2 @@ -private import SSAConstruction as SSA -import SSA::SsaConsistency +private import SSAConstruction as Ssa +import Ssa::SsaConsistency diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 901735069c0..21c03e176a5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -1135,7 +1135,7 @@ deprecated module SSAConsistency = SsaConsistency; * These predicates are all just aliases for predicates defined in the `Cached` module. This ensures * that all of SSA construction will be evaluated in the same stage. */ -module SSA { +module Ssa { class MemoryLocation = Alias::MemoryLocation; predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2; @@ -1144,3 +1144,6 @@ module SSA { predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1; } + +/** DEPRECATED: Alias for Ssa */ +deprecated module SSA = Ssa; diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md index ad35d01050b..5546465c50e 100644 --- a/cpp/ql/src/CHANGELOG.md +++ b/cpp/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.4 + ## 0.3.3 ### Minor Analysis Improvements diff --git a/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql b/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql index 663f2e990b5..51d0bc71da7 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql @@ -163,19 +163,46 @@ TGlobalAddress globalAddress(Instruction instr) { result = globalAddress(instr.(PointerOffsetInstruction).getLeft()) } -/** Gets a `StoreInstruction` that may be executed after executing `store`. */ -pragma[inline] -StoreInstruction getAStoreStrictlyAfter(StoreInstruction store) { - exists(IRBlock block, int index1, int index2 | - block.getInstruction(index1) = store and - block.getInstruction(index2) = result and - index2 > index1 +/** + * Gets a first `StoreInstruction` that writes to address `globalAddress` reachable + * from `block`. + */ +StoreInstruction getFirstStore(IRBlock block, TGlobalAddress globalAddress) { + 1 = getStoreRank(result, block, globalAddress) + or + not exists(getStoreRank(_, block, globalAddress)) and + result = getFirstStore(block.getASuccessor(), globalAddress) +} + +/** + * Gets the rank of `store` in block `block` (i.e., a rank of `1` means that it is the + * first `store` to write to `globalAddress`, a rank of `2` means it's the second, etc.) + */ +int getStoreRank(StoreInstruction store, IRBlock block, TGlobalAddress globalAddress) { + blockStoresToAddress(block, _, store, globalAddress) and + store = + rank[result](StoreInstruction anotherStore, int i | + blockStoresToAddress(_, i, anotherStore, globalAddress) + | + anotherStore order by i + ) +} + +/** + * Gets a next subsequent `StoreInstruction` to write to `globalAddress` + * after `store` has done so. + */ +StoreInstruction getANextStoreTo(StoreInstruction store, TGlobalAddress globalAddress) { + exists(IRBlock block, int rnk | + rnk = getStoreRank(store, block, globalAddress) and + rnk + 1 = getStoreRank(result, block, globalAddress) ) or - exists(IRBlock block1, IRBlock block2 | - store.getBlock() = block1 and - result.getBlock() = block2 and - block1.getASuccessor+() = block2 + exists(IRBlock block, int rnk, IRBlock succ | + rnk = getStoreRank(store, block, globalAddress) and + not rnk + 1 = getStoreRank(_, block, globalAddress) and + succ = block.getASuccessor() and + result = getFirstStore(succ, globalAddress) ) } @@ -192,7 +219,7 @@ predicate stackAddressEscapes( stackPointerFlowsToUse(store.getSourceValue(), vai) ) and // Ensure there's no subsequent store that overrides the global address. - not globalAddress = globalAddress(getAStoreStrictlyAfter(store).getDestinationAddress()) + not exists(getANextStoreTo(store, globalAddress)) } predicate blockStoresToAddress( diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index 0c3e35e0fbc..4b0c3c60957 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -19,7 +19,7 @@ import semmle.code.cpp.ir.dataflow.TaintTracking import DataFlow::PathGraph /** - * Taint flow from user input to a buffer write. + * A taint flow configuration for flow from user input to a buffer write. */ class ToBufferConfiguration extends TaintTracking::Configuration { ToBufferConfiguration() { this = "ToBufferConfiguration" } diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql index 3df7d0cc5aa..e1b12f72fa2 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql @@ -21,7 +21,7 @@ import semmle.code.cpp.dataflow.TaintTracking import DataFlow::PathGraph /** - * Taint flow from a sensitive expression to a `FileWrite` sink. + * A taint flow configuration for flow from a sensitive expression to a `FileWrite` sink. */ class FromSensitiveConfiguration extends TaintTracking::Configuration { FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" } @@ -29,6 +29,10 @@ class FromSensitiveConfiguration extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr } override predicate isSink(DataFlow::Node sink) { any(FileWrite w).getASource() = sink.asExpr() } + + override predicate isSanitizer(DataFlow::Node node) { + node.asExpr().getUnspecifiedType() instanceof IntegralType + } } /** diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 72d96d0da3f..d1d6ccd8367 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -217,7 +217,8 @@ class Encrypted extends Expr { } /** - * Taint flow from a sensitive expression. + * A taint flow configuration for flow from a sensitive expression to a network + * operation or encryption operation. */ class FromSensitiveConfiguration extends TaintTracking::Configuration { FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" } @@ -234,6 +235,10 @@ class FromSensitiveConfiguration extends TaintTracking::Configuration { // flow through encryption functions to the return value (in case we can reach other sinks) node2.asExpr().(Encrypted).(FunctionCall).getAnArgument() = node1.asExpr() } + + override predicate isSanitizer(DataFlow::Node node) { + node.asExpr().getUnspecifiedType() instanceof IntegralType + } } from diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql index 8133d4752d9..464e6f325cc 100644 --- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql @@ -13,14 +13,8 @@ import cpp import semmle.code.cpp.security.SensitiveExprs -import semmle.code.cpp.security.TaintTracking -import TaintedWithPath - -class UserInputIsSensitiveExpr extends SecurityOptions { - override predicate isUserInput(Expr expr, string cause) { - expr instanceof SensitiveExpr and cause = "sensitive information" - } -} +import semmle.code.cpp.dataflow.TaintTracking +import DataFlow::PathGraph class SqliteFunctionCall extends FunctionCall { SqliteFunctionCall() { this.getTarget().getName().matches("sqlite%") } @@ -34,25 +28,51 @@ predicate sqlite_encryption_used() { any(FunctionCall fc).getTarget().getName().matches("sqlite%\\_key\\_%") } -class Configuration extends TaintTrackingConfiguration { - override predicate isSource(Expr source) { - super.isSource(source) and source instanceof SensitiveExpr +/** + * Gets a field of the class `c`, or of another class contained in `c`. + */ +Field getRecField(Class c) { + result = c.getAField() or + result = getRecField(c.getAField().getUnspecifiedType().stripType()) +} + +/** + * A taint flow configuration for flow from a sensitive expression to a `SqliteFunctionCall` sink. + */ +class FromSensitiveConfiguration extends TaintTracking::Configuration { + FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" } + + override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr } + + override predicate isSink(DataFlow::Node sink) { + any(SqliteFunctionCall c).getASource() = sink.asExpr() and + not sqlite_encryption_used() } - override predicate isSink(Element taintedArg) { - exists(SqliteFunctionCall sqliteCall | - taintedArg = sqliteCall.getASource() and - not sqlite_encryption_used() + override predicate isSanitizer(DataFlow::Node node) { + node.asExpr().getUnspecifiedType() instanceof IntegralType + } + + override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet content) { + // flow out from fields at the sink (only). + this.isSink(node) and + // constrain `content` to a field inside the node. + exists(Class c | + node.asExpr().getUnspecifiedType().stripType() = c and + content.(DataFlow::FieldContent).getField() = getRecField(c) ) + or + // any default implicit reads + super.allowImplicitRead(node, content) } } from - SensitiveExpr taintSource, Expr taintedArg, SqliteFunctionCall sqliteCall, PathNode sourceNode, - PathNode sinkNode + FromSensitiveConfiguration config, SensitiveExpr sensitive, DataFlow::PathNode source, + DataFlow::PathNode sink, SqliteFunctionCall sqliteCall where - taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and - taintedArg = sqliteCall.getASource() -select sqliteCall, sourceNode, sinkNode, - "This SQLite call may store $@ in a non-encrypted SQLite database", taintSource, - "sensitive information" + config.hasFlowPath(source, sink) and + source.getNode().asExpr() = sensitive and + sqliteCall.getASource() = sink.getNode().asExpr() +select sqliteCall, source, sink, "This SQLite call may store $@ in a non-encrypted SQLite database", + sensitive, "sensitive information" diff --git a/cpp/ql/src/change-notes/2022-09-05-cleartext-queries.md b/cpp/ql/src/change-notes/2022-09-05-cleartext-queries.md new file mode 100644 index 00000000000..b0422164365 --- /dev/null +++ b/cpp/ql/src/change-notes/2022-09-05-cleartext-queries.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Modernizations from "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) have been ported to the "Cleartext storage of sensitive information in file" (`cpp/cleartext-storage-file`), "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) and "Cleartext storage of sensitive information in an SQLite database" (`cpp/cleartext-storage-database`) queries. These changes may result in more correct results and fewer false positive results from these queries. diff --git a/cpp/ql/src/change-notes/released/0.3.4.md b/cpp/ql/src/change-notes/released/0.3.4.md new file mode 100644 index 00000000000..d62a8a1780d --- /dev/null +++ b/cpp/ql/src/change-notes/released/0.3.4.md @@ -0,0 +1 @@ +## 0.3.4 diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml index 9da182d3394..5ed15c24b9c 100644 --- a/cpp/ql/src/codeql-pack.release.yml +++ b/cpp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.3 +lastReleaseVersion: 0.3.4 diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.cpp new file mode 100644 index 00000000000..0ad0635ae40 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.cpp @@ -0,0 +1,26 @@ +void *malloc(unsigned); +unsigned get_size(); +void write_data(const unsigned char*, const unsigned char*); + +int main(int argc, char* argv[]) { + unsigned size = get_size(); + + { + unsigned char *begin = (unsigned char*)malloc(size); + if(!begin) return -1; + + unsigned char* end = begin + size; + write_data(begin, end); + *end = '\0'; // BAD: Out-of-bounds write + } + + { + unsigned char *begin = (unsigned char*)malloc(size); + if(!begin) return -1; + + unsigned char* end = begin + size; + write_data(begin, end); + *(end - 1) = '\0'; // GOOD: writing to the last byte + } + +} \ No newline at end of file diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.qhelp new file mode 100644 index 00000000000..4f590659112 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.qhelp @@ -0,0 +1,31 @@ + + + +

The program performs an out-of-bounds read or write operation. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code.

+ +
+ + +

Ensure that pointer dereferences are properly guarded to ensure that they cannot be used to read or write past the end of the allocation.

+ +
+ +

The first example allocates a buffer of size size and creates a local variable that stores the location that is one byte past the end of the allocation. +This local variable is then dereferenced which results in an out-of-bounds write. +The second example subtracts one from the end variable before dereferencing it. This subtraction ensures that the write correctly updates the final byte of the allocation.

+ + +
+ + +
  • CERT C Coding Standard: +ARR30-C. Do not form or use out-of-bounds pointers or array subscripts.
  • +
  • +OWASP: +Buffer Overflow. +
  • + +
    +
    diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql new file mode 100644 index 00000000000..05327263386 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql @@ -0,0 +1,360 @@ +/** + * @name Invalid pointer dereference + * @description Dereferencing a pointer that points past it allocation is undefined behavior + * and may lead to security vulnerabilities. + * @kind path-problem + * @problem.severity error + * @precision high + * @id cpp/invalid-pointer-deref + * @tags reliability + * security + * external/cwe/cwe-119 + * external/cwe/cwe-125 + * external/cwe/cwe-193 + * external/cwe/cwe-787 + */ + +import cpp +import experimental.semmle.code.cpp.dataflow.ProductFlow +import experimental.semmle.code.cpp.ir.dataflow.DataFlow3 +import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis +import experimental.semmle.code.cpp.semantic.SemanticBound +import experimental.semmle.code.cpp.semantic.SemanticExprSpecific +import semmle.code.cpp.ir.IR + +pragma[nomagic] +Instruction getABoundIn(SemBound b, IRFunction func) { + result = b.getExpr(0) and + result.getEnclosingIRFunction() = func +} + +/** + * Holds if `i <= b + delta`. + */ +pragma[nomagic] +predicate bounded(Instruction i, Instruction b, int delta) { + exists(SemBound bound, IRFunction func | + semBounded(getSemanticExpr(i), bound, delta, true, _) and + b = getABoundIn(bound, func) and + i.getEnclosingIRFunction() = func + ) +} + +/** + * Holds if the combination of `n` and `state` represents an appropriate + * source for the expression `e` suitable for use-use flow. + */ +private predicate hasSizeImpl(Expr e, DataFlow::Node n, string state) { + // The simple case: If the size is a variable access with no qualifier we can just use the + // dataflow node for that expression and no state. + exists(VariableAccess va | + va = e and + not va instanceof FieldAccess and + n.asConvertedExpr() = va.getFullyConverted() and + state = "0" + ) + or + // If the size is a choice between two expressions we allow both to be nodes representing the size. + exists(ConditionalExpr cond | cond = e | hasSizeImpl([cond.getThen(), cond.getElse()], n, state)) + or + // If the size is an expression plus a constant, we pick the dataflow node of the expression and + // remember the constant in the state. + exists(Expr const, Expr nonconst | + e.(AddExpr).hasOperands(const, nonconst) and + state = const.getValue() and + hasSizeImpl(nonconst, n, _) + ) + or + exists(Expr const, Expr nonconst | + e.(SubExpr).hasOperands(const, nonconst) and + state = "-" + const.getValue() and + hasSizeImpl(nonconst, n, _) + ) +} + +/** + * Holds if `(n, state)` pair represents the source of flow for the size + * expression associated with `alloc`. + */ +predicate hasSize(AllocationExpr alloc, DataFlow::Node n, string state) { + hasSizeImpl(alloc.getSizeExpr(), n, state) +} + +/** + * A product-flow configuration for flow from an (allocation, size) pair to a + * pointer-arithmetic operation that is non-strictly upper-bounded by `allocation + size`. + * + * The goal of this query is to find patterns such as: + * ```cpp + * 1. char* begin = (char*)malloc(size); + * 2. char* end = begin + size; + * 3. for(int *p = begin; p <= end; p++) { + * 4. use(*p); + * 5. } + * ``` + * + * We do this by splitting the task up into two configurations: + * 1. `AllocToInvalidPointerConf` find flow from `malloc(size)` to `begin + size`, and + * 2. `InvalidPointerToDerefConf` finds flow from `begin + size` to an `end` (on line 3). + * + * Finally, the range-analysis library will find a load from (or store to) an address that + * is non-strictly upper-bounded by `end` (which in this case is `*p`). + */ +class AllocToInvalidPointerConf extends ProductFlow::Configuration { + AllocToInvalidPointerConf() { this = "AllocToInvalidPointerConf" } + + override predicate isSourcePair( + DataFlow::Node source1, string state1, DataFlow::Node source2, string state2 + ) { + // In the case of an allocation like + // ```cpp + // malloc(size + 1); + // ``` + // we use `state2` to remember that there was an offset (in this case an offset of `1`) added + // to the size of the allocation. This state is then checked in `isSinkPair`. + state1 = "" and + hasSize(source1.asConvertedExpr(), source2, state2) + } + + override predicate isSinkPair( + DataFlow::Node sink1, DataFlow::FlowState state1, DataFlow::Node sink2, + DataFlow::FlowState state2 + ) { + state1 = "" and + // We check that the delta computed by the range analysis matches the + // state value that we set in `isSourcePair`. + exists(int delta | + isSinkImpl(_, sink1, sink2, delta) and + state2 = delta.toString() + ) + } +} + +pragma[nomagic] +predicate pointerAddInstructionHasOperands( + PointerAddInstruction pai, Instruction left, Instruction right +) { + pai.getLeft() = left and + pai.getRight() = right +} + +/** + * Holds if `pai` is non-strictly upper bounded by `sink2 + delta` and `sink1` is the + * left operand of the pointer-arithmetic operation. + * + * For example in, + * ```cpp + * char* end = p + (size + 1); + * ``` + * We will have: + * - `pai` is `p + (size + 1)`, + * - `sink1` is `p` + * - `sink2` is `size` + * - `delta` is `1`. + */ +pragma[nomagic] +predicate pointerAddInstructionHasBounds( + PointerAddInstruction pai, DataFlow::Node sink1, Instruction sink2, int delta +) { + exists(Instruction right | + pointerAddInstructionHasOperands(pai, sink1.asInstruction(), right) and + bounded(right, sink2, delta) + ) +} + +/** + * Holds if `pai` is non-strictly upper bounded by `sink2 + delta` and `sink1` is the + * left operand of the pointer-arithmetic operation. + * + * See `pointerAddInstructionHasBounds` for an example. + */ +predicate isSinkImpl( + PointerAddInstruction pai, DataFlow::Node sink1, DataFlow::Node sink2, int delta +) { + pointerAddInstructionHasBounds(pai, sink1, sink2.asInstruction(), delta) +} + +/** + * Holds if `sink` is a sink for `InvalidPointerToDerefConf` and `i` is a `StoreInstruction` that + * writes to an address that non-strictly upper-bounds `sink`, or `i` is a `LoadInstruction` that + * reads from an address that non-strictly upper-bounds `sink`. + */ +predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string operation) { + exists(AddressOperand addr, int delta | + bounded(addr.getDef(), sink.asInstruction(), delta) and + delta >= 0 and + i.getAnOperand() = addr + | + i instanceof StoreInstruction and + operation = "write" + or + i instanceof LoadInstruction and + operation = "read" + ) +} + +/** + * A configuration to track flow from a pointer-arithmetic operation found + * by `AllocToInvalidPointerConf` to a dereference of the pointer. + */ +class InvalidPointerToDerefConf extends DataFlow3::Configuration { + InvalidPointerToDerefConf() { this = "InvalidPointerToDerefConf" } + + override predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, source, _) } + + override predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) } +} + +/** + * Holds if `pai` is a pointer-arithmetic operation and `source` is a dataflow node with a + * pointer-value that is non-strictly upper bounded by `pai + delta`. + * + * For example, if `pai` is a pointer-arithmetic operation `p + size` in an expression such + * as `(p + size) + 1` and `source` is the node representing `(p + size) + 1`. In this + * case `delta` is 1. + */ +predicate invalidPointerToDerefSource( + PointerArithmeticInstruction pai, DataFlow::Node source, int delta +) { + exists(ProductFlow::Configuration conf, DataFlow::PathNode p, DataFlow::Node sink1 | + p.getNode() = sink1 and + conf.hasFlowPath(_, _, p, _) and + isSinkImpl(pai, sink1, _, _) and + bounded(source.asInstruction(), pai, delta) and + delta >= 0 + ) +} + +newtype TMergedPathNode = + // The path nodes computed by the first projection of `AllocToInvalidPointerConf` + TPathNode1(DataFlow::PathNode p) or + // The path nodes computed by `InvalidPointerToDerefConf` + TPathNode3(DataFlow3::PathNode p) or + // The read/write that uses the invalid pointer identified by `InvalidPointerToDerefConf`. + // This one is needed because the sink identified by `InvalidPointerToDerefConf` is the + // pointer, but we want to raise an alert at the dereference. + TPathNodeSink(Instruction i) { + exists(DataFlow::Node n | + any(InvalidPointerToDerefConf conf).hasFlow(_, n) and + isInvalidPointerDerefSink(n, i, _) + ) + } + +class MergedPathNode extends TMergedPathNode { + string toString() { none() } + + final DataFlow::PathNode asPathNode1() { this = TPathNode1(result) } + + final DataFlow3::PathNode asPathNode3() { this = TPathNode3(result) } + + final Instruction asSinkNode() { this = TPathNodeSink(result) } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + none() + } +} + +class PathNode1 extends MergedPathNode, TPathNode1 { + override string toString() { + exists(DataFlow::PathNode p | + this = TPathNode1(p) and + result = p.toString() + ) + } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asPathNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} + +class PathNode3 extends MergedPathNode, TPathNode3 { + override string toString() { + exists(DataFlow3::PathNode p | + this = TPathNode3(p) and + result = p.toString() + ) + } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asPathNode3().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} + +class PathSinkNode extends MergedPathNode, TPathNodeSink { + override string toString() { + exists(Instruction i | + this = TPathNodeSink(i) and + result = i.toString() + ) + } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asSinkNode() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} + +query predicate edges(MergedPathNode node1, MergedPathNode node2) { + node1.asPathNode1().getASuccessor() = node2.asPathNode1() + or + joinOn1(_, node1.asPathNode1(), node2.asPathNode3()) + or + node1.asPathNode3().getASuccessor() = node2.asPathNode3() + or + joinOn2(node1.asPathNode3(), node2.asSinkNode(), _) +} + +/** + * Holds if `p1` is a sink of `AllocToInvalidPointerConf` and `p2` is a source + * of `InvalidPointerToDerefConf`, and they are connected through `pai`. + */ +predicate joinOn1(PointerArithmeticInstruction pai, DataFlow::PathNode p1, DataFlow3::PathNode p2) { + isSinkImpl(pai, p1.getNode(), _, _) and + invalidPointerToDerefSource(pai, p2.getNode(), _) +} + +/** + * Holds if `p1` is a sink of `InvalidPointerToDerefConf` and `i` is the instruction + * that dereferences `p1`. The string `operation` describes whether the `i` is + * a `StoreInstruction` or `LoadInstruction`. + */ +predicate joinOn2(DataFlow3::PathNode p1, Instruction i, string operation) { + isInvalidPointerDerefSink(p1.getNode(), i, operation) +} + +predicate hasFlowPath( + MergedPathNode source1, MergedPathNode sink, DataFlow3::PathNode source3, + PointerArithmeticInstruction pai, string operation +) { + exists( + AllocToInvalidPointerConf conf1, InvalidPointerToDerefConf conf2, DataFlow3::PathNode sink3, + DataFlow::PathNode sink1 + | + conf1.hasFlowPath(source1.asPathNode1(), _, sink1, _) and + joinOn1(pai, sink1, source3) and + conf2.hasFlowPath(source3, sink3) and + joinOn2(sink3, sink.asSinkNode(), operation) + ) +} + +from + MergedPathNode source, MergedPathNode sink, int k, string kstr, DataFlow3::PathNode source3, + PointerArithmeticInstruction pai, string operation, Expr offset, DataFlow::Node n +where + hasFlowPath(source, sink, source3, pai, operation) and + invalidPointerToDerefSource(pai, source3.getNode(), k) and + offset = pai.getRight().getUnconvertedResultExpression() and + n = source.asPathNode1().getNode() and + if k = 0 then kstr = "" else kstr = " + " + k +select sink, source, sink, + "This " + operation + " might be out of bounds, as the pointer might be equal to $@ + $@" + kstr + + ".", n, n.toString(), offset, offset.toString() diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index 6b0f6e7ed01..252f9baa0f4 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 0.3.4-dev +version: 0.3.5-dev groups: - cpp - queries diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected index ea8c8f8f577..106313c8707 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected @@ -20,10 +20,12 @@ | test.cpp:62:10:62:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:62:10:62:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 3 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 | | test.cpp:62:10:62:13 | Load: iter | test.cpp:61:39:61:51 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 | +| test.cpp:62:10:62:13 | Load: iter | test.cpp:61:48:61:50 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 | | test.cpp:67:10:67:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:67:10:67:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 3 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 | | test.cpp:67:10:67:13 | Load: iter | test.cpp:61:32:61:35 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 | | test.cpp:67:10:67:13 | Load: iter | test.cpp:61:39:61:51 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 | +| test.cpp:67:10:67:13 | Load: iter | test.cpp:61:48:61:50 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 | | test.cpp:77:12:77:12 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:77:12:77:12 | Load: i | test.cpp:72:15:72:15 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 | | test.cpp:77:12:77:12 | Load: i | test.cpp:72:22:72:22 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected index 56ae4e59a9a..dedb1d72a38 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected @@ -1,2 +1,2 @@ -| test.cpp:19:19:19:24 | call to malloc | test.cpp:18:17:18:20 | size | test.cpp:26:18:26:23 | string | test.cpp:26:31:26:39 | (size_t)... | -| test.cpp:19:19:19:24 | call to malloc | test.cpp:18:17:18:20 | size | test.cpp:30:18:30:23 | string | test.cpp:30:31:30:39 | (size_t)... | +| test.cpp:19:19:19:24 | call to malloc | test.cpp:18:17:18:20 | size | test.cpp:26:18:26:23 | Load | test.cpp:26:31:26:39 | Convert | +| test.cpp:19:19:19:24 | call to malloc | test.cpp:18:17:18:20 | size | test.cpp:30:18:30:23 | Load | test.cpp:30:31:30:39 | Convert | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/ArrayAccessProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/ArrayAccessProductFlow.expected index 2564193fb2e..8b82181b9f7 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/ArrayAccessProductFlow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/ArrayAccessProductFlow.expected @@ -1,23 +1,20 @@ -| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:4:24:4:27 | size | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:4:24:4:27 | size | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:5:25:5:28 | size | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:5:25:5:28 | size | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:9:26:9:29 | size | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | arr | test.cpp:5:25:5:28 | size | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | arr | test.cpp:5:25:5:28 | size | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | arr | test.cpp:9:26:9:29 | size | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:9:26:9:29 | size | test.cpp:10:9:10:11 | arr | test.cpp:9:26:9:29 | size | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:9:26:9:29 | size | test.cpp:10:9:10:11 | arr | test.cpp:9:26:9:29 | size | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | p | test.cpp:55:5:55:19 | Store | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | p | test.cpp:55:16:55:19 | size | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | p | test.cpp:55:16:55:19 | size | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | p | test.cpp:56:20:56:23 | size | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:56:20:56:23 | size | test.cpp:63:13:63:13 | p | test.cpp:56:20:56:23 | size | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:56:20:56:23 | size | test.cpp:63:13:63:13 | p | test.cpp:56:20:56:23 | size | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:58:29:58:32 | size | test.cpp:63:13:63:13 | p | test.cpp:58:29:58:32 | size | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:58:29:58:32 | size | test.cpp:63:13:63:13 | p | test.cpp:58:29:58:32 | size | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:62:30:62:33 | size | test.cpp:63:13:63:13 | p | test.cpp:62:30:62:33 | size | -| test.cpp:56:13:56:18 | call to malloc | test.cpp:62:30:62:33 | size | test.cpp:63:13:63:13 | p | test.cpp:62:30:62:33 | size | -| test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:83:14:83:14 | p | test.cpp:82:31:82:34 | size | -| test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:93:14:93:14 | p | test.cpp:88:30:88:33 | size | -| test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:93:14:93:14 | p | test.cpp:92:31:92:34 | size | +| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | Load | test.cpp:5:25:5:28 | Load | +| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | Load | test.cpp:9:26:9:29 | Load | +| test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | Load | test.cpp:5:25:5:28 | Load | +| test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | Load | test.cpp:9:26:9:29 | Load | +| test.cpp:4:17:4:22 | call to malloc | test.cpp:9:26:9:29 | size | test.cpp:10:9:10:11 | Load | test.cpp:9:26:9:29 | Load | +| test.cpp:22:13:22:18 | call to malloc | test.cpp:21:16:21:19 | size | test.cpp:35:13:35:13 | Load | test.cpp:30:29:30:32 | Load | +| test.cpp:22:13:22:18 | call to malloc | test.cpp:21:16:21:19 | size | test.cpp:35:13:35:13 | Load | test.cpp:34:30:34:33 | Load | +| test.cpp:22:13:22:18 | call to malloc | test.cpp:21:16:21:19 | size | test.cpp:45:13:45:13 | Load | test.cpp:40:29:40:32 | Load | +| test.cpp:22:13:22:18 | call to malloc | test.cpp:21:16:21:19 | size | test.cpp:45:13:45:13 | Load | test.cpp:44:30:44:33 | Load | +| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:55:5:55:19 | Store | +| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:55:5:55:19 | Store | +| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:55:16:55:19 | Load | +| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:56:20:56:23 | Load | +| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:58:29:58:32 | Load | +| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:62:30:62:33 | Load | +| test.cpp:56:13:56:18 | call to malloc | test.cpp:58:29:58:32 | size | test.cpp:63:13:63:13 | Load | test.cpp:58:29:58:32 | Load | +| test.cpp:56:13:56:18 | call to malloc | test.cpp:62:30:62:33 | size | test.cpp:63:13:63:13 | Load | test.cpp:62:30:62:33 | Load | +| test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:83:14:83:14 | Load | test.cpp:82:31:82:34 | Load | +| test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:93:14:93:14 | Load | test.cpp:88:30:88:33 | Load | +| test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:93:14:93:14 | Load | test.cpp:92:31:92:34 | Load | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/test.cpp index b3c4341f9b8..f35379db3e4 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/test.cpp @@ -32,7 +32,7 @@ void test2(int size) { } for (int i = 0; i <= arr.size; i++) { - arr.p[i] = i; // BAD [NOT DETECTED] + arr.p[i] = i; // BAD } } @@ -42,7 +42,7 @@ void test3_callee(array_t arr) { } for (int i = 0; i <= arr.size; i++) { - arr.p[i] = i; // BAD [NOT DETECTED] + arr.p[i] = i; // BAD } } diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected new file mode 100644 index 00000000000..494713b124b --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected @@ -0,0 +1,627 @@ +edges +| test.cpp:4:15:4:20 | call to malloc | test.cpp:5:15:5:15 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | +| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | +| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | +| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | +| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | +| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | +| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | +| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | +| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... | +| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... | +| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... | +| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... | +| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:12:16:12:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:5:15:5:22 | Store | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:5:15:5:22 | Store | test.cpp:6:15:6:15 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:6:15:6:15 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:7:16:7:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:7:16:7:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:5:15:5:22 | Store | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:5:15:5:22 | Store | test.cpp:8:16:8:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:8:16:8:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:9:16:9:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:9:16:9:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:10:16:10:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:10:16:10:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:11:16:11:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:11:16:11:16 | Load | +| test.cpp:5:15:5:22 | Store | test.cpp:12:16:12:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:6:15:6:15 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:6:15:6:15 | Load | test.cpp:7:16:7:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:7:16:7:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:6:15:6:15 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:6:15:6:15 | Load | test.cpp:8:16:8:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:8:16:8:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:6:15:6:15 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:7:16:7:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:7:16:7:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:7:16:7:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:7:16:7:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:7:16:7:16 | Load | test.cpp:8:16:8:16 | Load | +| test.cpp:7:16:7:16 | Load | test.cpp:8:16:8:16 | Load | +| test.cpp:7:16:7:16 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:7:16:7:16 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:7:16:7:16 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:7:16:7:16 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:7:16:7:16 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:7:16:7:16 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:7:16:7:16 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:8:16:8:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:8:16:8:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:8:16:8:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:8:16:8:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:8:16:8:16 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:8:16:8:16 | Load | test.cpp:9:16:9:16 | Load | +| test.cpp:8:16:8:16 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:8:16:8:16 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:8:16:8:16 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:8:16:8:16 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:8:16:8:16 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:8:16:8:20 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:8:16:8:20 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:9:16:9:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:9:16:9:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:9:16:9:16 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:9:16:9:16 | Load | test.cpp:10:16:10:16 | Load | +| test.cpp:9:16:9:16 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:9:16:9:16 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:9:16:9:16 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:10:16:10:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:10:16:10:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:10:16:10:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:10:16:10:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:10:16:10:16 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:10:16:10:16 | Load | test.cpp:11:16:11:16 | Load | +| test.cpp:10:16:10:16 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:11:16:11:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:11:16:11:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:11:16:11:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:11:16:11:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:11:16:11:16 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:12:16:12:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:12:16:12:16 | Load | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:12:16:12:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:12:16:12:16 | Load | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:16:15:16:20 | call to malloc | test.cpp:17:15:17:15 | Load | +| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... | +| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... | +| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... | +| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... | +| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... | +| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... | +| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... | +| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... | +| test.cpp:17:15:17:22 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | +| test.cpp:17:15:17:22 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | +| test.cpp:20:16:20:20 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | +| test.cpp:20:16:20:20 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | +| test.cpp:28:15:28:20 | call to malloc | test.cpp:29:15:29:15 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | +| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | +| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | +| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | +| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | +| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | +| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | +| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | +| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... | +| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... | +| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... | +| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... | +| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:36:16:36:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:29:15:29:28 | Store | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:29:15:29:28 | Store | test.cpp:30:15:30:15 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:30:15:30:15 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:31:16:31:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:31:16:31:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:29:15:29:28 | Store | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:29:15:29:28 | Store | test.cpp:32:16:32:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:32:16:32:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:33:16:33:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:33:16:33:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:34:16:34:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:34:16:34:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:35:16:35:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:35:16:35:16 | Load | +| test.cpp:29:15:29:28 | Store | test.cpp:36:16:36:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:30:15:30:15 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:30:15:30:15 | Load | test.cpp:31:16:31:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:31:16:31:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:30:15:30:15 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:30:15:30:15 | Load | test.cpp:32:16:32:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:32:16:32:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:30:15:30:15 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:31:16:31:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:31:16:31:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:31:16:31:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:31:16:31:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:31:16:31:16 | Load | test.cpp:32:16:32:16 | Load | +| test.cpp:31:16:31:16 | Load | test.cpp:32:16:32:16 | Load | +| test.cpp:31:16:31:16 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:31:16:31:16 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:31:16:31:16 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:31:16:31:16 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:31:16:31:16 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:31:16:31:16 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:31:16:31:16 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:32:16:32:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:32:16:32:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:32:16:32:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:32:16:32:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:32:16:32:16 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:32:16:32:16 | Load | test.cpp:33:16:33:16 | Load | +| test.cpp:32:16:32:16 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:32:16:32:16 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:32:16:32:16 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:32:16:32:16 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:32:16:32:16 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:32:16:32:20 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:32:16:32:20 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:33:16:33:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:33:16:33:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:33:16:33:16 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:33:16:33:16 | Load | test.cpp:34:16:34:16 | Load | +| test.cpp:33:16:33:16 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:33:16:33:16 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:33:16:33:16 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:34:16:34:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:34:16:34:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:34:16:34:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:34:16:34:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:34:16:34:16 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:34:16:34:16 | Load | test.cpp:35:16:35:16 | Load | +| test.cpp:34:16:34:16 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:35:16:35:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:35:16:35:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:35:16:35:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:35:16:35:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:35:16:35:16 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:36:16:36:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:36:16:36:16 | Load | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:36:16:36:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:36:16:36:16 | Load | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:40:15:40:20 | call to malloc | test.cpp:41:15:41:15 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | +| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | +| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | +| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | +| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | +| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | +| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | +| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | +| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... | +| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... | +| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... | +| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... | +| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:48:16:48:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:41:15:41:28 | Store | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:41:15:41:28 | Store | test.cpp:42:15:42:15 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:42:15:42:15 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:43:16:43:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:43:16:43:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:41:15:41:28 | Store | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:41:15:41:28 | Store | test.cpp:44:16:44:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:44:16:44:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:45:16:45:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:45:16:45:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:46:16:46:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:46:16:46:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:47:16:47:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:47:16:47:16 | Load | +| test.cpp:41:15:41:28 | Store | test.cpp:48:16:48:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:42:15:42:15 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:42:15:42:15 | Load | test.cpp:43:16:43:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:43:16:43:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:42:15:42:15 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:42:15:42:15 | Load | test.cpp:44:16:44:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:44:16:44:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:42:15:42:15 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:43:16:43:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:43:16:43:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:43:16:43:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:43:16:43:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:43:16:43:16 | Load | test.cpp:44:16:44:16 | Load | +| test.cpp:43:16:43:16 | Load | test.cpp:44:16:44:16 | Load | +| test.cpp:43:16:43:16 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:43:16:43:16 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:43:16:43:16 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:43:16:43:16 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:43:16:43:16 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:43:16:43:16 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:43:16:43:16 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:44:16:44:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:44:16:44:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:44:16:44:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:44:16:44:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:44:16:44:16 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:44:16:44:16 | Load | test.cpp:45:16:45:16 | Load | +| test.cpp:44:16:44:16 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:44:16:44:16 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:44:16:44:16 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:44:16:44:16 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:44:16:44:16 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:44:16:44:20 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:44:16:44:20 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:45:16:45:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:45:16:45:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:45:16:45:16 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:45:16:45:16 | Load | test.cpp:46:16:46:16 | Load | +| test.cpp:45:16:45:16 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:45:16:45:16 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:45:16:45:16 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:46:16:46:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:46:16:46:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:46:16:46:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:46:16:46:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:46:16:46:16 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:46:16:46:16 | Load | test.cpp:47:16:47:16 | Load | +| test.cpp:46:16:46:16 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:47:16:47:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:47:16:47:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:47:16:47:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:47:16:47:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:47:16:47:16 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:48:16:48:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:48:16:48:16 | Load | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:48:16:48:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:48:16:48:16 | Load | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:62:39:62:39 | Load | +| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:66:39:66:39 | Load | +| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:70:38:70:38 | Load | +| test.cpp:51:33:51:35 | Load indirection | test.cpp:60:34:60:37 | mk_array output argument | +| test.cpp:52:19:52:24 | call to malloc | test.cpp:51:7:51:14 | VariableAddress indirection | +| test.cpp:52:19:52:24 | call to malloc | test.cpp:53:12:53:16 | Load | +| test.cpp:53:5:53:23 | Store | test.cpp:51:33:51:35 | Load indirection | +| test.cpp:53:12:53:16 | Load | test.cpp:53:5:53:23 | Store | +| test.cpp:53:12:53:16 | Load | test.cpp:53:5:53:23 | Store | +| test.cpp:53:12:53:16 | Load | test.cpp:53:12:53:23 | ... + ... | +| test.cpp:53:12:53:16 | Load | test.cpp:53:12:53:23 | ... + ... | +| test.cpp:53:12:53:23 | ... + ... | test.cpp:51:33:51:35 | Load indirection | +| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:62:32:62:34 | Load | +| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:66:32:66:34 | Load | +| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:70:31:70:33 | Load | +| test.cpp:62:32:62:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | +| test.cpp:62:32:62:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | +| test.cpp:66:32:66:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | +| test.cpp:66:32:66:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | +| test.cpp:70:31:70:33 | Load | test.cpp:67:9:67:14 | Store: ... = ... | +| test.cpp:70:31:70:33 | Load | test.cpp:67:9:67:14 | Store: ... = ... | +| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:91:20:91:22 | arr indirection [begin] | +| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:95:20:95:22 | arr indirection [begin] | +| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:99:20:99:22 | arr indirection [begin] | +| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:119:18:119:25 | call to mk_array [begin] | +| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:91:36:91:38 | arr indirection [end] | +| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:95:36:95:38 | arr indirection [end] | +| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:99:35:99:37 | arr indirection [end] | +| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:119:18:119:25 | call to mk_array [end] | +| test.cpp:82:5:82:28 | Store | test.cpp:82:9:82:13 | arr indirection [post update] [begin] | +| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:80:9:80:16 | VariableAddress indirection [begin] | +| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:83:15:83:17 | arr indirection [begin] | +| test.cpp:82:17:82:22 | call to malloc | test.cpp:82:5:82:28 | Store | +| test.cpp:83:5:83:30 | Store | test.cpp:83:9:83:11 | arr indirection [post update] [end] | +| test.cpp:83:9:83:11 | arr indirection [post update] [end] | test.cpp:80:9:80:16 | VariableAddress indirection [end] | +| test.cpp:83:15:83:17 | arr indirection [begin] | test.cpp:83:19:83:23 | begin | +| test.cpp:83:15:83:30 | ... + ... | test.cpp:83:5:83:30 | Store | +| test.cpp:83:19:83:23 | Load | test.cpp:83:5:83:30 | Store | +| test.cpp:83:19:83:23 | Load | test.cpp:83:5:83:30 | Store | +| test.cpp:83:19:83:23 | Load | test.cpp:83:15:83:30 | ... + ... | +| test.cpp:83:19:83:23 | Load | test.cpp:83:15:83:30 | ... + ... | +| test.cpp:83:19:83:23 | begin | test.cpp:83:19:83:23 | Load | +| test.cpp:91:20:91:22 | arr indirection [begin] | test.cpp:91:24:91:28 | begin | +| test.cpp:91:20:91:22 | arr indirection [begin] | test.cpp:91:47:91:47 | Load | +| test.cpp:91:24:91:28 | begin | test.cpp:91:47:91:47 | Load | +| test.cpp:91:36:91:38 | arr indirection [end] | test.cpp:91:40:91:42 | end | +| test.cpp:91:40:91:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | +| test.cpp:91:40:91:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | +| test.cpp:91:40:91:42 | end | test.cpp:91:40:91:42 | Load | +| test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:24:95:28 | begin | +| test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:47:95:47 | Load | +| test.cpp:95:24:95:28 | begin | test.cpp:95:47:95:47 | Load | +| test.cpp:95:36:95:38 | arr indirection [end] | test.cpp:95:40:95:42 | end | +| test.cpp:95:40:95:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | +| test.cpp:95:40:95:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | +| test.cpp:95:40:95:42 | end | test.cpp:95:40:95:42 | Load | +| test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:24:99:28 | begin | +| test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:46:99:46 | Load | +| test.cpp:99:24:99:28 | begin | test.cpp:99:46:99:46 | Load | +| test.cpp:99:35:99:37 | arr indirection [end] | test.cpp:99:39:99:41 | end | +| test.cpp:99:39:99:41 | Load | test.cpp:96:9:96:14 | Store: ... = ... | +| test.cpp:99:39:99:41 | Load | test.cpp:96:9:96:14 | Store: ... = ... | +| test.cpp:99:39:99:41 | end | test.cpp:99:39:99:41 | Load | +| test.cpp:104:27:104:29 | arr [begin] | test.cpp:105:20:105:22 | arr indirection [begin] | +| test.cpp:104:27:104:29 | arr [begin] | test.cpp:109:20:109:22 | arr indirection [begin] | +| test.cpp:104:27:104:29 | arr [begin] | test.cpp:113:20:113:22 | arr indirection [begin] | +| test.cpp:104:27:104:29 | arr [end] | test.cpp:105:36:105:38 | arr indirection [end] | +| test.cpp:104:27:104:29 | arr [end] | test.cpp:109:36:109:38 | arr indirection [end] | +| test.cpp:104:27:104:29 | arr [end] | test.cpp:113:35:113:37 | arr indirection [end] | +| test.cpp:105:20:105:22 | arr indirection [begin] | test.cpp:105:24:105:28 | begin | +| test.cpp:105:20:105:22 | arr indirection [begin] | test.cpp:105:47:105:47 | Load | +| test.cpp:105:24:105:28 | begin | test.cpp:105:47:105:47 | Load | +| test.cpp:105:36:105:38 | arr indirection [end] | test.cpp:105:40:105:42 | end | +| test.cpp:105:40:105:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | +| test.cpp:105:40:105:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | +| test.cpp:105:40:105:42 | end | test.cpp:105:40:105:42 | Load | +| test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:24:109:28 | begin | +| test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:47:109:47 | Load | +| test.cpp:109:24:109:28 | begin | test.cpp:109:47:109:47 | Load | +| test.cpp:109:36:109:38 | arr indirection [end] | test.cpp:109:40:109:42 | end | +| test.cpp:109:40:109:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | +| test.cpp:109:40:109:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | +| test.cpp:109:40:109:42 | end | test.cpp:109:40:109:42 | Load | +| test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:24:113:28 | begin | +| test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:46:113:46 | Load | +| test.cpp:113:24:113:28 | begin | test.cpp:113:46:113:46 | Load | +| test.cpp:113:35:113:37 | arr indirection [end] | test.cpp:113:39:113:41 | end | +| test.cpp:113:39:113:41 | Load | test.cpp:110:9:110:14 | Store: ... = ... | +| test.cpp:113:39:113:41 | Load | test.cpp:110:9:110:14 | Store: ... = ... | +| test.cpp:113:39:113:41 | end | test.cpp:113:39:113:41 | Load | +| test.cpp:119:18:119:25 | call to mk_array [begin] | test.cpp:104:27:104:29 | arr [begin] | +| test.cpp:119:18:119:25 | call to mk_array [end] | test.cpp:104:27:104:29 | arr [end] | +| test.cpp:124:15:124:20 | call to malloc | test.cpp:125:5:125:17 | Store | +| test.cpp:124:15:124:20 | call to malloc | test.cpp:126:15:126:15 | Load | +| test.cpp:125:5:125:17 | Store | test.cpp:125:9:125:13 | arr indirection [post update] [begin] | +| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:129:11:129:13 | arr indirection [begin] | +| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:133:11:133:13 | arr indirection [begin] | +| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:137:11:137:13 | arr indirection [begin] | +| test.cpp:129:11:129:13 | arr indirection [begin] | test.cpp:129:15:129:19 | begin | +| test.cpp:129:15:129:19 | begin | test.cpp:129:15:129:19 | Load | +| test.cpp:133:11:133:13 | arr indirection [begin] | test.cpp:133:15:133:19 | begin | +| test.cpp:133:15:133:19 | begin | test.cpp:133:15:133:19 | Load | +| test.cpp:137:11:137:13 | arr indirection [begin] | test.cpp:137:15:137:19 | begin | +| test.cpp:137:15:137:19 | begin | test.cpp:137:15:137:19 | Load | +| test.cpp:141:10:141:19 | VariableAddress indirection [begin] | test.cpp:150:20:150:29 | Call indirection [begin] | +| test.cpp:141:10:141:19 | VariableAddress indirection [begin] | test.cpp:180:19:180:28 | call to mk_array_p indirection [begin] | +| test.cpp:141:10:141:19 | VariableAddress indirection [end] | test.cpp:150:20:150:29 | Call indirection [end] | +| test.cpp:141:10:141:19 | VariableAddress indirection [end] | test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | +| test.cpp:143:5:143:29 | Store | test.cpp:143:10:143:14 | Load indirection [post update] [begin] | +| test.cpp:143:10:143:14 | Load indirection [post update] [begin] | test.cpp:141:10:141:19 | VariableAddress indirection [begin] | +| test.cpp:143:10:143:14 | Load indirection [post update] [begin] | test.cpp:144:16:144:18 | Load indirection [begin] | +| test.cpp:143:18:143:23 | call to malloc | test.cpp:143:5:143:29 | Store | +| test.cpp:144:5:144:32 | Store | test.cpp:144:10:144:12 | Load indirection [post update] [end] | +| test.cpp:144:10:144:12 | Load indirection [post update] [end] | test.cpp:141:10:141:19 | VariableAddress indirection [end] | +| test.cpp:144:16:144:18 | Load indirection [begin] | test.cpp:144:21:144:25 | begin | +| test.cpp:144:16:144:32 | ... + ... | test.cpp:144:5:144:32 | Store | +| test.cpp:144:21:144:25 | Load | test.cpp:144:5:144:32 | Store | +| test.cpp:144:21:144:25 | Load | test.cpp:144:5:144:32 | Store | +| test.cpp:144:21:144:25 | Load | test.cpp:144:16:144:32 | ... + ... | +| test.cpp:144:21:144:25 | Load | test.cpp:144:16:144:32 | ... + ... | +| test.cpp:144:21:144:25 | begin | test.cpp:144:21:144:25 | Load | +| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:152:20:152:22 | Load indirection [begin] | +| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:156:20:156:22 | Load indirection [begin] | +| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:160:20:160:22 | Load indirection [begin] | +| test.cpp:150:20:150:29 | Call indirection [end] | test.cpp:156:37:156:39 | Load indirection [end] | +| test.cpp:152:20:152:22 | Load indirection [begin] | test.cpp:152:25:152:29 | begin | +| test.cpp:152:20:152:22 | Load indirection [begin] | test.cpp:152:49:152:49 | Load | +| test.cpp:152:25:152:29 | begin | test.cpp:152:49:152:49 | Load | +| test.cpp:156:20:156:22 | Load indirection [begin] | test.cpp:156:25:156:29 | begin | +| test.cpp:156:20:156:22 | Load indirection [begin] | test.cpp:156:49:156:49 | Load | +| test.cpp:156:25:156:29 | begin | test.cpp:156:49:156:49 | Load | +| test.cpp:156:37:156:39 | Load indirection [end] | test.cpp:156:42:156:44 | end | +| test.cpp:156:42:156:44 | Load | test.cpp:157:9:157:14 | Store: ... = ... | +| test.cpp:156:42:156:44 | Load | test.cpp:157:9:157:14 | Store: ... = ... | +| test.cpp:156:42:156:44 | end | test.cpp:156:42:156:44 | Load | +| test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:25:160:29 | begin | +| test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:48:160:48 | Load | +| test.cpp:160:25:160:29 | begin | test.cpp:160:48:160:48 | Load | +| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:166:20:166:22 | Load indirection [begin] | +| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:170:20:170:22 | Load indirection [begin] | +| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:174:20:174:22 | Load indirection [begin] | +| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:166:37:166:39 | Load indirection [end] | +| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:170:37:170:39 | Load indirection [end] | +| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:174:36:174:38 | Load indirection [end] | +| test.cpp:166:20:166:22 | Load indirection [begin] | test.cpp:166:25:166:29 | begin | +| test.cpp:166:20:166:22 | Load indirection [begin] | test.cpp:166:49:166:49 | Load | +| test.cpp:166:25:166:29 | begin | test.cpp:166:49:166:49 | Load | +| test.cpp:166:37:166:39 | Load indirection [end] | test.cpp:166:42:166:44 | end | +| test.cpp:166:42:166:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | +| test.cpp:166:42:166:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | +| test.cpp:166:42:166:44 | end | test.cpp:166:42:166:44 | Load | +| test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:25:170:29 | begin | +| test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:49:170:49 | Load | +| test.cpp:170:25:170:29 | begin | test.cpp:170:49:170:49 | Load | +| test.cpp:170:37:170:39 | Load indirection [end] | test.cpp:170:42:170:44 | end | +| test.cpp:170:42:170:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | +| test.cpp:170:42:170:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | +| test.cpp:170:42:170:44 | end | test.cpp:170:42:170:44 | Load | +| test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:25:174:29 | begin | +| test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:48:174:48 | Load | +| test.cpp:174:25:174:29 | begin | test.cpp:174:48:174:48 | Load | +| test.cpp:174:36:174:38 | Load indirection [end] | test.cpp:174:41:174:43 | end | +| test.cpp:174:41:174:43 | Load | test.cpp:171:9:171:14 | Store: ... = ... | +| test.cpp:174:41:174:43 | Load | test.cpp:171:9:171:14 | Store: ... = ... | +| test.cpp:174:41:174:43 | end | test.cpp:174:41:174:43 | Load | +| test.cpp:180:19:180:28 | call to mk_array_p indirection [begin] | test.cpp:165:29:165:31 | arr indirection [begin] | +| test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | test.cpp:165:29:165:31 | arr indirection [end] | +| test.cpp:188:15:188:20 | call to malloc | test.cpp:189:15:189:15 | Load | +#select +| test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size | +| test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size | +| test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size | +| test.cpp:20:14:20:21 | Load: * ... | test.cpp:16:15:16:20 | call to malloc | test.cpp:20:14:20:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:16:15:16:20 | call to malloc | call to malloc | test.cpp:17:19:17:22 | size | size | +| test.cpp:30:14:30:15 | Load: * ... | test.cpp:28:15:28:20 | call to malloc | test.cpp:30:14:30:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:28:15:28:20 | call to malloc | call to malloc | test.cpp:29:20:29:27 | ... + ... | ... + ... | +| test.cpp:32:14:32:21 | Load: * ... | test.cpp:28:15:28:20 | call to malloc | test.cpp:32:14:32:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:28:15:28:20 | call to malloc | call to malloc | test.cpp:29:20:29:27 | ... + ... | ... + ... | +| test.cpp:32:14:32:21 | Load: * ... | test.cpp:28:15:28:20 | call to malloc | test.cpp:32:14:32:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:28:15:28:20 | call to malloc | call to malloc | test.cpp:29:20:29:27 | ... + ... | ... + ... | +| test.cpp:42:14:42:15 | Load: * ... | test.cpp:40:15:40:20 | call to malloc | test.cpp:42:14:42:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:40:15:40:20 | call to malloc | call to malloc | test.cpp:41:20:41:27 | ... - ... | ... - ... | +| test.cpp:44:14:44:21 | Load: * ... | test.cpp:40:15:40:20 | call to malloc | test.cpp:44:14:44:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:40:15:40:20 | call to malloc | call to malloc | test.cpp:41:20:41:27 | ... - ... | ... - ... | +| test.cpp:44:14:44:21 | Load: * ... | test.cpp:40:15:40:20 | call to malloc | test.cpp:44:14:44:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:40:15:40:20 | call to malloc | call to malloc | test.cpp:41:20:41:27 | ... - ... | ... - ... | +| test.cpp:67:9:67:14 | Store: ... = ... | test.cpp:52:19:52:24 | call to malloc | test.cpp:67:9:67:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:52:19:52:24 | call to malloc | call to malloc | test.cpp:53:20:53:23 | size | size | +| test.cpp:96:9:96:14 | Store: ... = ... | test.cpp:82:17:82:22 | call to malloc | test.cpp:96:9:96:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:82:17:82:22 | call to malloc | call to malloc | test.cpp:83:27:83:30 | size | size | +| test.cpp:110:9:110:14 | Store: ... = ... | test.cpp:82:17:82:22 | call to malloc | test.cpp:110:9:110:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:82:17:82:22 | call to malloc | call to malloc | test.cpp:83:27:83:30 | size | size | +| test.cpp:157:9:157:14 | Store: ... = ... | test.cpp:143:18:143:23 | call to malloc | test.cpp:157:9:157:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:143:18:143:23 | call to malloc | call to malloc | test.cpp:144:29:144:32 | size | size | +| test.cpp:171:9:171:14 | Store: ... = ... | test.cpp:143:18:143:23 | call to malloc | test.cpp:171:9:171:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:143:18:143:23 | call to malloc | call to malloc | test.cpp:144:29:144:32 | size | size | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.qlref new file mode 100644 index 00000000000..76da29dc7a0 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp new file mode 100644 index 00000000000..809c348c0b0 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp @@ -0,0 +1,191 @@ +char *malloc(int size); + +void test1(int size) { + char* p = malloc(size); + char* q = p + size; + char a = *q; // BAD + char b = *(q - 1); // GOOD + char c = *(q + 1); // BAD + char d = *(q + size); // BAD [NOT DETECTED] + char e = *(q - size); // GOOD + char f = *(q + size + 1); // BAD [NOT DETECTED] + char g = *(q - size - 1); // GOOD +} + +void test2(int size) { + char* p = malloc(size); + char* q = p + size - 1; + char a = *q; // GOOD + char b = *(q - 1); // GOOD + char c = *(q + 1); // BAD + char d = *(q + size); // BAD [NOT DETECTED] + char e = *(q - size); // GOOD + char f = *(q + size + 1); // BAD [NOT DETECTED] + char g = *(q - size - 1); // GOOD +} + +void test3(int size) { + char* p = malloc(size + 1); + char* q = p + (size + 1); + char a = *q; // BAD + char b = *(q - 1); // GOOD + char c = *(q + 1); // BAD + char d = *(q + size); // BAD [NOT DETECTED] + char e = *(q - size); // GOOD + char f = *(q + size + 1); // BAD [NOT DETECTED] + char g = *(q - size - 1); // GOOD +} + +void test4(int size) { + char* p = malloc(size - 1); + char* q = p + (size - 1); + char a = *q; // BAD + char b = *(q - 1); // GOOD + char c = *(q + 1); // BAD + char d = *(q + size); // BAD [NOT DETECTED] + char e = *(q - size); // GOOD + char f = *(q + size + 1); // BAD [NOT DETECTED] + char g = *(q - size - 1); // GOOD +} + +char* mk_array(int size, char** end) { + char* begin = malloc(size); + *end = begin + size; + + return begin; +} + +void test5(int size) { + char* end; + char* begin = mk_array(size, &end); + + for (char* p = begin; p != end; ++p) { + *p = 0; // GOOD + } + + for (char* p = begin; p <= end; ++p) { + *p = 0; // BAD + } + + for (char* p = begin; p < end; ++p) { + *p = 0; // GOOD + } +} + +struct array_t { + char* begin; + char* end; +}; + +array_t mk_array(int size) { + array_t arr; + arr.begin = malloc(size); + arr.end = arr.begin + size; + + return arr; +} + +void test6(int size) { + array_t arr = mk_array(size); + + for (char* p = arr.begin; p != arr.end; ++p) { + *p = 0; // GOOD + } + + for (char* p = arr.begin; p <= arr.end; ++p) { + *p = 0; // BAD + } + + for (char* p = arr.begin; p < arr.end; ++p) { + *p = 0; // GOOD + } +} + +void test7_callee(array_t arr) { + for (char* p = arr.begin; p != arr.end; ++p) { + *p = 0; // GOOD + } + + for (char* p = arr.begin; p <= arr.end; ++p) { + *p = 0; // BAD + } + + for (char* p = arr.begin; p < arr.end; ++p) { + *p = 0; // GOOD + } +} + +void test7(int size) { + test7_callee(mk_array(size)); +} + +void test8(int size) { + array_t arr; + char* p = malloc(size); + arr.begin = p; + arr.end = p + size; + + for (int i = 0; i < arr.end - arr.begin; i++) { + *(arr.begin + i) = 0; // GOOD + } + + for (int i = 0; i != arr.end - arr.begin; i++) { + *(arr.begin + i) = 0; // GOOD + } + + for (int i = 0; i <= arr.end - arr.begin; i++) { + *(arr.begin + i) = 0; // BAD [NOT DETECTED] + } +} + +array_t *mk_array_p(int size) { + array_t *arr = (array_t*) malloc(sizeof(array_t)); + arr->begin = malloc(size); + arr->end = arr->begin + size; + + return arr; +} + +void test9(int size) { + array_t *arr = mk_array_p(size); + + for (char* p = arr->begin; p != arr->end; ++p) { + *p = 0; // GOOD + } + + for (char* p = arr->begin; p <= arr->end; ++p) { + *p = 0; // BAD + } + + for (char* p = arr->begin; p < arr->end; ++p) { + *p = 0; // GOOD + } +} + +void test10_callee(array_t *arr) { + for (char* p = arr->begin; p != arr->end; ++p) { + *p = 0; // GOOD + } + + for (char* p = arr->begin; p <= arr->end; ++p) { + *p = 0; // BAD + } + + for (char* p = arr->begin; p < arr->end; ++p) { + *p = 0; // GOOD + } +} + +void test10(int size) { + test10_callee(mk_array_p(size)); +} + +void deref_plus_one(char* q) { + char a = *(q + 1); // BAD [NOT DETECTED] +} + +void test11(unsigned size) { + char *p = malloc(size); + char *q = p + size - 1; + deref_plus_one(q); +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/UsingExpiredStackAddress.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/UsingExpiredStackAddress.expected index 80d09858338..955668b4e7a 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/UsingExpiredStackAddress.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/UsingExpiredStackAddress.expected @@ -64,6 +64,10 @@ edges | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p | | test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | | test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p | +| test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:238:3:238:9 | Call: call to escape2 | +| test.cpp:238:3:238:9 | Call: call to escape2 | test.cpp:239:17:239:17 | Load: p | +| test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:267:3:267:9 | Call: call to escape3 | +| test.cpp:267:3:267:9 | Call: call to escape3 | test.cpp:268:17:268:17 | Load: p | #select | test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here | | test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here | @@ -90,3 +94,5 @@ edges | test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here | | test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here | | test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here | +| test.cpp:239:17:239:17 | Load: p | test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:239:17:239:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:232:7:232:7 | x | x | test.cpp:234:3:234:13 | Store: ... = ... | here | +| test.cpp:268:17:268:17 | Load: p | test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:268:17:268:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:260:7:260:7 | x | x | test.cpp:263:3:263:13 | Store: ... = ... | here | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/test.cpp index 3e8a7e90b84..616305a8174 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/test.cpp @@ -209,4 +209,61 @@ int maybe_deref_p(bool b) { int field_indirect_maybe_bad(bool b) { escape1(); return maybe_deref_p(b); +} + +// These next tests cover subsequent stores to the same address in the same basic block. + +static struct S100 s102; + +void not_escape1() { + int x; + s102.p = &x; + s102.p = nullptr; +} + +void calls_not_escape1() { + not_escape1(); + int x = *s102.p; // GOOD +} + +static struct S100 s103; + +void escape2() { + int x; + s103.p = nullptr; + s103.p = &x; +} + +void calls_escape2() { + escape2(); + int x = *s103.p; // BAD +} + +bool unknown(); +static struct S100 s104; + +void not_escape2() { + int x; + s104.p = &x; + if(unknown()) { } + s104.p = nullptr; +} + +void calls_not_escape2() { + not_escape2(); + int x = *s104.p; // GOOD +} + +static struct S100 s105; + +void escape3() { + int x; + s105.p = nullptr; + if(unknown()) { } + s105.p = &x; +} + +void calls_escape3() { + escape3(); + int x = *s105.p; // BAD } \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.expected index 5fc5f82768e..9a3747dd2df 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.expected @@ -1,5 +1,4 @@ edges -| test2.cpp:52:44:52:57 | password_tries | test2.cpp:52:40:52:58 | * ... | | test2.cpp:62:18:62:25 | password | test2.cpp:65:31:65:34 | cpy1 | | test2.cpp:72:17:72:24 | password | test2.cpp:73:30:73:32 | buf | | test2.cpp:72:17:72:24 | password | test2.cpp:76:30:76:32 | buf | @@ -9,8 +8,6 @@ nodes | test2.cpp:44:37:44:45 | thepasswd | semmle.label | thepasswd | | test2.cpp:45:38:45:47 | accountkey | semmle.label | accountkey | | test2.cpp:50:41:50:53 | passwd_config | semmle.label | passwd_config | -| test2.cpp:52:40:52:58 | * ... | semmle.label | * ... | -| test2.cpp:52:44:52:57 | password_tries | semmle.label | password_tries | | test2.cpp:54:41:54:52 | widepassword | semmle.label | widepassword | | test2.cpp:55:40:55:51 | widepassword | semmle.label | widepassword | | test2.cpp:57:39:57:49 | call to getPassword | semmle.label | call to getPassword | diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md index 072581ceeec..d993fc0868f 100644 --- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.2.5 + ## 1.2.4 ## 1.2.3 diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.2.5.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.2.5.md new file mode 100644 index 00000000000..e040f831239 --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.2.5.md @@ -0,0 +1 @@ +## 1.2.5 diff --git a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml index 172090f46b6..40355f0807f 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.2.4 +lastReleaseVersion: 1.2.5 diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index db606ea8fbe..6d33146531d 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.2.5-dev +version: 1.2.6-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md index 072581ceeec..d993fc0868f 100644 --- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.2.5 + ## 1.2.4 ## 1.2.3 diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.2.5.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.2.5.md new file mode 100644 index 00000000000..e040f831239 --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.2.5.md @@ -0,0 +1 @@ +## 1.2.5 diff --git a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml index 172090f46b6..40355f0807f 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.2.4 +lastReleaseVersion: 1.2.5 diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 1eab4e25bb0..0b31bb4af53 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.2.5-dev +version: 1.2.6-dev groups: - csharp - solorigate diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_pack/Program.cs b/csharp/ql/integration-tests/all-platforms/dotnet_pack/Program.cs new file mode 100644 index 00000000000..3751555cbd3 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/dotnet_pack/Program.cs @@ -0,0 +1,2 @@ +// See https://aka.ms/new-console-template for more information +Console.WriteLine("Hello, World!"); diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_pack/dotnet_pack.csproj b/csharp/ql/integration-tests/all-platforms/dotnet_pack/dotnet_pack.csproj new file mode 100644 index 00000000000..74abf5c9766 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/dotnet_pack/dotnet_pack.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_pack/test.py b/csharp/ql/integration-tests/all-platforms/dotnet_pack/test.py new file mode 100644 index 00000000000..9eac6efe388 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/dotnet_pack/test.py @@ -0,0 +1,8 @@ +import os +from create_database_utils import * + +run_codeql_database_create(['dotnet pack'], test_db="default-db", db=None, lang="csharp") + +## Check that the NuGet package is created. +if not os.path.isfile("bin/Debug/dotnet_pack.1.0.0.nupkg"): + raise Exception("The NuGet package was not created.") diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_publish/Program.cs b/csharp/ql/integration-tests/all-platforms/dotnet_publish/Program.cs new file mode 100644 index 00000000000..3751555cbd3 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/dotnet_publish/Program.cs @@ -0,0 +1,2 @@ +// See https://aka.ms/new-console-template for more information +Console.WriteLine("Hello, World!"); diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_publish/dotnet_publish.csproj b/csharp/ql/integration-tests/all-platforms/dotnet_publish/dotnet_publish.csproj new file mode 100644 index 00000000000..74abf5c9766 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/dotnet_publish/dotnet_publish.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_publish/test.py b/csharp/ql/integration-tests/all-platforms/dotnet_publish/test.py new file mode 100644 index 00000000000..ad040a8932b --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/dotnet_publish/test.py @@ -0,0 +1,8 @@ +import os +from create_database_utils import * + +run_codeql_database_create(['dotnet publish'], test_db="default-db", db=None, lang="csharp") + +## Check that the publish folder is created. +if not os.path.isdir("bin/Debug/net6.0/publish/"): + raise Exception("The publish artifact folder was not created.") diff --git a/csharp/ql/integration-tests/posix-only/dotnet_test/UnitTest1.cs b/csharp/ql/integration-tests/posix-only/dotnet_test/UnitTest1.cs new file mode 100644 index 00000000000..4a8e236a7a0 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/dotnet_test/UnitTest1.cs @@ -0,0 +1,17 @@ +using NUnit.Framework; + +namespace dotnet_test; + +public class Tests +{ + [SetUp] + public void Setup() + { + } + + [Test] + public void Test1() + { + Assert.Pass(); + } +} \ No newline at end of file diff --git a/csharp/ql/integration-tests/posix-only/dotnet_test/dotnet_test.csproj b/csharp/ql/integration-tests/posix-only/dotnet_test/dotnet_test.csproj new file mode 100644 index 00000000000..50852359bb8 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/dotnet_test/dotnet_test.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + + false + + + + + + + + + + diff --git a/csharp/ql/integration-tests/posix-only/dotnet_test/test.py b/csharp/ql/integration-tests/posix-only/dotnet_test/test.py new file mode 100644 index 00000000000..6e3cdab30f7 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/dotnet_test/test.py @@ -0,0 +1,3 @@ +from create_database_utils import * + +run_codeql_database_create(['dotnet test'], test_db="default-db", db=None, lang="csharp") \ No newline at end of file diff --git a/csharp/ql/integration-tests/all-platforms/qlpack.yml b/csharp/ql/integration-tests/qlpack.yml similarity index 100% rename from csharp/ql/integration-tests/all-platforms/qlpack.yml rename to csharp/ql/integration-tests/qlpack.yml diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md index bae0baebc1d..4b79fb8ee02 100644 --- a/csharp/ql/lib/CHANGELOG.md +++ b/csharp/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.5 + ## 0.3.4 ### Deprecated APIs diff --git a/csharp/ql/lib/change-notes/2022-09-12-uppercase.md b/csharp/ql/lib/change-notes/2022-09-12-uppercase.md new file mode 100644 index 00000000000..996861f1c2c --- /dev/null +++ b/csharp/ql/lib/change-notes/2022-09-12-uppercase.md @@ -0,0 +1,5 @@ +--- +category: deprecated +--- +* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide. + The old name still exists as a deprecated alias. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/released/0.3.5.md b/csharp/ql/lib/change-notes/released/0.3.5.md new file mode 100644 index 00000000000..88b60b4e980 --- /dev/null +++ b/csharp/ql/lib/change-notes/released/0.3.5.md @@ -0,0 +1 @@ +## 0.3.5 diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml index 5ed15c24b9c..468917f2543 100644 --- a/csharp/ql/lib/codeql-pack.release.yml +++ b/csharp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.4 +lastReleaseVersion: 0.3.5 diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index ca88b27e42f..7716eb77741 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 0.3.5-dev +version: 0.3.6-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/lib/semmle/code/cil/CallableReturns.qll b/csharp/ql/lib/semmle/code/cil/CallableReturns.qll index 6a86ef72170..4cd46c10941 100644 --- a/csharp/ql/lib/semmle/code/cil/CallableReturns.qll +++ b/csharp/ql/lib/semmle/code/cil/CallableReturns.qll @@ -56,7 +56,7 @@ private predicate alwaysNotNullVariableUpdate(VariableUpdate vu) { /** Holds if expression `expr` always evaluates to non-null. */ private predicate alwaysNotNullExpr(Expr expr) { - expr instanceof Opcodes::Newobj + expr instanceof Opcodes::NewObj or expr instanceof Literal and not expr instanceof NullLiteral or diff --git a/csharp/ql/lib/semmle/code/cil/Instructions.qll b/csharp/ql/lib/semmle/code/cil/Instructions.qll index 91bc1f37ea6..7d425594b8d 100644 --- a/csharp/ql/lib/semmle/code/cil/Instructions.qll +++ b/csharp/ql/lib/semmle/code/cil/Instructions.qll @@ -766,7 +766,7 @@ module Opcodes { } /** A `newobj` instruction. */ - class Newobj extends Call, @cil_newobj { + class NewObj extends Call, @cil_newobj { override string getOpcodeName() { result = "newobj" } override int getPushCount() { result = 1 } @@ -788,6 +788,9 @@ module Opcodes { } } + /** DEPRECATED: Alias for NewObj */ + deprecated class Newobj = NewObj; + /** An `initobj` instruction. */ class Initobj extends Instruction, @cil_initobj { override string getOpcodeName() { result = "initobj" } @@ -847,10 +850,13 @@ module Opcodes { } /** A `rethrow` instruction. */ - class Rethrow extends Throw, @cil_rethrow { + class ReThrow extends Throw, @cil_rethrow { override string getOpcodeName() { result = "rethrow" } } + /** DEPRECATED: Alias for ReThrow */ + deprecated class Rethrow = ReThrow; + /** A `ldlen` instruction. */ class Ldlen extends UnaryExpr, @cil_ldlen { override string getOpcodeName() { result = "ldlen" } diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md index 60b637b99cd..121f81270df 100644 --- a/csharp/ql/src/CHANGELOG.md +++ b/csharp/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.4 + ## 0.3.3 ### Minor Analysis Improvements diff --git a/csharp/ql/src/change-notes/released/0.3.4.md b/csharp/ql/src/change-notes/released/0.3.4.md new file mode 100644 index 00000000000..d62a8a1780d --- /dev/null +++ b/csharp/ql/src/change-notes/released/0.3.4.md @@ -0,0 +1 @@ +## 0.3.4 diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml index 9da182d3394..5ed15c24b9c 100644 --- a/csharp/ql/src/codeql-pack.release.yml +++ b/csharp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.3 +lastReleaseVersion: 0.3.4 diff --git a/csharp/ql/src/experimental/ir/implementation/internal/AliasedSSAStub.qll b/csharp/ql/src/experimental/ir/implementation/internal/AliasedSSAStub.qll index 0fedd38bfbd..6fca9e3b974 100644 --- a/csharp/ql/src/experimental/ir/implementation/internal/AliasedSSAStub.qll +++ b/csharp/ql/src/experimental/ir/implementation/internal/AliasedSSAStub.qll @@ -6,7 +6,7 @@ private import IRFunctionBase private import TInstruction -module SSA { +module Ssa { class MemoryLocation = boolean; predicate hasPhiInstruction(TRawInstruction blockStartInstr, MemoryLocation memoryLocation) { @@ -17,3 +17,6 @@ module SSA { predicate hasUnreachedInstruction(IRFunctionBase irFunc) { none() } } + +/** DEPRECATED: Alias for Ssa */ +deprecated module SSA = Ssa; diff --git a/csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll b/csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll index b30372a791b..5564a16f215 100644 --- a/csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll @@ -20,24 +20,24 @@ newtype TInstruction = IRConstruction::Raw::hasInstruction(tag1, tag2) } or TUnaliasedSsaPhiInstruction( - TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation + TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation ) { - UnaliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) + UnaliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation) } or TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { - UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc) + UnaliasedSsa::Ssa::hasUnreachedInstruction(irFunc) } or TAliasedSsaPhiInstruction( - TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation + TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation ) { - AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) + AliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation) } or TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) { - AliasedSsa::SSA::hasChiInstruction(primaryInstruction) + AliasedSsa::Ssa::hasChiInstruction(primaryInstruction) } or TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { - AliasedSsa::SSA::hasUnreachedInstruction(irFunc) + AliasedSsa::Ssa::hasUnreachedInstruction(irFunc) } /** @@ -50,7 +50,7 @@ module UnaliasedSsaInstructions { class TPhiInstruction = TUnaliasedSsaPhiInstruction; TPhiInstruction phiInstruction( - TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation + TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation ) { result = TUnaliasedSsaPhiInstruction(blockStartInstr, memoryLocation) } @@ -83,7 +83,7 @@ module AliasedSsaInstructions { class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction; TPhiInstruction phiInstruction( - TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation + TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation ) { result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation) } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll index 1c75529be00..873a3c635f8 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll @@ -1,2 +1,2 @@ -private import SSAConstruction as SSA -import SSA::SsaConsistency +private import SSAConstruction as Ssa +import Ssa::SsaConsistency diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 901735069c0..21c03e176a5 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -1135,7 +1135,7 @@ deprecated module SSAConsistency = SsaConsistency; * These predicates are all just aliases for predicates defined in the `Cached` module. This ensures * that all of SSA construction will be evaluated in the same stage. */ -module SSA { +module Ssa { class MemoryLocation = Alias::MemoryLocation; predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2; @@ -1144,3 +1144,6 @@ module SSA { predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1; } + +/** DEPRECATED: Alias for Ssa */ +deprecated module SSA = Ssa; diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index 1cc369a1319..2bd1377630e 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 0.3.4-dev +version: 0.3.5-dev groups: - csharp - queries diff --git a/csharp/ql/src/utils/model-generator/CaptureDiscardedSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureDiscardedSummaryModels.ql index 6276f9793dc..b9e0cc23987 100644 --- a/csharp/ql/src/utils/model-generator/CaptureDiscardedSummaryModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureDiscardedSummaryModels.ql @@ -4,10 +4,10 @@ * @id csharp/utils/model-generator/discarded-summary-models */ -private import semmle.code.csharp.dataflow.ExternalFlow -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import semmle.code.csharp.dataflow.ExternalFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string flow +from DataFlowTargetApi api, string flow where flow = captureFlow(api) and hasSummary(api, false) select flow order by flow diff --git a/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql index 09202f423ea..0e26d3eee7f 100644 --- a/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql @@ -6,10 +6,12 @@ * @tags model-generator */ -private import semmle.code.csharp.dataflow.ExternalFlow -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import semmle.code.csharp.dataflow.ExternalFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string noflow -where noflow = captureNoFlow(api) and not hasSummary(api, false) +from DataFlowTargetApi api, string noflow +where + noflow = captureNoFlow(api) and + not hasSummary(api, false) select noflow order by noflow diff --git a/csharp/ql/src/utils/model-generator/CaptureSinkModels.ql b/csharp/ql/src/utils/model-generator/CaptureSinkModels.ql index 03eeeeda273..ea249016427 100644 --- a/csharp/ql/src/utils/model-generator/CaptureSinkModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureSinkModels.ql @@ -6,8 +6,8 @@ * @tags model-generator */ -private import internal.CaptureModels +import internal.CaptureModels -from TargetApi api, string sink +from DataFlowTargetApi api, string sink where sink = captureSink(api) select sink order by sink diff --git a/csharp/ql/src/utils/model-generator/CaptureSourceModels.ql b/csharp/ql/src/utils/model-generator/CaptureSourceModels.ql index f60682b2b6d..72ce31d4b61 100644 --- a/csharp/ql/src/utils/model-generator/CaptureSourceModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureSourceModels.ql @@ -6,8 +6,8 @@ * @tags model-generator */ -private import internal.CaptureModels +import internal.CaptureModels -from TargetApi api, string source +from DataFlowTargetApi api, string source where source = captureSource(api) select source order by source diff --git a/csharp/ql/src/utils/model-generator/CaptureSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureSummaryModels.ql index f6c91335428..f308c57c89d 100644 --- a/csharp/ql/src/utils/model-generator/CaptureSummaryModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureSummaryModels.ql @@ -6,10 +6,10 @@ * @tags model-generator */ -private import semmle.code.csharp.dataflow.ExternalFlow -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import semmle.code.csharp.dataflow.ExternalFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string flow +from DataFlowTargetApi api, string flow where flow = captureFlow(api) and not hasSummary(api, false) select flow order by flow diff --git a/csharp/ql/src/utils/model-generator/CaptureTypeBasedSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureTypeBasedSummaryModels.ql new file mode 100644 index 00000000000..e3dcc9dc2f6 --- /dev/null +++ b/csharp/ql/src/utils/model-generator/CaptureTypeBasedSummaryModels.ql @@ -0,0 +1,14 @@ +/** + * @name Capture typed based summary models. + * @description Finds applicable summary models to be used by other queries. + * @kind diagnostic + * @id cs/utils/model-generator/summary-models-typed-based + * @tags model-generator + */ + +import semmle.code.csharp.dataflow.ExternalFlow +import internal.CaptureTypeBasedSummaryModels + +from TypeBasedFlowTargetApi api, string flow +where flow = captureFlow(api) +select flow order by flow diff --git a/csharp/ql/src/utils/model-generator/internal/CaptureModels.qll b/csharp/ql/src/utils/model-generator/internal/CaptureModels.qll index c6ebc854edb..82c6fbd1bbb 100644 --- a/csharp/ql/src/utils/model-generator/internal/CaptureModels.qll +++ b/csharp/ql/src/utils/model-generator/internal/CaptureModels.qll @@ -5,7 +5,9 @@ private import CaptureModelsSpecific -class TargetApi = TargetApiSpecific; +class DataFlowTargetApi extends TargetApiSpecific { + DataFlowTargetApi() { isRelevantForDataFlowModels(this) } +} /** * Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`. @@ -40,7 +42,7 @@ private predicate isRelevantContent(DataFlow::Content c) { * Gets the summary model for `api` with `input`, `output` and `kind`. */ bindingset[input, output, kind] -private string asSummaryModel(TargetApi api, string input, string output, string kind) { +private string asSummaryModel(TargetApiSpecific api, string input, string output, string kind) { result = asPartialModel(api) + input + ";" // + output + ";" // @@ -48,13 +50,15 @@ private string asSummaryModel(TargetApi api, string input, string output, string + "generated" } -string asNegativeSummaryModel(TargetApi api) { result = asPartialNegativeModel(api) + "generated" } +string asNegativeSummaryModel(TargetApiSpecific api) { + result = asPartialNegativeModel(api) + "generated" +} /** * Gets the value summary model for `api` with `input` and `output`. */ bindingset[input, output] -private string asValueModel(TargetApi api, string input, string output) { +string asValueModel(TargetApiSpecific api, string input, string output) { result = asSummaryModel(api, input, output, "value") } @@ -62,7 +66,7 @@ private string asValueModel(TargetApi api, string input, string output) { * Gets the taint summary model for `api` with `input` and `output`. */ bindingset[input, output] -private string asTaintModel(TargetApi api, string input, string output) { +private string asTaintModel(TargetApiSpecific api, string input, string output) { result = asSummaryModel(api, input, output, "taint") } @@ -70,7 +74,7 @@ private string asTaintModel(TargetApi api, string input, string output) { * Gets the sink model for `api` with `input` and `kind`. */ bindingset[input, kind] -private string asSinkModel(TargetApi api, string input, string kind) { +private string asSinkModel(TargetApiSpecific api, string input, string kind) { result = asPartialModel(api) + input + ";" // + kind + ";" // @@ -81,7 +85,7 @@ private string asSinkModel(TargetApi api, string input, string kind) { * Gets the source model for `api` with `output` and `kind`. */ bindingset[output, kind] -private string asSourceModel(TargetApi api, string output, string kind) { +private string asSourceModel(TargetApiSpecific api, string output, string kind) { result = asPartialModel(api) + output + ";" // + kind + ";" // @@ -91,7 +95,7 @@ private string asSourceModel(TargetApi api, string output, string kind) { /** * Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`). */ -string captureQualifierFlow(TargetApi api) { +string captureQualifierFlow(TargetApiSpecific api) { exists(DataFlowImplCommon::ReturnNodeExt ret | api = returnNodeEnclosingCallable(ret) and isOwnInstanceAccessNode(ret) @@ -140,7 +144,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { source instanceof DataFlow::ParameterNode and - source.getEnclosingCallable() instanceof TargetApi and + source.getEnclosingCallable() instanceof DataFlowTargetApi and state.(TaintRead).getStep() = 0 } @@ -184,7 +188,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { /** * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. */ -string captureThroughFlow(TargetApi api) { +string captureThroughFlow(DataFlowTargetApi api) { exists( ThroughFlowConfig config, DataFlow::ParameterNode p, DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output @@ -211,7 +215,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) } override predicate isSink(DataFlow::Node sink) { - exists(TargetApi c | + exists(DataFlowTargetApi c | sink instanceof DataFlowImplCommon::ReturnNodeExt and sink.getEnclosingCallable() = c ) @@ -229,7 +233,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration { /** * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`. */ -string captureSource(TargetApi api) { +string captureSource(DataFlowTargetApi api) { exists(DataFlow::Node source, DataFlow::Node sink, FromSourceConfiguration config, string kind | config.hasFlow(source, sink) and ExternalFlow::sourceNode(source, kind) and @@ -259,7 +263,7 @@ private class PropagateToSinkConfiguration extends PropagateToSinkConfigurationS /** * Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink. */ -string captureSink(TargetApi api) { +string captureSink(DataFlowTargetApi api) { exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind | config.hasFlow(src, sink) and ExternalFlow::sinkNode(sink, kind) and diff --git a/csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll b/csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll index 57407dcc391..3b0a33336c0 100644 --- a/csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll +++ b/csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll @@ -36,10 +36,21 @@ private predicate isRelevantForModels(CS::Callable api) { api.getDeclaringType().getNamespace().getQualifiedName() != "" and not api instanceof CS::ConversionOperator and not api instanceof Util::MainMethod and - not isHigherOrder(api) and not api instanceof CS::Destructor } +/** + * Holds if it is relevant to generate models for `api` based on data flow analysis. + */ +predicate isRelevantForDataFlowModels(CS::Callable api) { + isRelevantForModels(api) and not isHigherOrder(api) +} + +/** + * Holds if it is relevant to generate models for `api` based on its type. + */ +predicate isRelevantForTypeBasedFlowModels = isRelevantForModels/1; + /** * A class of callables that are relevant generating summary, source and sinks models for. * @@ -49,8 +60,7 @@ private predicate isRelevantForModels(CS::Callable api) { class TargetApiSpecific extends DotNet::Callable { TargetApiSpecific() { this.fromSource() and - this.isUnboundDeclaration() and - isRelevantForModels(this) + this.isUnboundDeclaration() } } @@ -100,7 +110,7 @@ predicate isRelevantType(CS::Type t) { */ string qualifierString() { result = "Argument[this]" } -private string parameterAccess(CS::Parameter p) { +string parameterAccess(CS::Parameter p) { if Collections::isCollectionType(p.getType()) then result = "Argument[" + p.getPosition() + "].Element" else result = "Argument[" + p.getPosition() + "]" diff --git a/csharp/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll b/csharp/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll index 65a5181ee89..e06ea1a609a 100644 --- a/csharp/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll +++ b/csharp/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll @@ -75,7 +75,7 @@ private import CaptureModels * Captured Model: * ```Summaries;BasicFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint``` */ -string captureFlow(TargetApi api) { +string captureFlow(DataFlowTargetApi api) { result = captureQualifierFlow(api) or result = captureThroughFlow(api) } @@ -84,7 +84,7 @@ string captureFlow(TargetApi api) { * Gets the negative summary for `api`, if any. * A negative summary is generated, if there does not exist any positive flow. */ -string captureNoFlow(TargetApi api) { +string captureNoFlow(DataFlowTargetApi api) { not exists(captureFlow(api)) and result = asNegativeSummaryModel(api) } diff --git a/csharp/ql/src/utils/model-generator/internal/CaptureTypeBasedSummaryModels.qll b/csharp/ql/src/utils/model-generator/internal/CaptureTypeBasedSummaryModels.qll new file mode 100644 index 00000000000..02f00986c3c --- /dev/null +++ b/csharp/ql/src/utils/model-generator/internal/CaptureTypeBasedSummaryModels.qll @@ -0,0 +1,224 @@ +private import csharp +private import dotnet +private import semmle.code.csharp.frameworks.system.collections.Generic as GenericCollections +private import semmle.code.csharp.dataflow.internal.DataFlowPrivate +private import semmle.code.csharp.frameworks.system.linq.Expressions +private import CaptureModelsSpecific as Specific +private import CaptureModels + +/** + * Holds if `t` is a subtype (reflexive/transitive) of `IEnumerable`, where `T` = `tp`. + */ +private predicate genericCollectionType(ValueOrRefType t, TypeParameter tp) { + exists(ConstructedGeneric t2 | + t2 = t.getABaseType*() and + t2.getUnboundDeclaration() instanceof + GenericCollections::SystemCollectionsGenericIEnumerableTInterface and + tp = t2.getATypeArgument() + ) +} + +/** + * Holds if `tp` is a type parameter of the immediate type declaring `callable`. + */ +private predicate classTypeParameter(DotNet::Callable callable, TypeParameter tp) { + callable.getDeclaringType().(UnboundGeneric).getATypeParameter() = tp +} + +/** + * Holds if `tp` is type parameter of `callable` or the type declaring `callable`. + */ +private predicate localTypeParameter(DotNet::Callable callable, TypeParameter tp) { + classTypeParameter(callable, tp) or + callable.(UnboundGeneric).getATypeParameter() = tp +} + +/** + * Holds if `callable` has a parameter of type `tp` + * or collection parameterized over type `tp`. + */ +private predicate parameter(DotNet::Callable callable, string input, TypeParameter tp) { + exists(Parameter p | + input = Specific::parameterAccess(p) and + p = callable.getAParameter() and + ( + // Parameter of type tp + p.getType() = tp + or + // Parameter is a collection of type tp + genericCollectionType(p.getType(), tp) + ) + ) +} + +/** + * Gets the string representation of a synthetic field corresponding to `tp`. + */ +private string getSyntheticField(TypeParameter tp) { + result = ".SyntheticField[ArgType" + tp.getIndex() + "]" +} + +/** + * Gets a models as data string representation of, how a value of type `tp` + * can be read or stored implicitly in relation to `callable`. + */ +private string implicit(DotNet::Callable callable, TypeParameter tp) { + classTypeParameter(callable, tp) and + exists(string access | + if genericCollectionType(callable.getDeclaringType(), tp) + then access = ".Element" + else access = getSyntheticField(tp) + | + result = Specific::qualifierString() + access + ) +} + +/** + * Holds if `callable` has a delegate parameter `dt` at parameter position `position`. + */ +private predicate delegate(DotNet::Callable callable, DelegateType dt, int position) { + exists(Parameter p | + p = callable.getAParameter() and + dt = p.getType().(SystemLinqExpressions::DelegateExtType).getDelegateType() and + position = p.getPosition() + ) +} + +/** + * Gets models as data input/output access relative to the type parameter `tp` in the + * type `t` in the scope of `callable`. + * + * Note: This predicate has to be inlined as `callable` is not related to `return` or `tp` + * in every disjunction. + */ +bindingset[callable] +private string getAccess(DotNet::Callable callable, Type return, TypeParameter tp) { + return = tp and result = "" + or + genericCollectionType(return, tp) and result = ".Element" + or + not genericCollectionType(return, tp) and + ( + return.(ConstructedGeneric).getATypeArgument() = tp + or + callable.getDeclaringType() = return and return.(UnboundGeneric).getATypeParameter() = tp + ) and + result = getSyntheticField(tp) +} + +/** + * Holds if `input` is a models as data string representation of, how a value of type `tp` + * (or a generic parameterized over `tp`) can be generated by a delegate parameter of `callable`. + */ +private predicate delegateSource(DotNet::Callable callable, string input, TypeParameter tp) { + exists(DelegateType dt, int position, Type return, string access | + delegate(callable, dt, position) and + return = dt.getReturnType() and + access = getAccess(callable, return, tp) and + input = "Argument[" + position + "].ReturnValue" + access + ) +} + +/** + * Holds if `input` is a models as data string representation of, how a + * value of type `tp` (or a generic parameterized over `tp`) + * can be provided as input to `callable`. + * This includes + * (1) The implicit synthetic field(s) of the declaring type of `callable`. + * (2) The parameters of `callable`. + * (3) Any delegate parameters of `callable`. + */ +private predicate input(DotNet::Callable callable, string input, TypeParameter tp) { + input = implicit(callable, tp) + or + parameter(callable, input, tp) + or + delegateSource(callable, input, tp) +} + +/** + * Holds if `callable` returns a value of type `tp` (or a generic parameterized over `tp`) and `output` + * is a models as data string representation of, how data is routed to the return. + */ +private predicate returns(DotNet::Callable callable, TypeParameter tp, string output) { + exists(Type return, string access | return = callable.getReturnType() | + access = getAccess(callable, return, tp) and + output = "ReturnValue" + access + ) +} + +/** + * Holds if `callable` has a delegate parameter that accepts a value of type `tp` + * and `output` is the models as data string representation of, how data is routed to + * the delegate parameter. + */ +private predicate delegateSink(DotNet::Callable callable, TypeParameter tp, string output) { + exists(DelegateType dt, int position, Parameter p | + delegate(callable, dt, position) and + p = dt.getAParameter() and + p.getType() = tp and + output = "Argument[" + position + "]" + ".Parameter[" + p.getPosition() + "]" + ) +} + +/** + * Holds if `output` is a models as data string representation of, how values of type `tp` + * (or generics parameterized over `tp`) can be routed. + * This includes + * (1) The implicit synthetic field(s) of the declaring type of `callable`. + * (2) The return of `callable`. + * (3) Any delegate parameters of `callable`. + */ +private predicate output(DotNet::Callable callable, TypeParameter tp, string output) { + output = implicit(callable, tp) + or + returns(callable, tp, output) + or + delegateSink(callable, tp, output) +} + +/** + * A class of callables that are relevant generating summaries for based + * on the Theorems for Free approach. + */ +class TypeBasedFlowTargetApi extends Specific::TargetApiSpecific { + TypeBasedFlowTargetApi() { Specific::isRelevantForTypeBasedFlowModels(this) } + + /** + * Gets the string representation of all type based summaries for `this` + * inspired by the Theorems for Free approach. + * + * Examples could be (see C# psuedo code below) + * (1) `Get` returns a value of type `T`. We assume that the returned + * value was fetched from a (synthetic) field. + * (2) `Set` consumes a value of type `T`. We assume that the value is stored in + * a (synthetic) field. + * (3) `Apply` is assumed to apply the provided function to a value stored in + * a (synthetic) field and return the result. + * (4) `Apply` is assumed to apply the provided function to provided value + * and return the result. + * ```csharp + * public class MyGeneric { + * public void Set(T x) { ... } + * public T Get() { ... } + * public S Apply(Func f) { ... } + * public S2 Apply(S1 x, Func f) { ... } + * } + * ``` + */ + string getSummaries() { + exists(TypeParameter tp, string input, string output | + localTypeParameter(this, tp) and + input(this, input, tp) and + output(this, tp, output) and + input != output + | + result = asValueModel(this, input, output) + ) + } +} + +/** + * Returns the Theorems for Free inspired typed based summaries for `api`. + */ +string captureFlow(TypeBasedFlowTargetApi api) { result = api.getSummaries() } diff --git a/csharp/ql/test/utils/model-generator/CaptureNegativeSummaryModels.expected b/csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.expected similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureNegativeSummaryModels.expected rename to csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.expected diff --git a/csharp/ql/test/utils/model-generator/CaptureNegativeSummaryModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureNegativeSummaryModels.qlref rename to csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref diff --git a/csharp/ql/test/utils/model-generator/CaptureSinkModels.expected b/csharp/ql/test/utils/model-generator/dataflow/CaptureSinkModels.expected similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSinkModels.expected rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSinkModels.expected diff --git a/csharp/ql/test/utils/model-generator/CaptureSinkModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureSinkModels.qlref similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSinkModels.qlref rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSinkModels.qlref diff --git a/csharp/ql/test/utils/model-generator/CaptureSourceModels.expected b/csharp/ql/test/utils/model-generator/dataflow/CaptureSourceModels.expected similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSourceModels.expected rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSourceModels.expected diff --git a/csharp/ql/test/utils/model-generator/CaptureSourceModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureSourceModels.qlref similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSourceModels.qlref rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSourceModels.qlref diff --git a/csharp/ql/test/utils/model-generator/CaptureSummaryModels.expected b/csharp/ql/test/utils/model-generator/dataflow/CaptureSummaryModels.expected similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSummaryModels.expected rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSummaryModels.expected diff --git a/csharp/ql/test/utils/model-generator/CaptureSummaryModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureSummaryModels.qlref similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSummaryModels.qlref rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSummaryModels.qlref diff --git a/csharp/ql/test/utils/model-generator/NoSummaries.cs b/csharp/ql/test/utils/model-generator/dataflow/NoSummaries.cs similarity index 100% rename from csharp/ql/test/utils/model-generator/NoSummaries.cs rename to csharp/ql/test/utils/model-generator/dataflow/NoSummaries.cs diff --git a/csharp/ql/test/utils/model-generator/Sinks.cs b/csharp/ql/test/utils/model-generator/dataflow/Sinks.cs similarity index 100% rename from csharp/ql/test/utils/model-generator/Sinks.cs rename to csharp/ql/test/utils/model-generator/dataflow/Sinks.cs diff --git a/csharp/ql/test/utils/model-generator/Sources.cs b/csharp/ql/test/utils/model-generator/dataflow/Sources.cs similarity index 100% rename from csharp/ql/test/utils/model-generator/Sources.cs rename to csharp/ql/test/utils/model-generator/dataflow/Sources.cs diff --git a/csharp/ql/test/utils/model-generator/Summaries.cs b/csharp/ql/test/utils/model-generator/dataflow/Summaries.cs similarity index 99% rename from csharp/ql/test/utils/model-generator/Summaries.cs rename to csharp/ql/test/utils/model-generator/dataflow/Summaries.cs index 28e777700f2..3db83726765 100644 --- a/csharp/ql/test/utils/model-generator/Summaries.cs +++ b/csharp/ql/test/utils/model-generator/dataflow/Summaries.cs @@ -259,4 +259,4 @@ public class EqualsGetHashCodeNoFlow { return intTainted; } -} \ No newline at end of file +} diff --git a/csharp/ql/test/utils/model-generator/options b/csharp/ql/test/utils/model-generator/dataflow/options similarity index 52% rename from csharp/ql/test/utils/model-generator/options rename to csharp/ql/test/utils/model-generator/dataflow/options index a55169c6e97..ed33eca5326 100644 --- a/csharp/ql/test/utils/model-generator/options +++ b/csharp/ql/test/utils/model-generator/dataflow/options @@ -1,2 +1,2 @@ semmle-extractor-options: /r:System.Linq.dll /r:System.Collections.Specialized.dll -semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs +semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.expected b/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.expected new file mode 100644 index 00000000000..6405ea3fab8 --- /dev/null +++ b/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.expected @@ -0,0 +1,165 @@ +| Summaries;IGrouping<,>;true;get_Key;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;IOrderedEnumerable<>;true;CreateOrderedEnumerable<>;(System.Func,System.Collections.Generic.IComparer,System.Boolean);;Argument[this].Element;Argument[0].Parameter[0];value;generated | +| Summaries;IOrderedEnumerable<>;true;CreateOrderedEnumerable<>;(System.Func,System.Collections.Generic.IComparer,System.Boolean);;Argument[this].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[0].Element;Argument[2].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[1];Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[1];Argument[3].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[2].ReturnValue;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[2].ReturnValue;Argument[3].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[3].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[0].Element;Argument[2].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[1];Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[1];ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[2].ReturnValue;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[2].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;Argument[1].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;All<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Any<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Append<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Append<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;AsEnumerable<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Average<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Concat<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Concat<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[1].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Count<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;DefaultIfEmpty<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;DefaultIfEmpty<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;DefaultIfEmpty<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Distinct<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;DistinctBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;DistinctBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ElementAt<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;ElementAtOrDefault<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;First<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;First<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;First<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Intersect<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Intersect<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[1].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;IntersectBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;IntersectBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[0].Element;Argument[4].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[1].Element;Argument[3].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[1].Element;Argument[4].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[4].ReturnValue;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Last<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Last<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Last<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LongCount<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Max<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Max<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Max<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Max<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;MaxBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;MaxBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Min<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Min<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Min<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;MinBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;MinBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;OrderBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;OrderBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;OrderByDescending<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;OrderByDescending<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Prepend<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Prepend<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Repeat<>;(TResult,System.Int32);;Argument[0];ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Reverse<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Select<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Select<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,,>;(System.Collections.Generic.IEnumerable,System.Func>,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,,>;(System.Collections.Generic.IEnumerable,System.Func>,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,,>;(System.Collections.Generic.IEnumerable,System.Func>,System.Func);;Argument[1].ReturnValue.Element;Argument[2].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,,>;(System.Collections.Generic.IEnumerable,System.Func>,System.Func);;Argument[2].ReturnValue;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,>;(System.Collections.Generic.IEnumerable,System.Func>);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,>;(System.Collections.Generic.IEnumerable,System.Func>);;Argument[1].ReturnValue.Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Single<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Single<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Single<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Skip<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;SkipLast<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;SkipWhile<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SkipWhile<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Take<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;TakeLast<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;TakeWhile<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;TakeWhile<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ThenBy<,>;(Summaries.IOrderedEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;ThenBy<,>;(Summaries.IOrderedEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ThenByDescending<,>;(Summaries.IOrderedEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;ThenByDescending<,>;(Summaries.IOrderedEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ToHashSet<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ToList<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Union<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Union<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[1].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;UnionBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;UnionBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;UnionBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[1].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;UnionBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[1].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Where<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Where<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Zip<,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Zip<,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[1].Element;Argument[2].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Zip<,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[2].ReturnValue;ReturnValue.Element;value;generated | +| Summaries;TypeBasedCollection<>;false;Add;(T);;Argument[0];Argument[this].Element;value;generated | +| Summaries;TypeBasedCollection<>;false;AddMany;(System.Collections.Generic.IEnumerable);;Argument[0].Element;Argument[this].Element;value;generated | +| Summaries;TypeBasedCollection<>;false;First;();;Argument[this].Element;ReturnValue;value;generated | +| Summaries;TypeBasedCollection<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedCollection<>;false;GetMany;();;Argument[this].Element;ReturnValue.Element;value;generated | +| Summaries;TypeBasedComplex<>;false;AddMany;(System.Collections.Generic.IEnumerable);;Argument[0].Element;Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;Apply;(System.Func);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Apply<,>;(T1,System.Func);;Argument[0];Argument[1].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Apply<,>;(T1,System.Func);;Argument[1].ReturnValue;ReturnValue;value;generated | +| Summaries;TypeBasedComplex<>;false;Apply<>;(System.Func);;Argument[0].ReturnValue;ReturnValue;value;generated | +| Summaries;TypeBasedComplex<>;false;Apply<>;(System.Func);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[0].ReturnValue.Element;Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[0].ReturnValue.Element;Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[this].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap<>;(System.Func>);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap<>;(System.Func>);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;GetMany;();;Argument[this].SyntheticField[ArgType0];ReturnValue.Element;value;generated | +| Summaries;TypeBasedComplex<>;false;Map<>;(System.Func);;Argument[0].ReturnValue;ReturnValue;value;generated | +| Summaries;TypeBasedComplex<>;false;Map<>;(System.Func);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;MapComplex<>;(System.Func);;Argument[0].ReturnValue;ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;MapComplex<>;(System.Func);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[0].ReturnValue.SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[this].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;Set;(System.Int32,System.Func);;Argument[1].ReturnValue;Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedNoCollection<>;false;Get;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedNoCollection<>;false;Set;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;Get;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Get;(System.Object);;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Id;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;Id;(T);;Argument[0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Id;(T);;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Id<>;(S);;Argument[0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Set;(System.Int32,T);;Argument[1];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;Set;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;TypeBasedSimple;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;get_Prop;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;set_Prop;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | diff --git a/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.qlref b/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.qlref new file mode 100644 index 00000000000..99c0975a4c2 --- /dev/null +++ b/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.qlref @@ -0,0 +1 @@ +utils/model-generator/CaptureTypeBasedSummaryModels.ql \ No newline at end of file diff --git a/csharp/ql/test/utils/model-generator/typebasedflow/TypeBasedSummaries.cs b/csharp/ql/test/utils/model-generator/typebasedflow/TypeBasedSummaries.cs new file mode 100644 index 00000000000..f87563b945d --- /dev/null +++ b/csharp/ql/test/utils/model-generator/typebasedflow/TypeBasedSummaries.cs @@ -0,0 +1,210 @@ +using System; +using System.Linq; +using System.Collections; +using System.Collections.Generic; + +namespace Summaries; + +public class TypeBasedSimple { + + public T Prop { + get { throw null; } + set { throw null; } + } + + public TypeBasedSimple(T t) { throw null; } + + public T Get() { throw null; } + + public T Get(object x) { throw null; } + + public T Id(T x) { throw null; } + + public S Id(S x) { throw null; } + + public void Set(T x) { throw null; } + + public void Set(int x, T y) { throw null; } + + public void Set(S x) { throw null; } // No summary as S is unrelated to T +} + +public class TypeBasedComplex { + + public void AddMany(IEnumerable xs) { throw null; } + + public int Apply(Func f) { throw null; } + + public S Apply(Func f) { throw null; } + + public T2 Apply(T1 x, Func f) { throw null; } + + public TypeBasedComplex FlatMap(Func> f) { throw null; } + + public TypeBasedComplex FlatMap(Func> f) { throw null; } + + public IList GetMany() { throw null; } + + public S Map(Func f) { throw null; } + + public TypeBasedComplex MapComplex(Func f) { throw null; } + + public TypeBasedComplex Return(Func> f) { throw null; } + + public void Set(int x, Func f) { throw null;} +} + +// It is assumed that this is a collection with elements of type T. +public class TypeBasedCollection : IEnumerable { + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + + public void Add(T x) { throw null; } + + public void AddMany(IEnumerable x) { throw null; } + + public T First() { throw null; } + + public ICollection GetMany() { throw null; } +} + +// It is assumed that this is NOT a collection with elements of type T. +public class TypeBasedNoCollection : IEnumerable { + IEnumerator IEnumerable.GetEnumerator() { throw null; } + + public T Get() { throw null; } + + public void Set(T x) { throw null; } +} + +/* + * Representative subset of Linq. + * + * Only methods that will get summaries generated correctly are commented in. + * The remaning methods and interfaces are commented out with a descriptive reason. + * In some cases we will not be able correctly generate a summary based purely on the + * type information. + */ +public static class SystemLinqEnumerable { + + public static TSource Aggregate(this IEnumerable source, Func func) { throw null; } + public static TAccumulate Aggregate(this IEnumerable source, TAccumulate seed, Func func) { throw null; } + public static TResult Aggregate(this IEnumerable source, TAccumulate seed, Func func, Func resultSelector) { throw null; } + public static bool All(this IEnumerable source, Func predicate) { throw null; } + public static bool Any(this IEnumerable source) { throw null; } + public static bool Any(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable Append(this IEnumerable source, TSource element) { throw null; } + public static IEnumerable AsEnumerable(this IEnumerable source) { throw null; } + public static decimal Average(this IEnumerable source, Func selector) { throw null; } + // Summary will not be derivables based on type information. + // public static IEnumerable Cast(this IEnumerable source) { throw null; } + public static IEnumerable Chunk(this IEnumerable source, int size) { throw null; } + public static IEnumerable Concat(this IEnumerable first, IEnumerable second) { throw null; } + public static bool Contains(this IEnumerable source, TSource value) { throw null; } + public static int Count(this IEnumerable source) { throw null; } + public static int Count(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable DefaultIfEmpty(this IEnumerable source) { throw null; } + public static IEnumerable DefaultIfEmpty(this IEnumerable source, TSource defaultValue) { throw null; } + public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector) { throw null; } + public static IEnumerable Distinct(this IEnumerable source) { throw null; } + public static TSource? ElementAtOrDefault(this IEnumerable source, int index) { throw null; } + public static TSource ElementAt(this IEnumerable source, int index) { throw null; } + public static IEnumerable Empty() { throw null; } + // These summaries will not be derivable based on type information. + // public static IEnumerable ExceptBy(this IEnumerable first, IEnumerable second, Func keySelector) { throw null; } + // public static IEnumerable Except(this IEnumerable first, IEnumerable second) { throw null; } + public static TSource? FirstOrDefault(this IEnumerable source) { throw null; } + public static TSource FirstOrDefault(this IEnumerable source, TSource defaultValue) { throw null; } + public static TSource? FirstOrDefault(this IEnumerable source, Func predicate) { throw null; } + // Summary will not be correctly derivable based on type information. + // public static TSource FirstOrDefault(this IEnumerable source, Func predicate, TSource defaultValue) { throw null; } + public static TSource First(this IEnumerable source) { throw null; } + public static TSource First(this IEnumerable source, Func predicate) { throw null; } + // Missing summary for Argument[0].Element -> Argument[2].Parameter[1].Element and similar problem for GroupJoin (issue with generator) + // public static IEnumerable GroupBy(this IEnumerable source, Func keySelector, Func, TResult> resultSelector) { throw null; } + // public static IEnumerable GroupJoin(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector) { throw null; } + public static IEnumerable IntersectBy(this IEnumerable first, IEnumerable second, Func keySelector) { throw null; } + public static IEnumerable Intersect(this IEnumerable first, IEnumerable second) { throw null; } + public static IEnumerable Join(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector) { throw null; } + public static TSource? LastOrDefault(this IEnumerable source) { throw null; } + public static TSource LastOrDefault(this IEnumerable source, TSource defaultValue) { throw null; } + public static TSource? LastOrDefault(this IEnumerable source, Func predicate) { throw null; } + // Summary will not be correctly derivable based on type information (same problem as for FirstOrDefault) + // public static TSource LastOrDefault(this IEnumerable source, Func predicate, TSource defaultValue) { throw null; } + public static TSource Last(this IEnumerable source) { throw null; } + public static TSource Last(this IEnumerable source, Func predicate) { throw null; } + public static long LongCount(this IEnumerable source, Func predicate) { throw null; } + public static TSource? MaxBy(this IEnumerable source, Func keySelector) { throw null; } + public static TSource? Max(this IEnumerable source) { throw null; } + public static decimal Max(this IEnumerable source, Func selector) { throw null; } + public static TResult? Max(this IEnumerable source, Func selector) { throw null; } + public static TSource? MinBy(this IEnumerable source, Func keySelector) { throw null; } + public static TSource? Min(this IEnumerable source) { throw null; } + public static TResult? Min(this IEnumerable source, Func selector) { throw null; } + // These summaries will not be derivable based on type information. + // public static IEnumerable OfType(this IEnumerable source) { throw null; } + public static IOrderedEnumerable OrderByDescending(this IEnumerable source, Func keySelector) { throw null; } + public static IOrderedEnumerable OrderBy(this IEnumerable source, Func keySelector) { throw null; } + public static IEnumerable Prepend(this IEnumerable source, TSource element) { throw null; } + public static IEnumerable Repeat(TResult element, int count) { throw null; } + public static IEnumerable Reverse(this IEnumerable source) { throw null; } + public static IEnumerable SelectMany(this IEnumerable source, Func> selector) { throw null; } + public static IEnumerable SelectMany(this IEnumerable source, Func> collectionSelector, Func resultSelector) { throw null; } + public static IEnumerable Select(this IEnumerable source, Func selector) { throw null; } + public static bool SequenceEqual(this IEnumerable first, IEnumerable second) { throw null; } + public static TSource? SingleOrDefault(this IEnumerable source) { throw null; } + public static TSource SingleOrDefault(this IEnumerable source, TSource defaultValue) { throw null; } + public static TSource? SingleOrDefault(this IEnumerable source, Func predicate) { throw null; } + // Summary will not be correctly derivable based on type information (same problem as for FirstOrDefault) + // public static TSource SingleOrDefault(this IEnumerable source, Func predicate, TSource defaultValue) { throw null; } + public static TSource Single(this IEnumerable source) { throw null; } + public static TSource Single(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable SkipLast(this IEnumerable source, int count) { throw null; } + public static IEnumerable SkipWhile(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable Skip(this IEnumerable source, int count) { throw null; } + public static IEnumerable TakeLast(this IEnumerable source, int count) { throw null; } + public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable Take(this IEnumerable source, int count) { throw null; } + public static IOrderedEnumerable ThenByDescending(this IOrderedEnumerable source, Func keySelector) { throw null; } + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, Func keySelector) { throw null; } + // Missing summary for Argument[0].Element -> ReturnValue.Element (issue with generator) + // public static TSource[] ToArray(this IEnumerable source) { throw null; } + // Summaries related to dictionaries is not generated correctly as dictionaries are not identified as collections of keys and values (issue with generator). + // public static Dictionary ToDictionary(this IEnumerable source, Func keySelector) where TKey : notnull { throw null; } + // public static Dictionary ToDictionary(this IEnumerable source, Func keySelector, Func elementSelector) where TKey : notnull { throw null; } + public static HashSet ToHashSet(this IEnumerable source) { throw null; } + public static List ToList(this IEnumerable source) { throw null; } + // Type to complicated to be handled by the generator (issue with generator). + // public static ILookup ToLookup(this IEnumerable source, Func keySelector) { throw null; } + // public static ILookup ToLookup(this IEnumerable source, Func keySelector, Func elementSelector) { throw null; } + public static IEnumerable UnionBy(this IEnumerable first, IEnumerable second, Func keySelector) { throw null; } + public static IEnumerable Union(this IEnumerable first, IEnumerable second) { throw null; } + public static IEnumerable Where(this IEnumerable source, Func predicate) { throw null; } + // Type to complicated to be handled by the generator (issue with generator). + // public static IEnumerable<(TFirst First, TSecond Second)> Zip(this IEnumerable first, IEnumerable second) { throw null; } + // public static IEnumerable<(TFirst First, TSecond Second, TThird Third)> Zip(this IEnumerable first, IEnumerable second, IEnumerable third) { throw null; } + public static IEnumerable Zip(this IEnumerable first, IEnumerable second, Func resultSelector) { throw null; } +} + +public interface IGrouping : IEnumerable, IEnumerable { + TKey Key { get; } +} + +// public interface ILookup : IEnumerable>, IEnumerable { +// IEnumerable this[TKey key] { get; } +// bool Contains(TKey key); +// } + +public interface IOrderedEnumerable : IEnumerable, IEnumerable { + IOrderedEnumerable CreateOrderedEnumerable(Func keySelector, IComparer? comparer, bool descending); +} + +// public partial class Lookup : IEnumerable>, IEnumerable, ILookup{ +// internal Lookup() { } +// public int Count { get { throw null; } } +// public IEnumerable this[TKey key] { get { throw null; } } +// public IEnumerable ApplyResultSelector(Func, TResult> resultSelector) { throw null; } +// public bool Contains(TKey key) { throw null; } +// public IEnumerator> GetEnumerator() { throw null; } +// IEnumerator IEnumerable.GetEnumerator() { throw null; } +// } diff --git a/csharp/tools/tracing-config.lua b/csharp/tools/tracing-config.lua index c1c45adb00d..7c62f0062e4 100644 --- a/csharp/tools/tracing-config.lua +++ b/csharp/tools/tracing-config.lua @@ -38,26 +38,12 @@ function RegisterExtractorPack(id) match = true break end - if arg == 'run' then - -- for `dotnet run`, we need to make sure that `-p:UseSharedCompilation=false` is - -- not passed in as an argument to the program that is run - match = true - needsSeparator = true - end - end - if arg == '--' then - needsSeparator = false - break end end if match then - local injections = { '-p:UseSharedCompilation=false' } - if needsSeparator then - table.insert(injections, '--') - end return { order = ORDER_REPLACE, - invocation = BuildExtractorInvocation(id, compilerPath, compilerPath, compilerArguments, nil, injections) + invocation = BuildExtractorInvocation(id, compilerPath, compilerPath, compilerArguments, nil, { '-p:UseSharedCompilation=false' }) } end return nil diff --git a/docs/codeql/codeql-cli/about-codeql-workspaces.rst b/docs/codeql/codeql-cli/about-codeql-workspaces.rst index 3215c44042e..860fbdb7d63 100644 --- a/docs/codeql/codeql-cli/about-codeql-workspaces.rst +++ b/docs/codeql/codeql-cli/about-codeql-workspaces.rst @@ -1,6 +1,6 @@ .. _about-codeql-workspaces: -About CodeQL Workspaces +About CodeQL workspaces ======================= .. include:: ../reusables/beta-note-package-management.rst @@ -12,16 +12,17 @@ The main benefit of a CodeQL workspace is that it makes it easier for you to dev In most cases, you should store the CodeQL workspace and the CodeQL packs contained in it in one git repository. This makes it easier to share your CodeQL development environment. The ``codeql-workspace.yml`` file ----------------------------------- +--------------------------------- -A CodeQL workspace is defined by a ``codeql-workspace.yml`` yaml file. This file contains a ``provide`` block, and optionally an ``ignore`` block. +A CodeQL workspace is defined by a ``codeql-workspace.yml`` yaml file. This file contains a ``provide`` block, and optionally ``ignore`` and ``registries`` blocks. * The ``provide`` block contains a list of glob patterns that define the CodeQL packs that are available in the workspace. * The ``ignore`` block contains a list of glob patterns that define CodeQL packs that are not available in the workspace. +* The ``registries`` block contains a list of GHES URLs and package patterns that control which container registry is used for publishing CodeQL packs. For more information, see :ref:`Working with CodeQL packs on GitHub Enterprise Server `. Each entry in the ``provide`` or ``ignore`` section must map to the location of a ``qlpack.yml`` file. All glob patterns are defined relative to the directory that contains the workspace file. For a list of patterns accepted in this file, see "`@actions/glob `__ ." -For example, the following ``codeql-workspace.yml`` file defines a workspace that contains all the CodeQL packs recursively found in the ``codeql-packs`` directory, except for the packs in the ``experimental`` directory: +For example, the following ``codeql-workspace.yml`` file defines a workspace that contains all the CodeQL packs recursively found in the ``codeql-packs`` directory, except for the packs in the ``experimental`` directory. The ``registries`` block specifies that ``codeql/*`` packs should be downloaded from https://ghcr.io/v2/, which is GitHub's default container registry. All other packs should be downloaded from and published to the regsitry at ``GHE_HOSTNAME``. .. code-block:: yaml @@ -30,6 +31,13 @@ For example, the following ``codeql-workspace.yml`` file defines a workspace tha ignore: - "*/codeql-packs/**/experimental/**/qlpack.yml" + registries: + - packages: 'codeql/*' + url: https://ghcr.io/v2/ + + - packages: '*' + url: https://containers.GHE_HOSTNAME/v2/ + To verify that your ``codeql-workspace.yml`` file includes the CodeQL packs that you expect, run the ``codeql pack ls`` command in the same directory as your workspace. The result of the command is a list of all CodeQL packs in the workspace. .. _source-dependencies: diff --git a/docs/codeql/codeql-cli/about-ql-packs.rst b/docs/codeql/codeql-cli/about-ql-packs.rst new file mode 100644 index 00000000000..2f8d4d9229d --- /dev/null +++ b/docs/codeql/codeql-cli/about-ql-packs.rst @@ -0,0 +1,12 @@ +.. _about-ql-packs: + +About QL packs +============== + +This page has been moved to ":doc:`About CodeQL packs `." + + +.. toctree:: + :hidden: + + about-ql-packs diff --git a/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst index 770129c8f9c..b99299119a2 100644 --- a/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst @@ -219,6 +219,56 @@ When the analysis has finished, a SARIF results file is generated. Specifying `` that the results are formatted according to the most recent SARIF specification supported by CodeQL. +.. _including-query-help-for-custom-codeql-queries-in-sarif-files: + +Running a subset of queries in a CodeQL pack +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are using CodeQL CLI v2.8.1 or later, you can include a path at the end of a pack specification to run a subset of queries inside the pack. This applies to any command that locates or runs queries within a pack. + +The complete way to specify a set of queries is in the form ``scope/name@range:path``, where: + +- ``scope/name`` is the qualified name of a CodeQL pack. +- ``range`` is a `semver range `_. +- ``path`` is a file system path to a single query, a directory containing queries, or a query suite file. + +When you specify a ``scope/name``, the ``range`` and ``path`` are +optional. If you omit a ``range`` then the latest version of the +specified pack is used. If you omit a ``path`` then the default query suite +of the specified pack is used. + +The ``path`` can be one of a ``*.ql`` query file, a directory +containing one or more queries, or a ``.qls`` query suite file. If +you omit a pack name, then you must provide a ``path``, +which will be interpreted relative to the working directory +of the current process. + +If you specify a ``scope/name`` and ``path``, then the ``path`` cannot +be absolute. It is considered relative to the root of the CodeQL +pack. + +To analyze a database using all queries in the `experimental/Security` folder within the `codeql/cpp-queries` CodeQL pack you can use:: + + codeql database analyze --format=sarif-latest --output=results \ + codeql/cpp-queries:experimental/Security + +To run the `RedundantNullCheckParam.ql` query in the `codeql/cpp-queries` CodeQL pack use:: + + codeql database analyze --format=sarif-latest --output=results \ + 'codeql/cpp-queries:experimental/Likely Bugs/RedundantNullCheckParam.ql' + +To analyze your database using the `cpp-security-and-quality.qls` query suite from a version of the `codeql/cpp-queries` CodeQL pack that is >= 0.0.3 and < 0.1.0 (the highest compatible version will be chosen) you can use:: + + codeql database analyze --format=sarif-latest --output=results \ + 'codeql/cpp-queries@~0.0.3:codeql-suites/cpp-security-and-quality.qls' + +If you need to reference a query file, directory, or suite whose path contains a literal `@` or `:`, you can prefix the query specification with `path:` like so:: + + codeql database analyze --format=sarif-latest --output=results \ + path:C:/Users/ci/workspace@2/security/query.ql + +For more information about CodeQL packs, see :doc:`About CodeQL Packs `. + Running query suites ~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index 65afbca40c1..484163d94e7 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -11,11 +11,11 @@ or download them from GitHub.com. CodeQL analysis relies on extracting relational data from your code, and using it to build a :ref:`CodeQL database `. CodeQL databases contain all of the important information about a codebase, which can -be analyzed by executing CodeQL queries against it. GitHub creates and +be analyzed by executing CodeQL queries against it. GitHub creates and stores CodeQL databases for a large number of open-source projects. For more information, see ":ref:`Downloading CodeQL databases from GitHub.com `." -You can also create CodeQL databases yourself using the CodeQL CLI. +You can also create CodeQL databases yourself using the CodeQL CLI. Before you generate a CodeQL database, you need to: - Install and set up the CodeQL CLI. For more information, see @@ -214,12 +214,12 @@ commands that you can specify for compiled languages. codeql database create cpp-database --language=cpp --command=make -- C# project built using ``dotnet build``:: +- C# project built using ``dotnet build``: - It is a good idea to add `/t:rebuild` to ensure that all code will be built, or do a - prior `dotnet clean` (code that is not built will not be included in the CodeQL database): + It is a good idea to add `/t:rebuild` to ensure that all code will be built, or do a + prior `dotnet clean` (code that is not built will not be included in the CodeQL database):: - codeql database create csharp-database --language=csharp --command='dotnet build /t:rebuild' + codeql database create csharp-database --language=csharp --command='dotnet build /t:rebuild' - Go project built using the ``CODEQL_EXTRACTOR_GO_BUILD_TRACING=on`` environment variable:: @@ -391,9 +391,9 @@ Downloading databases from GitHub.com ------------------------------------- .. include:: ../reusables/download-github-database.rst - + Before running an analysis with the CodeQL CLI, you must unzip the databases. - + Further reading --------------- diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index 1e212755367..c65e1c42ad4 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -118,8 +118,10 @@ typically a query metadata property. The value can be: To match a constraint, a metadata value must match one of the strings or regular expressions. When there is more than one metadata key, each key must be matched. -For more information about query metadata properties, see ":ref:`Metadata for CodeQL queries -`." +The standard metadata keys available to match on are: ``description``, ``id``, ``kind``, +``name``, ``tags``, ``precision``, and ``problem.severity``. +For more information about query metadata properties, see +":ref:`Metadata for CodeQL queries `." In addition to metadata tags, the keys in the constraint block can also be: @@ -131,8 +133,37 @@ In addition to metadata tags, the keys in the constraint block can also be: - ``tags contain all``---each of the given match strings must match one of the components of the ``@tags`` metadata property. -Examples -~~~~~~~~ +Examples of filtering which queries are run +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A common use case is to create a query suite that runs all queries in a CodeQL pack, +except for a few specific queries that the user does not want to run. In general, we +recommend filtering on the query ``id``, which is a unique and stable identifier for +each query. The following three query suite definitions are semantically identical and +filter by the query ``id``: + +This filter matches all the queries in the default suite of ``codeql/cpp-queries``, except for the two queries with the excluded identifiers:: + + - qlpack: codeql/cpp-queries + - exclude: + id: + - cpp/cleartext-transmission + - cpp/cleartext-storage-file + +In this example, a separate ``exclude`` instruction is used for each query:: + + - qlpack: codeql/cpp-queries + - exclude: + id: cpp/cleartext-transmission + - exclude: + id: cpp/cleartext-storage-file + +In this example, a regular expression excludes the same two queries. It would also exclude any future queries added to the suite with identifiers that begin: ``cpp/cleartext-``:: + + - qlpack: codeql/cpp-queries + - exclude: + id: + - /^cpp\/cleartext-.*/ To define a suite that selects all queries in the default suite of the ``codeql/cpp-queries`` CodeQL pack, and then refines them to only include @@ -150,6 +181,15 @@ and ``@precision high`` from the ``my-custom-queries`` directory, use:: kind: problem precision: very-high +Note that the following query suite definition behaves differently from the definition above. This definition selects queries that are ``@kind problem`` *or* +are ``@precision very-high``:: + + - queries: my-custom-queries + - include: + kind: problem + - include: + precision: very-high + To create a suite that selects all queries with ``@kind problem`` from the ``my-custom-queries`` directory except those with ``@problem.severity recommendation``, use:: @@ -172,6 +212,15 @@ use:: - high - very-high +.. pull-quote:: + + Tip + + You can use the ``codeql resolve queries /path/to/suite.qls`` command to see + which queries are selected by a query suite definition. For more information, + see the `resolve queries <../../codeql-cli/manual/resolve-queries>`__ + reference documentation. + Reusing existing query suite definitions ----------------------------------------- @@ -208,14 +257,8 @@ Existing query suite definitions can be reused by specifying: conditions, saved in a ``.yml`` file, to multiple query definitions. For more information, see the `example <#example>`__ below. -- An ``eval`` instruction---performs the same function as an ``import`` - instruction, but takes a full suite definition as the argument, rather than the - path to a ``.qls`` file on disk. - -To see what queries are included in a query suite, you can run the ``codeql resolve queries my-suite.qls`` command. - -Example -~~~~~~~ +Reusability Examples +~~~~~~~~~~~~~~~~~~~~ To use the same conditions in multiple query suite definitions, create a separate ``.yml`` file containing your instructions. For example, save the @@ -252,6 +295,30 @@ instruction:: from: my-org/my-custom-instructions version: ^1.2.3 # optional +A common use case for an ``import`` instruction is to apply a further filter to queries from another +query suite. For example, this suite will further filter the ``cpp-security-and-quality`` suite +and exclude ``low`` and ``medium`` precision queries:: + + - import: codeql-suites/cpp-security-and-quality.qls + from: codeql/cpp-queries + - exclude: + precision: + - low + - medium + +If you want to ``include`` queries imported from another suite, the syntax is a little different:: + + - import: codeql-suites/cpp-security-and-quality.qls + from: codeql/cpp-queries + - exclude: {} + - include: + precision: + - very-high + - high + +Notice the empty ``exclude`` instruction. This is required to ensure that the subsequent ``include`` +instruction is able to filter queries from the imported suite. + Naming a query suite -------------------- diff --git a/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst b/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst index 3aa61e2b7fe..a91bc570768 100644 --- a/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst +++ b/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst @@ -74,6 +74,8 @@ The ``analyze`` command will run the default suite of any specified CodeQL packs codeql analyze / / +.. _working-with-codeql-packs-on-ghes: + Working with CodeQL packs on GitHub Enterprise Server ----------------------------------------------------- @@ -91,13 +93,17 @@ For example, the following ``qlconfig.yml`` file associates all packs with the C .. code-block:: yaml registries: - - packages: 'codeql/*' + - packages: + - 'codeql/*' + - 'other-org/*' url: https://ghcr.io/v2/ - packages: '*' url: https://containers.GHE_HOSTNAME/v2/ The CodeQL CLI will determine which registry to use for a given package name by finding the first item in the ``registries`` list with a ``packages`` property that matches that package name. -This means that you'll generally want to define the most specific package name patterns first. +This means that you'll generally want to define the most specific package name patterns first. The ``packages`` property may be a single package name, a glob pattern, or a YAML list of package names and glob patterns. + +The ``registries`` list can also be placed inside of a ``codeql-workspace.yml`` file. Doing so will allow you to define the registries to be used within a specific workspace, so that it can be shared amongst other CodeQL users of the workspace. The ``registries`` list in the ``codeql-workspace.yml`` will be merged with and take precedence over the list in the global ``qlconfig.yml``. For more information about ``codeql-workspace.yml``, see :ref:`About CodeQL workspaces `. You can now use ``codeql pack publish``, ``codeql pack download``, and ``codeql database analyze`` to manage packs on GitHub Enterprise Server. diff --git a/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst index c820bf007df..1881dfc71a7 100644 --- a/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst +++ b/docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst @@ -36,7 +36,7 @@ Running the query .. code-block:: ql - import ruby + import codeql.ruby.AST from IfExpr ifexpr where @@ -80,7 +80,7 @@ After the initial ``import`` statement, this simple query comprises three parts +---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+ | Query part | Purpose | Details | +===============================================================+===================================================================================================================+========================================================================================================================+ -| ``import ruby`` | Imports the standard CodeQL libraries for Ruby. | Every query begins with one or more ``import`` statements. | +| ``import codeql.ruby.AST`` | Imports the standard CodeQL AST libraries for Ruby. | Every query begins with one or more ``import`` statements. | +---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+ | ``from IfExpr ifexpr`` | Defines the variables for the query. | We use: an ``IfExpr`` variable for ``if`` expressions. | | | Declarations are of the form: | | diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst index ede3182fd56..ad6ecdb591c 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst @@ -18,7 +18,7 @@ library by beginning your query with: .. code-block:: ql - import ruby + import codeql.ruby.AST The CodeQL libraries model various aspects of Ruby code, depending on the type of query you want to write. For example the abstract syntax tree (AST) library is used for locating program elements, to match syntactic @@ -138,7 +138,7 @@ The following example lists all methods in the class `ApiController`: .. code-block:: ql - import ruby + import codeql.ruby.AST from ClassDeclaration m where m.getName() = "ApiController" @@ -223,7 +223,7 @@ Example .. code-block:: ql - import ruby + import codeql.ruby.AST from Method m where m.getName() = "show" @@ -274,7 +274,7 @@ The following example finds all literals that are returned by a `return` stateme .. code-block:: ql - import ruby + import codeql.ruby.AST from ReturnStmt return, Literal lit where lit.getParent() = return @@ -421,7 +421,7 @@ The following example finds "chained assignments" (of the form ``A=B=C``): .. code-block:: ql - import ruby + import codeql.ruby.AST from Assignment op where op.getRightOperand() instanceof Assignment @@ -460,7 +460,7 @@ The following example finds all method calls to a method called `delete`. .. code-block:: ql - import ruby + import codeql.ruby.AST from MethodCall call where call.getMethodName() = "delete" @@ -517,7 +517,7 @@ The following example finds `if`-expressions that are missing a `then` branch. .. code-block:: ql - import ruby + import codeql.ruby.AST from IfExpr expr where not exists(expr.getThen()) @@ -559,7 +559,7 @@ The following example finds all class variables in the class `StaticController`: .. code-block:: ql - import ruby + import codeql.ruby.AST from ClassDeclaration cd, ClassVariable v where @@ -612,7 +612,7 @@ The following example finds writes to class variables in the class `StaticContro .. code-block:: ql - import ruby + import codeql.ruby.AST from ClassVariableWriteAccess write, ClassDeclaration cd, ClassVariable v where diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index ea90ebbf843..45747ae86ab 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -57,44 +57,27 @@ construction of the library path. First, determine the *query directory* of the ``.ql`` file being compiled. Starting with the directory containing the ``.ql`` file, and walking up the directory structure, each directory is checked for a -file called ``queries.xml`` or ``qlpack.yml``. The first directory +file called ``qlpack.yml`` or ``codeql-pack.yml``. The first directory where such a file is found is the query directory. If there is no such directory, the directory of the ``.ql`` file itself is the query directory. -A ``queries.xml`` file that defines a query directory must always -contain a single top-level tag named -``queries``, which has a ``language`` attribute set to the identifier -of the active database schema (for example, ````). - A ``qlpack.yml`` file defines a :ref:`CodeQL pack `. The content of a ``qlpack.yml`` file is described in the CodeQL CLI documentation. +``codeql-pack.yml`` is an alias for ``qlpack.yml``. -If both a ``queries.xml`` and a ``qlpack.yml`` exist in the same -directory, the latter takes precedence (and the former is assumed to -exist for compatibility with older tooling). - -The CodeQL CLI and newer tools based on it (such as, +The CodeQL CLI and tools based on it (such as, GitHub code scanning and the CodeQL extension for Visual Studio Code) construct a library path using CodeQL packs. For each CodeQL pack added to the library path, the CodeQL packs named in its -``libraryPathDependencies`` will be subsequently added to the library +``dependencies`` will be subsequently added to the library path, and the process continues until all packs have been resolved. The actual library path consists of the root directories of the selected CodeQL packs. This process depends on a mechanism for finding -CodeQL packs by pack name, as described in the :ref:`CodeQL CLI documentation `. +CodeQL packs by pack name and version, as described in the :ref:`CodeQL CLI documentation `. -When the query directory contains a ``queries.xml`` file but no -``qlpack.yml``, the CodeQL pack resolution behaves as if it defines a QL -pack with no name and a single library path dependency named -``legacy-libraries-LANGUAGE`` where ``LANGUAGE`` is taken from -``queries.xml``. The ``github/codeql`` repository provides packs with -names following this pattern, which themselves depend on the actual -CodeQL libraries for each language. - -When the query directory contains neither a ``queries.xml`` nor -``qlpack.yml`` file, it is considered to be a CodeQL pack with no name and +When the query directory contains neither a ``qlpack.yml`` nor +``codeql-pack.yml`` file, it is considered to be a CodeQL pack with no name and no library dependencies. This causes the library path to consist of *only* the query directory itself. This is not generally useful, but it suffices for running toy examples of QL code that don't @@ -160,7 +143,7 @@ Module definitions A QL module definition has the following syntax: -:: +:: module ::= annotation* "module" modulename "{" moduleBody "}" @@ -196,7 +179,7 @@ An import directive refers to a module identifier: import ::= annotations "import" importModuleId ("as" modulename)? - qualId ::= simpleId | qualId "." simpleId + qualId ::= simpleId | qualId "." simpleId importModuleId ::= qualId | importModuleId "::" simpleId @@ -268,7 +251,7 @@ With the exception of class domain types and character types (which cannot be re type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" - moduleId ::= simpleId | moduleId "::" simpleId + moduleId ::= simpleId | moduleId "::" simpleId A type reference is resolved to a type as follows: @@ -598,7 +581,7 @@ An integer literal is a possibly negated sequence of decimal digits (``0`` throu 0 42 123 - -2147483648 + -2147483648 Float literals (float) ~~~~~~~~~~~~~~~~~~~~~~ @@ -760,7 +743,7 @@ it is parsed as part of the first declaration. Inheriting QLDoc ~~~~~~~~~~~~~~~~ -If no QLDoc is provided then it may be inherited. +If no QLDoc is provided then it may be inherited. In the case of an alias then it may be inherited from the right-hand side of the alias. @@ -818,7 +801,7 @@ The body of a predicate is of one of three forms: :: optbody ::= ";" - | "{" formula "}" + | "{" formula "}" | "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")" In the first form, with just a semicolon, the predicate is said to not have a body. In the second form, the body of the predicate is the given formula (see "`Formulas <#formulas>`__"). In the third form, the body is a higher-order relation. @@ -873,7 +856,7 @@ Each member of a class is either a *character*, a predicate, or a field: :: member ::= character | predicate | field - character ::= qldoc? annotations classname "(" ")" "{" formula "}" + character ::= qldoc? annotations classname "(" ")" "{" formula "}" field ::= qldoc? annotations var_decl ";" Characters @@ -924,7 +907,7 @@ A valid class may not inherit from two different classes that include a field wi A valid field must override another field if it is annotated ``override``. -When field ``f`` overrides field ``g`` the type of ``f`` must be a subtype of the type of ``g``. ``f`` may not be a final field. +When field ``f`` overrides field ``g`` the type of ``f`` must be a subtype of the type of ``g``. ``f`` may not be a final field. Select clauses ~~~~~~~~~~~~~~ @@ -993,8 +976,8 @@ There are several kinds of expressions: | binop | cast | primary - - primary ::= eparen + + primary ::= eparen | literal | variable | super_expr @@ -1103,7 +1086,7 @@ A super expression has the following syntax: :: - super_expr ::= "super" | type "." "super" + super_expr ::= "super" | type "." "super" For a super expression to be valid, the ``this`` keyword must have a type and value in the typing environment. The type of the expression is the same as the type of ``this`` in the typing environment. @@ -1163,11 +1146,11 @@ A valid call with results *resolves* to a set of predicates. The ways a call can - If the call has no receiver and the predicate name is a selection identifier, then the qualifier is resolved as a module (see "`Module resolution <#module-resolution>`__"). The identifier is then resolved in the exported predicate environment of the qualifier module. - If the call has a super expression as the receiver, then it resolves to a member predicate in a class that the enclosing class inherits from: - - If the super expression is unqualified and there is a single class that the current class inherits from, then the super-class is that class. + - If the super expression is unqualified and there is a single class that the current class inherits from, then the super-class is that class. - If the super expression is unqualified and there are multiple classes that the current class inherits from, then the super-class is the domain type. - - Otherwise, the super-class is the class named by the qualifier of the super expression. + - Otherwise, the super-class is the class named by the qualifier of the super expression. - The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class. + The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class. - If the type of the receiver is the same as the enclosing class, the predicate is resolved by looking up its name and arity in the visible predicate environment of the class. @@ -1226,15 +1209,15 @@ The rank expression must be present if the aggregate id is ``rank``; otherwise i Apart from the presence or absence of the rank variable, all other reduced forms of an aggregation are equivalent to a full form using the following steps: - If the formula is omitted, then it is taken to be ``any()``. -- If there are no aggregation expressions, then either: +- If there are no aggregation expressions, then either: - - The aggregation id is ``count`` or ``strictcount`` and the expression is taken to be ``1``. + - The aggregation id is ``count`` or ``strictcount`` and the expression is taken to be ``1``. - There must be precisely one variable declaration, and the aggregation expression is taken to be a reference to that variable. - If the aggregation id is ``concat`` or ``strictconcat`` and it has a single expression then the second expression is taken to be ``""``. -- If the ``monotonicAggregates`` language pragma is not enabled, or the original formula and variable declarations are both omitted, then the aggregate is transformed as follows: +- If the ``monotonicAggregates`` language pragma is not enabled, or the original formula and variable declarations are both omitted, then the aggregate is transformed as follows: - - For each aggregation expression ``expr_i``, a fresh variable ``v_i`` is declared with the same type as the expression in addition to the original variable declarations. + - For each aggregation expression ``expr_i``, a fresh variable ``v_i`` is declared with the same type as the expression in addition to the original variable declarations. - The new range is the conjunction of the original range and a term ``v_i = expr_i`` for each aggregation expression ``expr_i``. - Each original aggregation expression ``expr_i`` is replaced by a new aggregation expression ``v_i``. @@ -1320,11 +1303,11 @@ Expression pragmas can be used to guide optimization. The values of an expression pragma are the values of the contained expression. The type `only_bind_out` hints that uses of the result of the expression pragma should not be used to guide the evaluation of the result of the contained expression. -When checking to see that all values are bound the compiler does not assume that if the result of the expression pragma is bound then the result of the contained +When checking to see that all values are bound the compiler does not assume that if the result of the expression pragma is bound then the result of the contained expression is bound. The type `only_bind_into` hints that uses of the contained expression should not be used to guide the evaluation of the result of the expression pragma. -When checking to see that all values are bound the compiler does not assume that if the result of the contained expression is bound then the result of the +When checking to see that all values are bound the compiler does not assume that if the result of the contained expression is bound then the result of the expression pragma is bound. Ranges @@ -1498,7 +1481,7 @@ A comparison formula is two expressions separated by a comparison operator: :: comparison ::= expr compop expr - compop ::= "=" | "!=" | "<" | ">" | "<=" | ">=" + compop ::= "=" | "!=" | "<" | ">" | "<=" | ">=" A comparison formula matches if there is one value of the left expression that is in the given ordering with one of the values of the right expression. The ordering used is specified in "`Ordering <#ordering>`__." If one of the values is an integer and the other is a float value, then the integer is converted to a float value before the comparison. @@ -1582,7 +1565,7 @@ Aliases define new names for existing QL entities. alias ::= qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";" | qldoc? annotations "class" classname "=" type ";" | qldoc? annotations "module" modulename "=" moduleId ";" - + An alias introduces a binding from the new name to the entity referred to by the right-hand side in the current module's declared predicate, type, or module environment respectively. @@ -1973,13 +1956,13 @@ Each layer of the stratification is *populated* in order. To populate a layer, e - To populate a predicate that has a formula as a body, find each named tuple ``t`` that has the following properties: - The tuple matches the body formula. - - The variables should be the predicate's arguments. + - The variables should be the predicate's arguments. - If the predicate has a result, then the tuples should additionally have a value for ``result``. - If the predicate is a member predicate or characteristic predicate of a class ``C`` then the tuples should additionally have a value for ``this`` and each visible field on the class. - The values corresponding to the arguments should all be a member of the declared types of the arguments. - The values corresponding to ``result`` should all be a member of the result type. - The values corresponding to the fields should all be a member of the declared types of the fields. - - If the predicate is a member predicate of a class ``C`` and not a characteristic predicate, then the tuples should additionally extend some tuple in ``C.class``. + - If the predicate is a member predicate of a class ``C`` and not a characteristic predicate, then the tuples should additionally extend some tuple in ``C.class``. - If the predicate is a characteristic predicate of a class ``C``, then there should be a tuple ``t'`` in ``C.extends`` such that for each visible field in ``C``, any field that is equal to or overrides a field in ``t'`` should have the same value in ``t``. ``this`` should also map to the same value in ``t`` and ``t'``. For each such tuple remove any components that correspond to fields and add it to the predicate in the store. @@ -1998,7 +1981,7 @@ Each layer of the stratification is *populated* in order. To populate a layer, e - To populate the type ``C.C`` for a class ``C``, if ``C`` has a characteristic predicate, then add all tuples from that predicate to the store. Otherwise add all tuples ``t`` such that: - - The variables of ``t`` should be ``this`` and the visible fields of ``C``. + - The variables of ``t`` should be ``this`` and the visible fields of ``C``. - The values corresponding to the fields should all be a member of the declared types of the fields. - If the predicate is a characteristic predicate of a class ``C``, then there should be a tuple ``t'`` in ``C.extends`` such that for each visible field in ``C``, any field that is equal to or overrides a field in ``t'`` should have the same value in ``t``. ``this`` should also map to the same value in ``t`` and ``t'``. @@ -2033,7 +2016,7 @@ The complete grammar for QL is as follows: import ::= annotations "import" importModuleId ("as" modulename)? - qualId ::= simpleId | qualId "." simpleId + qualId ::= simpleId | qualId "." simpleId importModuleId ::= qualId | importModuleId "::" simpleId @@ -2072,18 +2055,18 @@ The complete grammar for QL is as follows: head ::= ("predicate" | type) predicateName "(" var_decls ")" optbody ::= ";" - | "{" formula "}" + | "{" formula "}" | "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")" class ::= qldoc? annotations "class" classname "extends" type ("," type)* "{" member* "}" member ::= character | predicate | field - character ::= qldoc? annotations classname "(" ")" "{" formula "}" + character ::= qldoc? annotations classname "(" ")" "{" formula "}" field ::= qldoc? annotations var_decl ";" - moduleId ::= simpleId | moduleId "::" simpleId + moduleId ::= simpleId | moduleId "::" simpleId type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" @@ -2092,7 +2075,7 @@ The complete grammar for QL is as follows: alias ::= qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";" | qldoc? annotations "class" classname "=" type ";" | qldoc? annotations "module" modulename "=" moduleId ";" - + var_decls ::= (var_decl ("," var_decl)*)? var_decl ::= type lowerId @@ -2108,7 +2091,7 @@ The complete grammar for QL is as follows: | instanceof | inrange | call - + fparen ::= "(" formula ")" disjunction ::= formula "or" formula @@ -2128,7 +2111,7 @@ The complete grammar for QL is as follows: comparison ::= expr compop expr - compop ::= "=" | "!=" | "<" | ">" | "<=" | ">=" + compop ::= "=" | "!=" | "<" | ">" | "<=" | ">=" instanceof ::= expr "instanceof" type @@ -2146,7 +2129,7 @@ The complete grammar for QL is as follows: | primary - primary ::= eparen + primary ::= eparen | literal | variable | super_expr @@ -2175,7 +2158,7 @@ The complete grammar for QL is as follows: variable ::= varname | "this" | "result" - super_expr ::= "super" | type "." "super" + super_expr ::= "super" | type "." "super" cast ::= "(" type ")" expr @@ -2184,7 +2167,7 @@ The complete grammar for QL is as follows: aggregation ::= aggid ("[" expr "]")? "(" var_decls ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" - + expression_pragma ::= "pragma" "[" expression_pragma_type "]" "(" expr ")" expression_pragma_type ::= "only_bind_out" | "only_bind_into" @@ -2199,9 +2182,9 @@ The complete grammar for QL is as follows: callwithresults ::= predicateRef (closure)? "(" (exprs)? ")" | primary "." predicateName (closure)? "(" (exprs)? ")" - + range ::= "[" expr ".." expr "]" - + setliteral ::= "[" expr ("," expr)* ","? "]" simpleId ::= lowerId | upperId diff --git a/docs/codeql/reusables/download-github-database.rst b/docs/codeql/reusables/download-github-database.rst index 1156c273456..56e15078740 100644 --- a/docs/codeql/reusables/download-github-database.rst +++ b/docs/codeql/reusables/download-github-database.rst @@ -7,7 +7,7 @@ For example, to check for CodeQL databases using the `GitHub CLI //code-scanning/codeql/databases/ -H 'Accept: application/zip' > path/to/local/database.zip diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md index 5660a08f72e..9b4b291a75a 100644 --- a/docs/query-metadata-style-guide.md +++ b/docs/query-metadata-style-guide.md @@ -179,7 +179,15 @@ The select clause of each alert query defines the alert message that is displaye * The message should factually describe the problem that is being highlighted–it should not contain recommendations about how to fix the problem or value judgements. * Program element references should be in 'single quotes' to distinguish them from ordinary words. Quotes are not needed around substitutions (`$@`). * Avoid constant alert message strings and include some context, if possible. For example, `The class 'Foo' is duplicated as 'Bar'.` is preferable to `This class is duplicated here.` +* If a reference to the current location can't be avoided use "this location" instead of "here". For example, `Bad thing at this location.` is preferable to `Bad thing here.`. This avoids the "click here" anti-pattern. +* For path queries, if possible, try to follow the template: `This path depends on a [user-provided value].`, or alternatively (if the first option doesn't work) `[User-provided value] flows to this location and is used in a path.`. +* Taint tracking queries generally have a sink that "depends on" the source, and dataflow queries generally have a source that "flows to" the sink. + +### Links in alert messages + * Where you reference another program element, link to it if possible using a substitution (`$@`). Links should be used inline in the sentence, rather than as parenthesised lists or appositions. +* Avoid using link texts that don't describe what they link to. For example, rewrite `This sensitive data is written to a logfile unescaped [here]` to `This sensitive data is [written to a logfile unescaped]`. +* Make link text as concise and precise as possible. For example, avoid starting a link text with an indefinite article (a, an). `Path construction depends on a [user-provided value]` is preferable to `Path construction depends on [a user-provided value]`. (Where the square brackets indicate a link.) See [the W3C guide on link texts](https://www.w3.org/WAI/WCAG22/Understanding/link-purpose-in-context.html) for further information. * When a message contains multiple links, construct a sentence that has the most variable link (that is, the link with most targets) last. For further information, see [Defining the results of a query](https://codeql.github.com/docs/writing-codeql-queries/defining-the-results-of-a-query/). For examples of select clauses and alert messages, see the query source files at the following pages: diff --git a/go/ql/lib/CHANGELOG.md b/go/ql/lib/CHANGELOG.md index 21888c17ed4..2a6ee5dbcb2 100644 --- a/go/ql/lib/CHANGELOG.md +++ b/go/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.2.5 + ## 0.2.4 ### Minor Analysis Improvements diff --git a/go/ql/lib/change-notes/2022-09-12-uppercase.md b/go/ql/lib/change-notes/2022-09-12-uppercase.md new file mode 100644 index 00000000000..996861f1c2c --- /dev/null +++ b/go/ql/lib/change-notes/2022-09-12-uppercase.md @@ -0,0 +1,5 @@ +--- +category: deprecated +--- +* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide. + The old name still exists as a deprecated alias. \ No newline at end of file diff --git a/go/ql/lib/change-notes/released/0.2.5.md b/go/ql/lib/change-notes/released/0.2.5.md new file mode 100644 index 00000000000..ec3e1ae7d2f --- /dev/null +++ b/go/ql/lib/change-notes/released/0.2.5.md @@ -0,0 +1 @@ +## 0.2.5 diff --git a/go/ql/lib/codeql-pack.release.yml b/go/ql/lib/codeql-pack.release.yml index 7f1e3841dcd..211454ed306 100644 --- a/go/ql/lib/codeql-pack.release.yml +++ b/go/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.2.4 +lastReleaseVersion: 0.2.5 diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index b34e1d09f52..24aa7b5555b 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 0.2.5-dev +version: 0.2.6-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/lib/semmle/go/concepts/HTTP.qll b/go/ql/lib/semmle/go/concepts/HTTP.qll index 83d387d386d..770f577b1ff 100644 --- a/go/ql/lib/semmle/go/concepts/HTTP.qll +++ b/go/ql/lib/semmle/go/concepts/HTTP.qll @@ -5,7 +5,7 @@ import go /** Provides classes for modeling HTTP-related APIs. */ -module HTTP { +module Http { /** Provides a class for modeling new HTTP response-writer APIs. */ module ResponseWriter { /** @@ -179,7 +179,7 @@ module HTTP { /** Gets a content-type associated with this body. */ string getAContentType() { - exists(HTTP::HeaderWrite hw | hw = this.getResponseWriter().getAHeaderWrite() | + exists(Http::HeaderWrite hw | hw = this.getResponseWriter().getAHeaderWrite() | hw.getHeaderName() = "content-type" and result = hw.getHeaderValue() ) @@ -189,7 +189,7 @@ module HTTP { /** Gets a dataflow node for a content-type associated with this body. */ DataFlow::Node getAContentTypeNode() { - exists(HTTP::HeaderWrite hw | hw = this.getResponseWriter().getAHeaderWrite() | + exists(Http::HeaderWrite hw | hw = this.getResponseWriter().getAHeaderWrite() | hw.getHeaderName() = "content-type" and result = hw.getValue() ) @@ -346,3 +346,6 @@ module HTTP { predicate guardedBy(DataFlow::Node check) { super.guardedBy(check) } } } + +/** DEPRECATED: Alias for Http */ +deprecated module HTTP = Http; diff --git a/go/ql/lib/semmle/go/frameworks/Beego.qll b/go/ql/lib/semmle/go/frameworks/Beego.qll index edcf383c6be..6d927112584 100644 --- a/go/ql/lib/semmle/go/frameworks/Beego.qll +++ b/go/ql/lib/semmle/go/frameworks/Beego.qll @@ -114,7 +114,7 @@ module Beego { } } - private class BeegoOutputInstance extends HTTP::ResponseWriter::Range { + private class BeegoOutputInstance extends Http::ResponseWriter::Range { SsaWithFields v; BeegoOutputInstance() { @@ -131,7 +131,7 @@ module Beego { } } - private class BeegoHeaderWrite extends HTTP::HeaderWrite::Range, DataFlow::MethodCallNode { + private class BeegoHeaderWrite extends Http::HeaderWrite::Range, DataFlow::MethodCallNode { string methodName; BeegoHeaderWrite() { @@ -142,7 +142,7 @@ module Beego { override DataFlow::Node getName() { methodName = "Header" and result = this.getArgument(0) } override string getHeaderName() { - result = HTTP::HeaderWrite::Range.super.getHeaderName() + result = Http::HeaderWrite::Range.super.getHeaderName() or methodName = "ContentType" and result = "content-type" } @@ -153,12 +153,12 @@ module Beego { else result = this.getArgument(1) } - override HTTP::ResponseWriter getResponseWriter() { + override Http::ResponseWriter getResponseWriter() { result.(BeegoOutputInstance).getAHeaderObject() = this } } - private class BeegoResponseBody extends HTTP::ResponseBody::Range { + private class BeegoResponseBody extends Http::ResponseBody::Range { DataFlow::MethodCallNode call; string methodName; @@ -170,7 +170,7 @@ module Beego { methodName in ["Body", "JSON", "JSONP", "ServeFormatted", "XML", "YAML"] } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = call.getReceiver() } + override Http::ResponseWriter getResponseWriter() { result.getANode() = call.getReceiver() } override string getAContentType() { // Super-method provides content-types for `Body`, which requires us to search @@ -192,7 +192,7 @@ module Beego { } } - private class ControllerResponseBody extends HTTP::ResponseBody::Range { + private class ControllerResponseBody extends Http::ResponseBody::Range { string name; ControllerResponseBody() { @@ -203,7 +203,7 @@ module Beego { ) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } override string getAContentType() { // Actually SetData can serve JSON, XML or YAML depending on the incoming @@ -213,7 +213,7 @@ module Beego { } } - private class ContextResponseBody extends HTTP::ResponseBody::Range { + private class ContextResponseBody extends Http::ResponseBody::Range { string name; ContextResponseBody() { @@ -224,7 +224,7 @@ module Beego { ) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } // Neither method is likely to be used with well-typed data such as JSON output, // because there are better methods to do this. Assume the Content-Type could @@ -314,7 +314,7 @@ module Beego { } } - private class RedirectMethods extends HTTP::Redirect::Range, DataFlow::CallNode { + private class RedirectMethods extends Http::Redirect::Range, DataFlow::CallNode { string package; string className; @@ -333,7 +333,7 @@ module Beego { className = "Context" and result = this.getArgument(1) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } } private class UtilsTaintPropagators extends TaintTracking::FunctionModel { diff --git a/go/ql/lib/semmle/go/frameworks/Echo.qll b/go/ql/lib/semmle/go/frameworks/Echo.qll index df58b492b87..c4d243b504c 100644 --- a/go/ql/lib/semmle/go/frameworks/Echo.qll +++ b/go/ql/lib/semmle/go/frameworks/Echo.qll @@ -29,7 +29,7 @@ private module Echo { /** * Data from a `Context` interface method that is not generally exploitable for open-redirect attacks. */ - private class EchoContextRedirectUnexploitableSource extends HTTP::Redirect::UnexploitableSource { + private class EchoContextRedirectUnexploitableSource extends Http::Redirect::UnexploitableSource { EchoContextRedirectUnexploitableSource() { exists(DataFlow::MethodCallNode call, string methodName | methodName = ["FormValue", "FormParams", "FormFile", "MultipartForm", "Cookie", "Cookies"] and @@ -77,14 +77,14 @@ private module Echo { /** * `echo.Context` methods which set the content-type to `text/html` and write a result in one operation. */ - private class EchoHtmlOutputs extends HTTP::ResponseBody::Range { + private class EchoHtmlOutputs extends Http::ResponseBody::Range { EchoHtmlOutputs() { exists(Method m | m.hasQualifiedName(packagePath(), "Context", ["HTML", "HTMLBlob"]) | this = m.getACall().getArgument(1) ) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } override string getAContentType() { result = "text/html" } } @@ -92,7 +92,7 @@ private module Echo { /** * `echo.Context` methods which take a content-type as a parameter. */ - private class EchoParameterizedOutputs extends HTTP::ResponseBody::Range { + private class EchoParameterizedOutputs extends Http::ResponseBody::Range { DataFlow::CallNode callNode; EchoParameterizedOutputs() { @@ -101,7 +101,7 @@ private module Echo { ) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } override DataFlow::Node getAContentTypeNode() { result = callNode.getArgument(1) } } @@ -109,7 +109,7 @@ private module Echo { /** * The `echo.Context.Redirect` method. */ - private class EchoRedirectMethod extends HTTP::Redirect::Range, DataFlow::CallNode { + private class EchoRedirectMethod extends Http::Redirect::Range, DataFlow::CallNode { EchoRedirectMethod() { exists(Method m | m.hasQualifiedName(packagePath(), "Context", "Redirect") | this = m.getACall() @@ -118,6 +118,6 @@ private module Echo { override DataFlow::Node getUrl() { result = this.getArgument(1) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } } } diff --git a/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll b/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll index 87c091fc3c5..42fb474a5f0 100644 --- a/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll +++ b/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll @@ -11,7 +11,7 @@ module ElazarlGoproxy { /** Gets the package name. */ string packagePath() { result = package("github.com/elazarl/goproxy", "") } - private class NewResponse extends HTTP::HeaderWrite::Range, DataFlow::CallNode { + private class NewResponse extends Http::HeaderWrite::Range, DataFlow::CallNode { NewResponse() { this.getTarget().hasQualifiedName(packagePath(), "NewResponse") } override string getHeaderName() { this.definesHeader(result, _) } @@ -28,21 +28,21 @@ module ElazarlGoproxy { header = "content-type" and value = this.getArgument(1).getStringValue() } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } } /** A body argument to a `NewResponse` call. */ - private class NewResponseBody extends HTTP::ResponseBody::Range { + private class NewResponseBody extends Http::ResponseBody::Range { NewResponse call; NewResponseBody() { this = call.getArgument(3) } override DataFlow::Node getAContentTypeNode() { result = call.getArgument(1) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } } - private class TextResponse extends HTTP::HeaderWrite::Range, DataFlow::CallNode { + private class TextResponse extends Http::HeaderWrite::Range, DataFlow::CallNode { TextResponse() { this.getTarget().hasQualifiedName(packagePath(), "TextResponse") } override string getHeaderName() { this.definesHeader(result, _) } @@ -59,22 +59,22 @@ module ElazarlGoproxy { header = "content-type" and value = "text/plain" } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } } /** A body argument to a `TextResponse` call. */ - private class TextResponseBody extends HTTP::ResponseBody::Range, TextResponse { + private class TextResponseBody extends Http::ResponseBody::Range, TextResponse { TextResponse call; TextResponseBody() { this = call.getArgument(2) } override DataFlow::Node getAContentTypeNode() { result = call.getArgument(1) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } } /** A handler attached to a goproxy proxy type. */ - private class ProxyHandler extends HTTP::RequestHandler::Range { + private class ProxyHandler extends Http::RequestHandler::Range { DataFlow::MethodCallNode handlerReg; ProxyHandler() { diff --git a/go/ql/lib/semmle/go/frameworks/Macaron.qll b/go/ql/lib/semmle/go/frameworks/Macaron.qll index a38b2b20da0..f107ec208ee 100644 --- a/go/ql/lib/semmle/go/frameworks/Macaron.qll +++ b/go/ql/lib/semmle/go/frameworks/Macaron.qll @@ -5,7 +5,7 @@ import go private module Macaron { - private class Context extends HTTP::ResponseWriter::Range { + private class Context extends Http::ResponseWriter::Range { SsaWithFields v; Context() { @@ -18,13 +18,13 @@ private module Macaron { override DataFlow::Node getANode() { result = v.similar().getAUse().getASuccessor*() } } - private class RedirectCall extends HTTP::Redirect::Range, DataFlow::MethodCallNode { + private class RedirectCall extends Http::Redirect::Range, DataFlow::MethodCallNode { RedirectCall() { this.getTarget().hasQualifiedName("gopkg.in/macaron.v1", "Context", "Redirect") } override DataFlow::Node getUrl() { result = this.getArgument(0) } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() } + override Http::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() } } } diff --git a/go/ql/lib/semmle/go/frameworks/Revel.qll b/go/ql/lib/semmle/go/frameworks/Revel.qll index 1ccad431b84..d006f46b2ee 100644 --- a/go/ql/lib/semmle/go/frameworks/Revel.qll +++ b/go/ql/lib/semmle/go/frameworks/Revel.qll @@ -114,7 +114,7 @@ module Revel { * We look particularly for html file extensions, since these are the only ones we currently have special rules * for (in particular, detecting XSS vulnerabilities). */ - private class ControllerRenderMethods extends HTTP::ResponseBody::Range { + private class ControllerRenderMethods extends Http::ResponseBody::Range { string contentType; ControllerRenderMethods() { @@ -149,7 +149,7 @@ module Revel { ) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } override string getAContentType() { result = contentType } } @@ -174,7 +174,7 @@ module Revel { * It is currently assumed that a tainted `value` in `Redirect(url, value)`, which calls `Sprintf(url, value)` * internally, cannot lead to an open redirect vulnerability. */ - private class ControllerRedirectMethod extends HTTP::Redirect::Range, DataFlow::CallNode { + private class ControllerRedirectMethod extends Http::Redirect::Range, DataFlow::CallNode { ControllerRedirectMethod() { exists(Method m | m.hasQualifiedName(packagePath(), "Controller", "Redirect") | this = m.getACall() @@ -183,7 +183,7 @@ module Revel { override DataFlow::Node getUrl() { result = this.getArgument(0) } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } } /** @@ -226,7 +226,7 @@ module Revel { /** * A write to a template argument field that is read raw inside of a template. */ - private class RawTemplateArgument extends HTTP::TemplateResponseBody::Range { + private class RawTemplateArgument extends Http::TemplateResponseBody::Range { RawTemplateRead read; RawTemplateArgument() { @@ -261,7 +261,7 @@ module Revel { override string getAContentType() { result = "text/html" } - override HTTP::ResponseWriter getResponseWriter() { none() } + override Http::ResponseWriter getResponseWriter() { none() } override HtmlTemplate::TemplateRead getRead() { result = read } } diff --git a/go/ql/lib/semmle/go/frameworks/Stdlib.qll b/go/ql/lib/semmle/go/frameworks/Stdlib.qll index b8481175216..db46167d205 100644 --- a/go/ql/lib/semmle/go/frameworks/Stdlib.qll +++ b/go/ql/lib/semmle/go/frameworks/Stdlib.qll @@ -128,7 +128,7 @@ module IntegerParser { } /** Provides models of commonly used functions in the `net/url` package. */ -module URL { +module Url { /** The `PathEscape` or `QueryEscape` function. */ class Escaper extends TaintTracking::FunctionModel { Escaper() { @@ -263,3 +263,6 @@ module URL { } } } + +/** DEPRECATED: Alias for Url */ +deprecated module URL = Url; diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll index c5e48e7d295..e0518ecf465 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll @@ -35,7 +35,7 @@ module NetHttp { } /** The declaration of a variable which either is or has a field that implements the http.ResponseWriter type */ - private class StdlibResponseWriter extends HTTP::ResponseWriter::Range { + private class StdlibResponseWriter extends Http::ResponseWriter::Range { SsaWithFields v; StdlibResponseWriter() { @@ -52,7 +52,7 @@ module NetHttp { } } - private class HeaderWriteCall extends HTTP::HeaderWrite::Range, DataFlow::MethodCallNode { + private class HeaderWriteCall extends Http::HeaderWrite::Range, DataFlow::MethodCallNode { HeaderWriteCall() { this.getTarget().hasQualifiedName("net/http", "Header", "Add") or this.getTarget().hasQualifiedName("net/http", "Header", "Set") @@ -62,7 +62,7 @@ module NetHttp { override DataFlow::Node getValue() { result = this.getArgument(1) } - override HTTP::ResponseWriter getResponseWriter() { + override Http::ResponseWriter getResponseWriter() { // find `v` in // ``` // header := v.Header() @@ -72,7 +72,7 @@ module NetHttp { } } - private class MapWrite extends HTTP::HeaderWrite::Range, DataFlow::Node { + private class MapWrite extends Http::HeaderWrite::Range, DataFlow::Node { Write write; DataFlow::Node index; DataFlow::Node rhs; @@ -86,7 +86,7 @@ module NetHttp { override DataFlow::Node getValue() { result = rhs } - override HTTP::ResponseWriter getResponseWriter() { + override Http::ResponseWriter getResponseWriter() { // find `v` in // ``` // header := v.Header() @@ -96,7 +96,7 @@ module NetHttp { } } - private class ResponseWriteHeaderCall extends HTTP::HeaderWrite::Range, DataFlow::MethodCallNode { + private class ResponseWriteHeaderCall extends Http::HeaderWrite::Range, DataFlow::MethodCallNode { ResponseWriteHeaderCall() { this.getTarget().implements("net/http", "ResponseWriter", "WriteHeader") } @@ -107,10 +107,10 @@ module NetHttp { override DataFlow::Node getValue() { result = this.getArgument(0) } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() } + override Http::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() } } - private class ResponseErrorCall extends HTTP::HeaderWrite::Range, DataFlow::CallNode { + private class ResponseErrorCall extends Http::HeaderWrite::Range, DataFlow::CallNode { ResponseErrorCall() { this.getTarget().hasQualifiedName("net/http", "Error") } override string getHeaderName() { result = "status" } @@ -119,10 +119,10 @@ module NetHttp { override DataFlow::Node getValue() { result = this.getArgument(2) } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getArgument(0) } + override Http::ResponseWriter getResponseWriter() { result.getANode() = this.getArgument(0) } } - private class RequestBody extends HTTP::RequestBody::Range, DataFlow::ExprNode { + private class RequestBody extends Http::RequestBody::Range, DataFlow::ExprNode { RequestBody() { exists(Function newRequest | newRequest.hasQualifiedName("net/http", "NewRequest") and @@ -137,7 +137,7 @@ module NetHttp { } } - private class ResponseBody extends HTTP::ResponseBody::Range, DataFlow::ArgumentNode { + private class ResponseBody extends Http::ResponseBody::Range, DataFlow::ArgumentNode { DataFlow::Node responseWriter; ResponseBody() { @@ -156,19 +156,19 @@ module NetHttp { ) } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = responseWriter } + override Http::ResponseWriter getResponseWriter() { result.getANode() = responseWriter } } - private class RedirectCall extends HTTP::Redirect::Range, DataFlow::CallNode { + private class RedirectCall extends Http::Redirect::Range, DataFlow::CallNode { RedirectCall() { this.getTarget().hasQualifiedName("net/http", "Redirect") } override DataFlow::Node getUrl() { result = this.getArgument(2) } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getArgument(0) } + override Http::ResponseWriter getResponseWriter() { result.getANode() = this.getArgument(0) } } /** A call to a function in the `net/http` package that performs an HTTP request to a URL. */ - private class RequestCall extends HTTP::ClientRequest::Range, DataFlow::CallNode { + private class RequestCall extends Http::ClientRequest::Range, DataFlow::CallNode { RequestCall() { exists(string functionName | ( @@ -185,7 +185,7 @@ module NetHttp { } /** A call to the Client.Do function in the `net/http` package. */ - private class ClientDo extends HTTP::ClientRequest::Range, DataFlow::MethodCallNode { + private class ClientDo extends Http::ClientRequest::Range, DataFlow::MethodCallNode { ClientDo() { this.getTarget().hasQualifiedName("net/http", "Client", "Do") } override DataFlow::Node getUrl() { @@ -212,7 +212,7 @@ module NetHttp { } /** A call to the `Transport.RoundTrip` function in the `net/http` package. */ - private class TransportRoundTrip extends HTTP::ClientRequest::Range, DataFlow::MethodCallNode { + private class TransportRoundTrip extends Http::ClientRequest::Range, DataFlow::MethodCallNode { TransportRoundTrip() { this.getTarget().hasQualifiedName("net/http", "Transport", "RoundTrip") } override DataFlow::Node getUrl() { @@ -239,7 +239,7 @@ module NetHttp { } /** Fields and methods of `net/http.Request` that are not generally exploitable in an open-redirect attack. */ - private class RedirectUnexploitableRequestFields extends HTTP::Redirect::UnexploitableSource { + private class RedirectUnexploitableRequestFields extends Http::Redirect::UnexploitableSource { RedirectUnexploitableRequestFields() { exists(Field f, string fieldName | f.hasQualifiedName("net/http", "Request", fieldName) and @@ -257,7 +257,7 @@ module NetHttp { } } - private class Handler extends HTTP::RequestHandler::Range { + private class Handler extends Http::RequestHandler::Range { DataFlow::CallNode handlerReg; Handler() { diff --git a/go/ql/lib/semmle/go/security/InsecureRandomness.qll b/go/ql/lib/semmle/go/security/InsecureRandomness.qll index f2db5860073..6de3071b598 100644 --- a/go/ql/lib/semmle/go/security/InsecureRandomness.qll +++ b/go/ql/lib/semmle/go/security/InsecureRandomness.qll @@ -29,5 +29,7 @@ module InsecureRandomness { /** Holds if `sink` is a sink for this configuration with kind `kind`. */ predicate isSink(Sink sink, string kind) { kind = sink.getKind() } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } } diff --git a/go/ql/lib/semmle/go/security/OpenUrlRedirectCustomizations.qll b/go/ql/lib/semmle/go/security/OpenUrlRedirectCustomizations.qll index d883c3c0101..80b9bb4a126 100644 --- a/go/ql/lib/semmle/go/security/OpenUrlRedirectCustomizations.qll +++ b/go/ql/lib/semmle/go/security/OpenUrlRedirectCustomizations.qll @@ -56,7 +56,7 @@ module OpenUrlRedirect { UntrustedFlowAsSource() { // exclude some fields and methods of URLs that are generally not attacker-controllable for // open redirect exploits - not this instanceof HTTP::Redirect::UnexploitableSource + not this instanceof Http::Redirect::UnexploitableSource } } @@ -64,7 +64,7 @@ module OpenUrlRedirect { * An HTTP redirect, considered as a sink for `Configuration`. */ class RedirectSink extends Sink, DataFlow::Node { - RedirectSink() { this = any(HTTP::Redirect redir).getUrl() } + RedirectSink() { this = any(Http::Redirect redir).getUrl() } } /** @@ -73,7 +73,7 @@ module OpenUrlRedirect { */ class LocationHeaderSink extends Sink, DataFlow::Node { LocationHeaderSink() { - exists(HTTP::HeaderWrite hw | hw.getHeaderName() = "location" | this = hw.getValue()) + exists(Http::HeaderWrite hw | hw.getHeaderName() = "location" | this = hw.getValue()) } } diff --git a/go/ql/lib/semmle/go/security/RequestForgeryCustomizations.qll b/go/ql/lib/semmle/go/security/RequestForgeryCustomizations.qll index b75b3503d55..b11157daa06 100644 --- a/go/ql/lib/semmle/go/security/RequestForgeryCustomizations.qll +++ b/go/ql/lib/semmle/go/security/RequestForgeryCustomizations.qll @@ -48,7 +48,7 @@ module RequestForgery { * The URL of an HTTP request, viewed as a sink for request forgery. */ private class ClientRequestUrlAsSink extends Sink { - HTTP::ClientRequest request; + Http::ClientRequest request; ClientRequestUrlAsSink() { this = request.getUrl() } diff --git a/go/ql/lib/semmle/go/security/SafeUrlFlowCustomizations.qll b/go/ql/lib/semmle/go/security/SafeUrlFlowCustomizations.qll index de0f95f8f3a..dbdb96a10a7 100644 --- a/go/ql/lib/semmle/go/security/SafeUrlFlowCustomizations.qll +++ b/go/ql/lib/semmle/go/security/SafeUrlFlowCustomizations.qll @@ -27,7 +27,7 @@ module SafeUrlFlow { /** * A method on a `net/url.URL` that is considered unsafe to use. */ - private class UnsafeUrlMethod extends URL::UrlGetter { + private class UnsafeUrlMethod extends Url::UrlGetter { UnsafeUrlMethod() { this.getName() = "Query" } } diff --git a/go/ql/lib/semmle/go/security/Xss.qll b/go/ql/lib/semmle/go/security/Xss.qll index 2ed5c5761a7..98b6da02fe8 100644 --- a/go/ql/lib/semmle/go/security/Xss.qll +++ b/go/ql/lib/semmle/go/security/Xss.qll @@ -6,8 +6,11 @@ import go /** Provides classes and predicates shared between the XSS queries. */ module SharedXss { - /** A data flow source for XSS vulnerabilities. */ - abstract class Source extends DataFlow::Node { } + /** + * DEPRECATED: This class is not used. + * A data flow source for XSS vulnerabilities. + */ + abstract deprecated class Source extends DataFlow::Node { } /** A data flow sink for XSS vulnerabilities. */ abstract class Sink extends DataFlow::Node { @@ -46,14 +49,14 @@ module SharedXss { * a content type that does not (case-insensitively) contain the string "html". This * is to prevent us from flagging plain-text or JSON responses as vulnerable. */ - class HttpResponseBodySink extends Sink, HTTP::ResponseBody { + class HttpResponseBodySink extends Sink, Http::ResponseBody { HttpResponseBodySink() { not nonHtmlContentType(this) } } /** * An expression that is rendered as part of a template. */ - class RawTemplateInstantiationSink extends HttpResponseBodySink, HTTP::TemplateResponseBody { + class RawTemplateInstantiationSink extends HttpResponseBodySink, Http::TemplateResponseBody { override string getSinkKind() { result = "rawtemplate" } override Locatable getAssociatedLoc() { result = this.getRead().getEnclosingTextNode() } @@ -62,7 +65,7 @@ module SharedXss { /** * Holds if `body` may send a response with a content type other than HTML. */ - private predicate nonHtmlContentType(HTTP::ResponseBody body) { + private predicate nonHtmlContentType(Http::ResponseBody body) { not htmlTypeSpecified(body) and ( exists(body.getAContentType()) @@ -90,7 +93,7 @@ module SharedXss { /** * Holds if `body` specifies the response's content type to be HTML. */ - private predicate htmlTypeSpecified(HTTP::ResponseBody body) { + private predicate htmlTypeSpecified(Http::ResponseBody body) { body.getAContentType().regexpMatch("(?i).*html.*") } diff --git a/go/ql/src/CHANGELOG.md b/go/ql/src/CHANGELOG.md index 0f01c599559..7f394f66ff0 100644 --- a/go/ql/src/CHANGELOG.md +++ b/go/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.2.5 + ## 0.2.4 ## 0.2.3 diff --git a/go/ql/src/InconsistentCode/ConstantLengthComparison.ql b/go/ql/src/InconsistentCode/ConstantLengthComparison.ql index 6058e287dec..c60e093650f 100644 --- a/go/ql/src/InconsistentCode/ConstantLengthComparison.ql +++ b/go/ql/src/InconsistentCode/ConstantLengthComparison.ql @@ -30,5 +30,5 @@ where cond.dominates(idx.getBasicBlock()) and // and that check happens inside the loop body cond.getCondition().getParent+() = fs -select cond.getCondition(), - "This checks the length against a constant, but it is indexed using a variable $@.", idx, "here" +select cond.getCondition(), "This checks the length against a constant, but it $@.", idx, + "is indexed using a variable" diff --git a/go/ql/src/InconsistentCode/MissingErrorCheck.ql b/go/ql/src/InconsistentCode/MissingErrorCheck.ql index 604d4c7f8a9..d2021517267 100644 --- a/go/ql/src/InconsistentCode/MissingErrorCheck.ql +++ b/go/ql/src/InconsistentCode/MissingErrorCheck.ql @@ -116,5 +116,5 @@ where // `deref` dereferences `ptr` deref.getOperand() = ptr.getAUse() select deref.getOperand(), - ptr.getSourceVariable() + " may be nil here, because $@ may not have been checked.", err, - err.getSourceVariable().toString() + "$@ may be nil at this dereference because $@ may not have been checked.", ptr, + ptr.getSourceVariable().toString(), err, err.getSourceVariable().toString() diff --git a/go/ql/src/RedundantCode/CompareIdenticalValues.ql b/go/ql/src/RedundantCode/CompareIdenticalValues.ql index d2703d8f58c..cd4d9d6dbfa 100644 --- a/go/ql/src/RedundantCode/CompareIdenticalValues.ql +++ b/go/ql/src/RedundantCode/CompareIdenticalValues.ql @@ -24,4 +24,4 @@ where cmp.getAnOperand() = decl.getAReference() and cmp.getAnOperand() instanceof BasicLit ) -select cmp, "This expression compares $@ to itself.", cmp.getLeftOperand(), "an expression" +select cmp, "This expression compares an $@ to itself.", cmp.getLeftOperand(), "expression" diff --git a/go/ql/src/RedundantCode/DuplicateCondition.ql b/go/ql/src/RedundantCode/DuplicateCondition.ql index 3d7416450dc..fb031044e47 100644 --- a/go/ql/src/RedundantCode/DuplicateCondition.ql +++ b/go/ql/src/RedundantCode/DuplicateCondition.ql @@ -30,4 +30,4 @@ GVN conditionGvn(IfStmt is, int i, Expr e) { from IfStmt is, Expr e, Expr f, int i, int j where conditionGvn(is, i, e) = conditionGvn(is, j, f) and i < j -select f, "This condition is a duplicate of $@.", e, "an earlier condition" +select f, "This condition is a duplicate of an $@.", e, "earlier condition" diff --git a/go/ql/src/RedundantCode/DuplicateSwitchCase.ql b/go/ql/src/RedundantCode/DuplicateSwitchCase.ql index b2777a1131f..3096f3bef94 100644 --- a/go/ql/src/RedundantCode/DuplicateSwitchCase.ql +++ b/go/ql/src/RedundantCode/DuplicateSwitchCase.ql @@ -20,4 +20,4 @@ GVN switchCaseGvn(SwitchStmt switch, int i, Expr e) { from SwitchStmt switch, int i, Expr e, int j, Expr f where switchCaseGvn(switch, i, e) = switchCaseGvn(switch, j, f) and i < j -select f, "This case is a duplicate of $@.", e, "an earlier case" +select f, "This case is a duplicate of an $@.", e, "earlier case" diff --git a/go/ql/src/RedundantCode/SelfAssignment.ql b/go/ql/src/RedundantCode/SelfAssignment.ql index fc5300efbeb..08647422669 100644 --- a/go/ql/src/RedundantCode/SelfAssignment.ql +++ b/go/ql/src/RedundantCode/SelfAssignment.ql @@ -23,4 +23,4 @@ from PotentialSelfAssignment assgn, HashableNode rhs where rhs = assgn.getRhs() and rhs.hash() = assgn.getLhs().(HashableNode).hash() -select assgn, "This statement assigns $@ to itself.", rhs, "an expression" +select assgn, "This statement assigns an $@ to itself.", rhs, "expression" diff --git a/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql b/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql index a6ce8c8c8b6..fdd83673b74 100644 --- a/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql +++ b/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql @@ -33,7 +33,7 @@ predicate isIncompleteHostNameRegexpPattern(string pattern, string hostPart) { /** Holds if `b` sets the HTTP status code (represented by a pseudo-header named `status`) */ predicate writesHttpError(ReachableBasicBlock b) { - forex(HTTP::HeaderWrite hw | + forex(Http::HeaderWrite hw | hw.getHeaderName() = "status" and hw.asInstruction().getBasicBlock() = b | exists(string code | code.matches("4__") or code.matches("5__") | @@ -65,7 +65,7 @@ DataFlow::Node getASafeHandler() { } /** Holds if `regexp` is used in a check before `handler` is called. */ -predicate regexpGuardsHandler(RegexpPattern regexp, HTTP::RequestHandler handler) { +predicate regexpGuardsHandler(RegexpPattern regexp, Http::RequestHandler handler) { handler.guardedBy(DataFlow::exprNode(regexp.getAUse().asExpr().getParent*())) } @@ -99,7 +99,7 @@ class Config extends DataFlow::Configuration { override predicate isSink(DataFlow::Node sink) { sink instanceof RegexpPattern and - forall(HTTP::RequestHandler handler | regexpGuardsHandler(sink, handler) | + forall(Http::RequestHandler handler | regexpGuardsHandler(sink, handler) | not handler = getASafeHandler() ) and not regexpGuardsError(sink) @@ -110,4 +110,4 @@ from Config c, DataFlow::PathNode source, DataFlow::PathNode sink, string hostPa where c.hasFlowPath(source, sink) and c.isSource(source.getNode(), hostPart) select source, source, sink, "This regular expression has an unescaped dot before '" + hostPart + "', " + - "so it might match more hosts than expected when used $@.", sink, "here" + "so it might match more hosts than expected when $@.", sink, "the regular expression is used" diff --git a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql index 6dbdaf640d4..71ae1ac183a 100644 --- a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql +++ b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql @@ -48,5 +48,5 @@ class Config extends DataFlow::Configuration { from Config c, DataFlow::PathNode source, DataFlow::PathNode sink, string report where c.hasFlowPath(source, sink) and c.isSource(source.getNode(), report) -select source, source, sink, "$@ used $@ contains " + report, source, "A regular expression", sink, - "here" +select source, source, sink, "$@ that is $@ contains " + report, source, "A string literal", sink, + "used as a regular expression" diff --git a/go/ql/src/Security/CWE-022/TaintedPath.ql b/go/ql/src/Security/CWE-022/TaintedPath.ql index 34738292f09..870fc2e97e1 100644 --- a/go/ql/src/Security/CWE-022/TaintedPath.ql +++ b/go/ql/src/Security/CWE-022/TaintedPath.ql @@ -21,5 +21,5 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ flows to here and is used in a path.", source.getNode(), - "User-provided value" +select sink.getNode(), source, sink, "This path depends on a $@.", source.getNode(), + "user-provided value" diff --git a/go/ql/src/Security/CWE-078/CommandInjection.ql b/go/ql/src/Security/CWE-078/CommandInjection.ql index 844d17bd0ac..925f2b32ab2 100644 --- a/go/ql/src/Security/CWE-078/CommandInjection.ql +++ b/go/ql/src/Security/CWE-078/CommandInjection.ql @@ -19,5 +19,5 @@ from CommandInjection::Configuration cfg, CommandInjection::DoubleDashSanitizingConfiguration cfg2, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) or cfg2.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This command depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "This command depends on a $@.", source.getNode(), + "user-provided value" diff --git a/go/ql/src/Security/CWE-078/StoredCommand.ql b/go/ql/src/Security/CWE-078/StoredCommand.ql index 605a9fe3ea6..c7675527cc8 100644 --- a/go/ql/src/Security/CWE-078/StoredCommand.ql +++ b/go/ql/src/Security/CWE-078/StoredCommand.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from StoredCommand::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This command depends on $@.", source.getNode(), - "a stored value" +select sink.getNode(), source, sink, "This command depends on a $@.", source.getNode(), + "stored value" diff --git a/go/ql/src/Security/CWE-079/ReflectedXss.ql b/go/ql/src/Security/CWE-079/ReflectedXss.ql index 0c33026dada..f8da256432a 100644 --- a/go/ql/src/Security/CWE-079/ReflectedXss.ql +++ b/go/ql/src/Security/CWE-079/ReflectedXss.ql @@ -24,9 +24,8 @@ where ( exists(string kind | kind = sink.getNode().(SharedXss::Sink).getSinkKind() | kind = "rawtemplate" and - msg = - "Cross-site scripting vulnerability due to $@. This template argument is instantiated raw $@." and - part = "here" + msg = "Cross-site scripting vulnerability due to $@. The value is $@." and + part = "instantiated as a raw template" ) or not exists(sink.getNode().(SharedXss::Sink).getSinkKind()) and diff --git a/go/ql/src/Security/CWE-089/SqlInjection.ql b/go/ql/src/Security/CWE-089/SqlInjection.ql index c228787a1f3..0206f4e88cd 100644 --- a/go/ql/src/Security/CWE-089/SqlInjection.ql +++ b/go/ql/src/Security/CWE-089/SqlInjection.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from SqlInjection::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This query depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(), + "user-provided value" diff --git a/go/ql/src/Security/CWE-117/LogInjection.ql b/go/ql/src/Security/CWE-117/LogInjection.ql index 175b5fed924..070788af884 100644 --- a/go/ql/src/Security/CWE-117/LogInjection.ql +++ b/go/ql/src/Security/CWE-117/LogInjection.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from LogInjection::Configuration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink, source, sink, "This log write receives unsanitized user input from $@.", - source.getNode(), "here" +select sink.getNode(), source, sink, "Log entry depends on a $@.", source.getNode(), + "user-provided value" diff --git a/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql b/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql index fcbfb4dfd22..c52e9c33305 100644 --- a/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql +++ b/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql @@ -22,5 +22,5 @@ where cfg.hasFlowPath(source, sink) and cfg.isSink(sink.getNode(), allocsz) select sink, source, sink, - "This operation, which is used in an $@, involves a potentially large $@ and might overflow.", - allocsz, "allocation", source, "value" + "This operation, which is used in an $@, involves a $@ and might overflow.", allocsz, + "allocation", source, "potentially large value" diff --git a/go/ql/src/Security/CWE-209/StackTraceExposure.ql b/go/ql/src/Security/CWE-209/StackTraceExposure.ql index a2005663784..cf95ac45418 100644 --- a/go/ql/src/Security/CWE-209/StackTraceExposure.ql +++ b/go/ql/src/Security/CWE-209/StackTraceExposure.ql @@ -60,7 +60,7 @@ class StackTraceExposureConfig extends TaintTracking::Configuration { node = any(DebugStackFunction f).getACall().getResult() } - override predicate isSink(DataFlow::Node node) { node instanceof HTTP::ResponseBody } + override predicate isSink(DataFlow::Node node) { node instanceof Http::ResponseBody } override predicate isSanitizer(DataFlow::Node node) { // Sanitise everything controlled by an is-debug-mode check. @@ -77,5 +77,5 @@ class StackTraceExposureConfig extends TaintTracking::Configuration { from StackTraceExposureConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "Stack trace information from $@ may be exposed to an external user here.", source.getNode(), - "here" + "HTTP response depends on $@ and may be exposed to an external user.", source.getNode(), + "stack trace information" diff --git a/go/ql/src/Security/CWE-312/CleartextLogging.ql b/go/ql/src/Security/CWE-312/CleartextLogging.ql index 57412739984..52e09051dd8 100644 --- a/go/ql/src/Security/CWE-312/CleartextLogging.ql +++ b/go/ql/src/Security/CWE-312/CleartextLogging.ql @@ -19,5 +19,5 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Sensitive data returned by $@ is logged here.", - source.getNode(), source.getNode().(Source).describe() +select sink.getNode(), source, sink, "$@ flows to a logging call.", source.getNode(), + "Sensitive data returned by " + source.getNode().(Source).describe() diff --git a/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql b/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql index efadce04a6c..63c8b945ab3 100644 --- a/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql +++ b/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql @@ -24,5 +24,5 @@ where // this excludes flow from safe parts of request URLs, for example the full URL when the // doing a redirect from `http://` to `https://` not scfg.hasFlow(_, sink.getNode()) -select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.", source.getNode(), +select sink.getNode(), source, sink, "Untrusted URL redirection depends on a $@.", source.getNode(), "user-provided value" diff --git a/go/ql/src/Security/CWE-643/XPathInjection.ql b/go/ql/src/Security/CWE-643/XPathInjection.ql index 24642d5a1dd..aa732debead 100644 --- a/go/ql/src/Security/CWE-643/XPathInjection.ql +++ b/go/ql/src/Security/CWE-643/XPathInjection.ql @@ -24,5 +24,5 @@ predicate isStringOrByte(DataFlow::PathNode node) { from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) and isStringOrByte(sink) -select sink.getNode(), source, sink, "$@ flows to here and is used in an XPath expression.", - source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "XPath expression depends on a $@.", source.getNode(), + "user-provided value" diff --git a/go/ql/src/Security/CWE-918/RequestForgery.ql b/go/ql/src/Security/CWE-918/RequestForgery.ql index 6f1e9b5cbfc..a9d0b10dc00 100644 --- a/go/ql/src/Security/CWE-918/RequestForgery.ql +++ b/go/ql/src/Security/CWE-918/RequestForgery.ql @@ -23,5 +23,5 @@ where request = sink.getNode().(Sink).getARequest() and // this excludes flow from safe parts of request URLs, for example the full URL not scfg.hasFlow(_, sink.getNode()) -select request, source, sink, "The $@ of this request depends on $@.", sink.getNode(), - sink.getNode().(Sink).getKind(), source, "a user-provided value" +select request, source, sink, "The $@ of this request depends on a $@.", sink.getNode(), + sink.getNode().(Sink).getKind(), source, "user-provided value" diff --git a/go/ql/src/change-notes/released/0.2.5.md b/go/ql/src/change-notes/released/0.2.5.md new file mode 100644 index 00000000000..ec3e1ae7d2f --- /dev/null +++ b/go/ql/src/change-notes/released/0.2.5.md @@ -0,0 +1 @@ +## 0.2.5 diff --git a/go/ql/src/codeql-pack.release.yml b/go/ql/src/codeql-pack.release.yml index 7f1e3841dcd..211454ed306 100644 --- a/go/ql/src/codeql-pack.release.yml +++ b/go/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.2.4 +lastReleaseVersion: 0.2.5 diff --git a/go/ql/src/experimental/CWE-090/LDAPInjection.ql b/go/ql/src/experimental/CWE-090/LDAPInjection.ql index 2be416a14d2..48f751b29bd 100644 --- a/go/ql/src/experimental/CWE-090/LDAPInjection.ql +++ b/go/ql/src/experimental/CWE-090/LDAPInjection.ql @@ -15,5 +15,5 @@ import DataFlow::PathGraph from LdapInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "LDAP query parameter is derived from $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "LDAP query parameter depends on a $@.", source.getNode(), + "user-provided value" diff --git a/go/ql/src/experimental/CWE-840/ConditionalBypass.ql b/go/ql/src/experimental/CWE-840/ConditionalBypass.ql index 09d8aefe3f9..1776c3a7d87 100644 --- a/go/ql/src/experimental/CWE-840/ConditionalBypass.ql +++ b/go/ql/src/experimental/CWE-840/ConditionalBypass.ql @@ -35,6 +35,5 @@ where rhs.getNode().asExpr() = c.getRightOperand() and config.hasFlowPath(lhsSource, lhs) and lhs.getNode().asExpr() = c.getLeftOperand() -select c, - "This comparison compares user-controlled values from $@ and $@, and hence can be bypassed.", - lhsSource, "here", rhsSource, "here" +select c, "This comparison of a $@ with another $@ can be bypassed by a malicious user.", + lhsSource.getNode(), "user-controlled value", rhsSource.getNode(), "user-controlled value" diff --git a/go/ql/src/experimental/CWE-918/SSRF.qll b/go/ql/src/experimental/CWE-918/SSRF.qll index b7a408902d0..cf264c8c0b6 100644 --- a/go/ql/src/experimental/CWE-918/SSRF.qll +++ b/go/ql/src/experimental/CWE-918/SSRF.qll @@ -74,7 +74,7 @@ module ServerSideRequestForgery { * The URL of an HTTP request, viewed as a sink for request forgery. */ private class ClientRequestUrlAsSink extends Sink { - HTTP::ClientRequest request; + Http::ClientRequest request; ClientRequestUrlAsSink() { this = request.getUrl() } diff --git a/go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql b/go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql index 4e4b452fb8e..372b1c21642 100644 --- a/go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql +++ b/go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql @@ -41,14 +41,14 @@ string headerAllowCredentials() { result = "Access-Control-Allow-Credentials".to /** * An `Access-Control-Allow-Origin` header write. */ -class AllowOriginHeaderWrite extends HTTP::HeaderWrite { +class AllowOriginHeaderWrite extends Http::HeaderWrite { AllowOriginHeaderWrite() { this.getHeaderName() = headerAllowOrigin() } } /** * An `Access-Control-Allow-Credentials` header write. */ -class AllowCredentialsHeaderWrite extends HTTP::HeaderWrite { +class AllowCredentialsHeaderWrite extends Http::HeaderWrite { AllowCredentialsHeaderWrite() { this.getHeaderName() = headerAllowCredentials() } } diff --git a/go/ql/src/experimental/frameworks/CleverGo.qll b/go/ql/src/experimental/frameworks/CleverGo.qll index c061c416b88..99d57a46189 100644 --- a/go/ql/src/experimental/frameworks/CleverGo.qll +++ b/go/ql/src/experimental/frameworks/CleverGo.qll @@ -174,7 +174,7 @@ private module CleverGo { /** * Models HTTP redirects. */ - private class HttpRedirect extends HTTP::Redirect::Range, DataFlow::CallNode { + private class HttpRedirect extends Http::Redirect::Range, DataFlow::CallNode { string package; DataFlow::Node urlNode; @@ -191,13 +191,13 @@ private module CleverGo { override DataFlow::Node getUrl() { result = urlNode } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() } + override Http::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() } } /** * Models HTTP ResponseBody where the content-type is static and non-modifiable. */ - private class HttpResponseBodyStaticContentType extends HTTP::ResponseBody::Range { + private class HttpResponseBodyStaticContentType extends Http::ResponseBody::Range { string contentTypeString; DataFlow::Node receiverNode; @@ -209,7 +209,7 @@ private module CleverGo { override string getAContentType() { result = contentTypeString } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } + override Http::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } } // Holds for a call that sets the body; the content-type is implicitly set. @@ -304,7 +304,7 @@ private module CleverGo { /** * Models HTTP ResponseBody where the content-type can be dynamically set by the caller. */ - private class HttpResponseBodyDynamicContentType extends HTTP::ResponseBody::Range { + private class HttpResponseBodyDynamicContentType extends Http::ResponseBody::Range { DataFlow::Node contentTypeNode; DataFlow::Node receiverNode; @@ -316,7 +316,7 @@ private module CleverGo { override DataFlow::Node getAContentTypeNode() { result = contentTypeNode } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } + override Http::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } } // Holds for a call that sets the body; the content-type is a parameter. @@ -352,7 +352,7 @@ private module CleverGo { /** * Models HTTP ResponseBody where only the body is set. */ - private class HttpResponseBodyNoContentType extends HTTP::ResponseBody::Range { + private class HttpResponseBodyNoContentType extends Http::ResponseBody::Range { DataFlow::Node receiverNode; HttpResponseBodyNoContentType() { @@ -361,7 +361,7 @@ private module CleverGo { ) } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } + override Http::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } } // Holds for a call that sets the body. The content-type is not defined. @@ -394,7 +394,7 @@ private module CleverGo { * Models HTTP header writers. * The write is done with a call where you can set both the key and the value of the header. */ - private class HeaderWrite extends HTTP::HeaderWrite::Range, DataFlow::CallNode { + private class HeaderWrite extends Http::HeaderWrite::Range, DataFlow::CallNode { DataFlow::Node receiverNode; DataFlow::Node headerNameNode; DataFlow::Node headerValueNode; @@ -407,7 +407,7 @@ private module CleverGo { override DataFlow::Node getValue() { result = headerValueNode } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } + override Http::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } } // Holds for a call that sets a header with a key-value combination. @@ -437,7 +437,7 @@ private module CleverGo { /** * Models an HTTP static content-type header setter. */ - private class StaticContentTypeHeaderSetter extends HTTP::HeaderWrite::Range, DataFlow::CallNode { + private class StaticContentTypeHeaderSetter extends Http::HeaderWrite::Range, DataFlow::CallNode { DataFlow::Node receiverNode; string valueString; @@ -453,7 +453,7 @@ private module CleverGo { override DataFlow::Node getValue() { none() } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } + override Http::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } } // Holds for a call that sets the content-type header (implicit). @@ -494,7 +494,7 @@ private module CleverGo { /** * Models an HTTP dynamic content-type header setter. */ - private class DynamicContentTypeHeaderSetter extends HTTP::HeaderWrite::Range, DataFlow::CallNode { + private class DynamicContentTypeHeaderSetter extends Http::HeaderWrite::Range, DataFlow::CallNode { DataFlow::Node receiverNode; DataFlow::Node valueNode; @@ -508,7 +508,7 @@ private module CleverGo { override DataFlow::Node getValue() { result = valueNode } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } + override Http::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } } // Holds for a call that sets the content-type header via a parameter. diff --git a/go/ql/src/experimental/frameworks/Fiber.qll b/go/ql/src/experimental/frameworks/Fiber.qll index a3240a0b85a..3a7e71e204e 100644 --- a/go/ql/src/experimental/frameworks/Fiber.qll +++ b/go/ql/src/experimental/frameworks/Fiber.qll @@ -129,7 +129,7 @@ private module Fiber { /** * Models HTTP redirects. */ - private class Redirect extends HTTP::Redirect::Range, DataFlow::CallNode { + private class Redirect extends Http::Redirect::Range, DataFlow::CallNode { string package; DataFlow::Node urlNode; @@ -146,14 +146,14 @@ private module Fiber { override DataFlow::Node getUrl() { result = urlNode } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() } + override Http::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() } } /** * Models HTTP header writers. * The write is done with a call where you can set both the key and the value of the header. */ - private class HeaderWrite extends HTTP::HeaderWrite::Range, DataFlow::CallNode { + private class HeaderWrite extends Http::HeaderWrite::Range, DataFlow::CallNode { DataFlow::Node receiverNode; DataFlow::Node headerNameNode; DataFlow::Node headerValueNode; @@ -166,7 +166,7 @@ private module Fiber { override DataFlow::Node getValue() { result = headerValueNode } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } + override Http::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } } // Holds for a call that sets a header with a key-value combination. @@ -201,7 +201,7 @@ private module Fiber { /** * Models HTTP ResponseBody where the content-type is static and non-modifiable. */ - private class ResponseBodyStaticContentType extends HTTP::ResponseBody::Range { + private class ResponseBodyStaticContentType extends Http::ResponseBody::Range { string contentTypeString; DataFlow::Node receiverNode; @@ -213,7 +213,7 @@ private module Fiber { override string getAContentType() { result = contentTypeString } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } + override Http::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } } // Holds for a call that sets the body; the content-type is implicitly set. @@ -248,7 +248,7 @@ private module Fiber { /** * Models HTTP ResponseBody where only the body is set. */ - private class ResponseBodyNoContentType extends HTTP::ResponseBody::Range { + private class ResponseBodyNoContentType extends Http::ResponseBody::Range { DataFlow::Node receiverNode; ResponseBodyNoContentType() { @@ -257,7 +257,7 @@ private module Fiber { ) } - override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } + override Http::ResponseWriter getResponseWriter() { result.getANode() = receiverNode } } // Holds for a call that sets the body. The content-type is not defined. diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index 4e9b30f4fc5..f09a484438b 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 0.2.5-dev +version: 0.2.6-dev groups: - go - queries diff --git a/go/ql/test/experimental/CWE-090/LDAPInjection.expected b/go/ql/test/experimental/CWE-090/LDAPInjection.expected index de21efee2be..6395227df6e 100644 --- a/go/ql/test/experimental/CWE-090/LDAPInjection.expected +++ b/go/ql/test/experimental/CWE-090/LDAPInjection.expected @@ -40,14 +40,14 @@ nodes | LDAPInjection.go:81:25:81:33 | untrusted | semmle.label | untrusted | subpaths #select -| LDAPInjection.go:59:3:59:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:59:3:59:11 | untrusted | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:61:3:61:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:61:3:61:51 | ...+... | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:62:3:62:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:62:3:62:33 | slice literal | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:66:3:66:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:66:3:66:11 | untrusted | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:68:3:68:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:68:3:68:51 | ...+... | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:69:3:69:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:69:3:69:33 | slice literal | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:73:3:73:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:73:3:73:11 | untrusted | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:75:3:75:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:75:3:75:51 | ...+... | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:76:3:76:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:76:3:76:33 | slice literal | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:80:22:80:30 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:80:22:80:30 | untrusted | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | -| LDAPInjection.go:81:25:81:33 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:81:25:81:33 | untrusted | LDAP query parameter is derived from $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | a user-provided value | +| LDAPInjection.go:59:3:59:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:59:3:59:11 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:61:3:61:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:61:3:61:51 | ...+... | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:62:3:62:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:62:3:62:33 | slice literal | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:66:3:66:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:66:3:66:11 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:68:3:68:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:68:3:68:51 | ...+... | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:69:3:69:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:69:3:69:33 | slice literal | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:73:3:73:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:73:3:73:11 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:75:3:75:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:75:3:75:51 | ...+... | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:76:3:76:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:76:3:76:33 | slice literal | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:80:22:80:30 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:80:22:80:30 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:81:25:81:33 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:81:25:81:33 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | diff --git a/go/ql/test/experimental/CWE-840/ConditionalBypass.expected b/go/ql/test/experimental/CWE-840/ConditionalBypass.expected index c57a25bddff..1ea23f8223e 100644 --- a/go/ql/test/experimental/CWE-840/ConditionalBypass.expected +++ b/go/ql/test/experimental/CWE-840/ConditionalBypass.expected @@ -1,3 +1,3 @@ -| ConditionalBypassBad.go:9:5:9:46 | ...!=... | This comparison compares user-controlled values from $@ and $@, and hence can be bypassed. | ConditionalBypassBad.go:9:5:9:12 | selection of Header : Header | here | ConditionalBypassBad.go:9:41:9:46 | selection of Host : string | here | -| condition.go:9:5:9:46 | ...!=... | This comparison compares user-controlled values from $@ and $@, and hence can be bypassed. | condition.go:9:5:9:12 | selection of Header : Header | here | condition.go:9:41:9:46 | selection of Host : string | here | -| condition.go:16:5:16:62 | ...!=... | This comparison compares user-controlled values from $@ and $@, and hence can be bypassed. | condition.go:16:5:16:12 | selection of Header : Header | here | condition.go:16:41:16:48 | selection of Header : Header | here | +| ConditionalBypassBad.go:9:5:9:46 | ...!=... | This comparison of a $@ with another $@ can be bypassed by a malicious user. | ConditionalBypassBad.go:9:5:9:12 | selection of Header | user-controlled value | ConditionalBypassBad.go:9:41:9:46 | selection of Host | user-controlled value | +| condition.go:9:5:9:46 | ...!=... | This comparison of a $@ with another $@ can be bypassed by a malicious user. | condition.go:9:5:9:12 | selection of Header | user-controlled value | condition.go:9:41:9:46 | selection of Host | user-controlled value | +| condition.go:16:5:16:62 | ...!=... | This comparison of a $@ with another $@ can be bypassed by a malicious user. | condition.go:16:5:16:12 | selection of Header | user-controlled value | condition.go:16:41:16:48 | selection of Header | user-controlled value | diff --git a/go/ql/test/experimental/frameworks/CleverGo/HeaderWrite.ql b/go/ql/test/experimental/frameworks/CleverGo/HeaderWrite.ql index 3f33ae98248..20dc73705a8 100644 --- a/go/ql/test/experimental/frameworks/CleverGo/HeaderWrite.ql +++ b/go/ql/test/experimental/frameworks/CleverGo/HeaderWrite.ql @@ -11,7 +11,7 @@ class HttpHeaderWriteTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { // Dynamic key-value header: - exists(HTTP::HeaderWrite hw | + exists(Http::HeaderWrite hw | hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and ( @@ -26,7 +26,7 @@ class HttpHeaderWriteTest extends InlineExpectationsTest { ) or // Static key, dynamic value header: - exists(HTTP::HeaderWrite hw | + exists(Http::HeaderWrite hw | hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and ( @@ -41,7 +41,7 @@ class HttpHeaderWriteTest extends InlineExpectationsTest { ) or // Static key, static value header: - exists(HTTP::HeaderWrite hw | + exists(Http::HeaderWrite hw | hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and ( diff --git a/go/ql/test/experimental/frameworks/CleverGo/HttpRedirect.ql b/go/ql/test/experimental/frameworks/CleverGo/HttpRedirect.ql index 5ceb813cec9..4b7bcb7823c 100644 --- a/go/ql/test/experimental/frameworks/CleverGo/HttpRedirect.ql +++ b/go/ql/test/experimental/frameworks/CleverGo/HttpRedirect.ql @@ -9,7 +9,7 @@ class HttpRedirectTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "redirectUrl" and - exists(HTTP::Redirect rd | + exists(Http::Redirect rd | rd.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and element = rd.getUrl().toString() and diff --git a/go/ql/test/experimental/frameworks/CleverGo/HttpResponseBody.ql b/go/ql/test/experimental/frameworks/CleverGo/HttpResponseBody.ql index 33c3f94ec07..a2b3dc62167 100644 --- a/go/ql/test/experimental/frameworks/CleverGo/HttpResponseBody.ql +++ b/go/ql/test/experimental/frameworks/CleverGo/HttpResponseBody.ql @@ -8,7 +8,7 @@ class HttpResponseBodyTest extends InlineExpectationsTest { override string getARelevantTag() { result = ["contentType", "responseBody"] } override predicate hasActualResult(Location location, string element, string tag, string value) { - exists(HTTP::ResponseBody rd | + exists(Http::ResponseBody rd | rd.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and ( diff --git a/go/ql/test/experimental/frameworks/Fiber/HeaderWrite.ql b/go/ql/test/experimental/frameworks/Fiber/HeaderWrite.ql index d83883f45a7..0130172e7d0 100644 --- a/go/ql/test/experimental/frameworks/Fiber/HeaderWrite.ql +++ b/go/ql/test/experimental/frameworks/Fiber/HeaderWrite.ql @@ -11,7 +11,7 @@ class HttpHeaderWriteTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { // Dynamic key-value header: - exists(HTTP::HeaderWrite hw | + exists(Http::HeaderWrite hw | hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and ( @@ -26,7 +26,7 @@ class HttpHeaderWriteTest extends InlineExpectationsTest { ) or // Static key, dynamic value header: - exists(HTTP::HeaderWrite hw | + exists(Http::HeaderWrite hw | hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and ( @@ -41,7 +41,7 @@ class HttpHeaderWriteTest extends InlineExpectationsTest { ) or // Static key, static value header: - exists(HTTP::HeaderWrite hw | + exists(Http::HeaderWrite hw | hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and ( diff --git a/go/ql/test/experimental/frameworks/Fiber/Redirect.ql b/go/ql/test/experimental/frameworks/Fiber/Redirect.ql index 68d5bee465c..37bb0f97bfb 100644 --- a/go/ql/test/experimental/frameworks/Fiber/Redirect.ql +++ b/go/ql/test/experimental/frameworks/Fiber/Redirect.ql @@ -9,7 +9,7 @@ class HttpRedirectTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "redirectUrl" and - exists(HTTP::Redirect rd | + exists(Http::Redirect rd | rd.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and element = rd.getUrl().toString() and diff --git a/go/ql/test/experimental/frameworks/Fiber/ResponseBody.ql b/go/ql/test/experimental/frameworks/Fiber/ResponseBody.ql index 4361b2fda6a..74a9008749d 100644 --- a/go/ql/test/experimental/frameworks/Fiber/ResponseBody.ql +++ b/go/ql/test/experimental/frameworks/Fiber/ResponseBody.ql @@ -8,7 +8,7 @@ class HttpResponseBodyTest extends InlineExpectationsTest { override string getARelevantTag() { result = ["contentType", "responseBody"] } override predicate hasActualResult(Location location, string element, string tag, string value) { - exists(HTTP::ResponseBody rd | + exists(Http::ResponseBody rd | rd.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and ( diff --git a/go/ql/test/library-tests/semmle/go/concepts/HTTP/Handler.ql b/go/ql/test/library-tests/semmle/go/concepts/HTTP/Handler.ql index e0b0acd426b..c6972eba275 100644 --- a/go/ql/test/library-tests/semmle/go/concepts/HTTP/Handler.ql +++ b/go/ql/test/library-tests/semmle/go/concepts/HTTP/Handler.ql @@ -8,7 +8,7 @@ class HttpHandler extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "handler" and - exists(HTTP::RequestHandler h, DataFlow::Node check | + exists(Http::RequestHandler h, DataFlow::Node check | element = h.toString() and value = check.toString() | h.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), diff --git a/go/ql/test/library-tests/semmle/go/concepts/HTTP/Header.ql b/go/ql/test/library-tests/semmle/go/concepts/HTTP/Header.ql index e5449bf3e53..0ec82e5ad89 100644 --- a/go/ql/test/library-tests/semmle/go/concepts/HTTP/Header.ql +++ b/go/ql/test/library-tests/semmle/go/concepts/HTTP/Header.ql @@ -1,6 +1,6 @@ import go -from HTTP::HeaderWrite headerWrite, string name, string value, string definedName, string definedVal +from Http::HeaderWrite headerWrite, string name, string value, string definedName, string definedVal where ( name = headerWrite.getName().toString() diff --git a/go/ql/test/library-tests/semmle/go/concepts/HTTP/RequestBody.ql b/go/ql/test/library-tests/semmle/go/concepts/HTTP/RequestBody.ql index d49b7e95bb4..90d58b2db8d 100644 --- a/go/ql/test/library-tests/semmle/go/concepts/HTTP/RequestBody.ql +++ b/go/ql/test/library-tests/semmle/go/concepts/HTTP/RequestBody.ql @@ -1,4 +1,4 @@ import go -from HTTP::RequestBody rb +from Http::RequestBody rb select rb diff --git a/go/ql/test/library-tests/semmle/go/concepts/HTTP/ResponseBody.ql b/go/ql/test/library-tests/semmle/go/concepts/HTTP/ResponseBody.ql index d8d89b7f5bb..80394628bfc 100644 --- a/go/ql/test/library-tests/semmle/go/concepts/HTTP/ResponseBody.ql +++ b/go/ql/test/library-tests/semmle/go/concepts/HTTP/ResponseBody.ql @@ -1,4 +1,4 @@ import go -from HTTP::ResponseBody rb +from Http::ResponseBody rb select rb diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected b/go/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected index 14bf56d6cd2..6056f572d7c 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected @@ -36,37 +36,37 @@ nodes | test.go:180:16:180:23 | password | semmle.label | password | subpaths #select -| test.go:147:14:147:21 | password | test.go:147:14:147:21 | password | test.go:147:14:147:21 | password | Sensitive data returned by $@ is logged here. | test.go:147:14:147:21 | password | an access to password | -| test.go:148:17:148:24 | password | test.go:148:17:148:24 | password | test.go:148:17:148:24 | password | Sensitive data returned by $@ is logged here. | test.go:148:17:148:24 | password | an access to password | -| test.go:149:14:149:21 | password | test.go:149:14:149:21 | password | test.go:149:14:149:21 | password | Sensitive data returned by $@ is logged here. | test.go:149:14:149:21 | password | an access to password | -| test.go:150:18:150:25 | password | test.go:150:18:150:25 | password | test.go:150:18:150:25 | password | Sensitive data returned by $@ is logged here. | test.go:150:18:150:25 | password | an access to password | -| test.go:151:14:151:21 | password | test.go:151:14:151:21 | password | test.go:151:14:151:21 | password | Sensitive data returned by $@ is logged here. | test.go:151:14:151:21 | password | an access to password | -| test.go:152:13:152:20 | password | test.go:152:13:152:20 | password | test.go:152:13:152:20 | password | Sensitive data returned by $@ is logged here. | test.go:152:13:152:20 | password | an access to password | -| test.go:153:22:153:29 | password | test.go:153:22:153:29 | password | test.go:153:22:153:29 | password | Sensitive data returned by $@ is logged here. | test.go:153:22:153:29 | password | an access to password | -| test.go:154:15:154:22 | password | test.go:154:15:154:22 | password | test.go:154:15:154:22 | password | Sensitive data returned by $@ is logged here. | test.go:154:15:154:22 | password | an access to password | -| test.go:155:14:155:21 | password | test.go:155:14:155:21 | password | test.go:155:14:155:21 | password | Sensitive data returned by $@ is logged here. | test.go:155:14:155:21 | password | an access to password | -| test.go:156:13:156:20 | password | test.go:156:13:156:20 | password | test.go:156:13:156:20 | password | Sensitive data returned by $@ is logged here. | test.go:156:13:156:20 | password | an access to password | -| test.go:157:16:157:23 | password | test.go:157:16:157:23 | password | test.go:157:16:157:23 | password | Sensitive data returned by $@ is logged here. | test.go:157:16:157:23 | password | an access to password | -| test.go:158:13:158:20 | password | test.go:158:13:158:20 | password | test.go:158:13:158:20 | password | Sensitive data returned by $@ is logged here. | test.go:158:13:158:20 | password | an access to password | -| test.go:159:16:159:23 | password | test.go:159:16:159:23 | password | test.go:159:16:159:23 | password | Sensitive data returned by $@ is logged here. | test.go:159:16:159:23 | password | an access to password | -| test.go:160:13:160:20 | password | test.go:160:13:160:20 | password | test.go:160:13:160:20 | password | Sensitive data returned by $@ is logged here. | test.go:160:13:160:20 | password | an access to password | -| test.go:161:17:161:24 | password | test.go:161:17:161:24 | password | test.go:161:17:161:24 | password | Sensitive data returned by $@ is logged here. | test.go:161:17:161:24 | password | an access to password | -| test.go:162:13:162:20 | password | test.go:162:13:162:20 | password | test.go:162:13:162:20 | password | Sensitive data returned by $@ is logged here. | test.go:162:13:162:20 | password | an access to password | -| test.go:163:12:163:19 | password | test.go:163:12:163:19 | password | test.go:163:12:163:19 | password | Sensitive data returned by $@ is logged here. | test.go:163:12:163:19 | password | an access to password | -| test.go:164:21:164:28 | password | test.go:164:21:164:28 | password | test.go:164:21:164:28 | password | Sensitive data returned by $@ is logged here. | test.go:164:21:164:28 | password | an access to password | -| test.go:165:14:165:21 | password | test.go:165:14:165:21 | password | test.go:165:14:165:21 | password | Sensitive data returned by $@ is logged here. | test.go:165:14:165:21 | password | an access to password | -| test.go:166:13:166:20 | password | test.go:166:13:166:20 | password | test.go:166:13:166:20 | password | Sensitive data returned by $@ is logged here. | test.go:166:13:166:20 | password | an access to password | -| test.go:167:12:167:19 | password | test.go:167:12:167:19 | password | test.go:167:12:167:19 | password | Sensitive data returned by $@ is logged here. | test.go:167:12:167:19 | password | an access to password | -| test.go:168:15:168:22 | password | test.go:168:15:168:22 | password | test.go:168:15:168:22 | password | Sensitive data returned by $@ is logged here. | test.go:168:15:168:22 | password | an access to password | -| test.go:169:15:169:22 | password | test.go:169:15:169:22 | password | test.go:169:15:169:22 | password | Sensitive data returned by $@ is logged here. | test.go:169:15:169:22 | password | an access to password | -| test.go:170:18:170:25 | password | test.go:170:18:170:25 | password | test.go:170:18:170:25 | password | Sensitive data returned by $@ is logged here. | test.go:170:18:170:25 | password | an access to password | -| test.go:171:15:171:22 | password | test.go:171:15:171:22 | password | test.go:171:15:171:22 | password | Sensitive data returned by $@ is logged here. | test.go:171:15:171:22 | password | an access to password | -| test.go:172:19:172:26 | password | test.go:172:19:172:26 | password | test.go:172:19:172:26 | password | Sensitive data returned by $@ is logged here. | test.go:172:19:172:26 | password | an access to password | -| test.go:173:15:173:22 | password | test.go:173:15:173:22 | password | test.go:173:15:173:22 | password | Sensitive data returned by $@ is logged here. | test.go:173:15:173:22 | password | an access to password | -| test.go:174:14:174:21 | password | test.go:174:14:174:21 | password | test.go:174:14:174:21 | password | Sensitive data returned by $@ is logged here. | test.go:174:14:174:21 | password | an access to password | -| test.go:175:23:175:30 | password | test.go:175:23:175:30 | password | test.go:175:23:175:30 | password | Sensitive data returned by $@ is logged here. | test.go:175:23:175:30 | password | an access to password | -| test.go:176:16:176:23 | password | test.go:176:16:176:23 | password | test.go:176:16:176:23 | password | Sensitive data returned by $@ is logged here. | test.go:176:16:176:23 | password | an access to password | -| test.go:177:15:177:22 | password | test.go:177:15:177:22 | password | test.go:177:15:177:22 | password | Sensitive data returned by $@ is logged here. | test.go:177:15:177:22 | password | an access to password | -| test.go:178:14:178:21 | password | test.go:178:14:178:21 | password | test.go:178:14:178:21 | password | Sensitive data returned by $@ is logged here. | test.go:178:14:178:21 | password | an access to password | -| test.go:179:17:179:24 | password | test.go:179:17:179:24 | password | test.go:179:17:179:24 | password | Sensitive data returned by $@ is logged here. | test.go:179:17:179:24 | password | an access to password | -| test.go:180:16:180:23 | password | test.go:180:16:180:23 | password | test.go:180:16:180:23 | password | Sensitive data returned by $@ is logged here. | test.go:180:16:180:23 | password | an access to password | +| test.go:147:14:147:21 | password | test.go:147:14:147:21 | password | test.go:147:14:147:21 | password | $@ flows to a logging call. | test.go:147:14:147:21 | password | Sensitive data returned by an access to password | +| test.go:148:17:148:24 | password | test.go:148:17:148:24 | password | test.go:148:17:148:24 | password | $@ flows to a logging call. | test.go:148:17:148:24 | password | Sensitive data returned by an access to password | +| test.go:149:14:149:21 | password | test.go:149:14:149:21 | password | test.go:149:14:149:21 | password | $@ flows to a logging call. | test.go:149:14:149:21 | password | Sensitive data returned by an access to password | +| test.go:150:18:150:25 | password | test.go:150:18:150:25 | password | test.go:150:18:150:25 | password | $@ flows to a logging call. | test.go:150:18:150:25 | password | Sensitive data returned by an access to password | +| test.go:151:14:151:21 | password | test.go:151:14:151:21 | password | test.go:151:14:151:21 | password | $@ flows to a logging call. | test.go:151:14:151:21 | password | Sensitive data returned by an access to password | +| test.go:152:13:152:20 | password | test.go:152:13:152:20 | password | test.go:152:13:152:20 | password | $@ flows to a logging call. | test.go:152:13:152:20 | password | Sensitive data returned by an access to password | +| test.go:153:22:153:29 | password | test.go:153:22:153:29 | password | test.go:153:22:153:29 | password | $@ flows to a logging call. | test.go:153:22:153:29 | password | Sensitive data returned by an access to password | +| test.go:154:15:154:22 | password | test.go:154:15:154:22 | password | test.go:154:15:154:22 | password | $@ flows to a logging call. | test.go:154:15:154:22 | password | Sensitive data returned by an access to password | +| test.go:155:14:155:21 | password | test.go:155:14:155:21 | password | test.go:155:14:155:21 | password | $@ flows to a logging call. | test.go:155:14:155:21 | password | Sensitive data returned by an access to password | +| test.go:156:13:156:20 | password | test.go:156:13:156:20 | password | test.go:156:13:156:20 | password | $@ flows to a logging call. | test.go:156:13:156:20 | password | Sensitive data returned by an access to password | +| test.go:157:16:157:23 | password | test.go:157:16:157:23 | password | test.go:157:16:157:23 | password | $@ flows to a logging call. | test.go:157:16:157:23 | password | Sensitive data returned by an access to password | +| test.go:158:13:158:20 | password | test.go:158:13:158:20 | password | test.go:158:13:158:20 | password | $@ flows to a logging call. | test.go:158:13:158:20 | password | Sensitive data returned by an access to password | +| test.go:159:16:159:23 | password | test.go:159:16:159:23 | password | test.go:159:16:159:23 | password | $@ flows to a logging call. | test.go:159:16:159:23 | password | Sensitive data returned by an access to password | +| test.go:160:13:160:20 | password | test.go:160:13:160:20 | password | test.go:160:13:160:20 | password | $@ flows to a logging call. | test.go:160:13:160:20 | password | Sensitive data returned by an access to password | +| test.go:161:17:161:24 | password | test.go:161:17:161:24 | password | test.go:161:17:161:24 | password | $@ flows to a logging call. | test.go:161:17:161:24 | password | Sensitive data returned by an access to password | +| test.go:162:13:162:20 | password | test.go:162:13:162:20 | password | test.go:162:13:162:20 | password | $@ flows to a logging call. | test.go:162:13:162:20 | password | Sensitive data returned by an access to password | +| test.go:163:12:163:19 | password | test.go:163:12:163:19 | password | test.go:163:12:163:19 | password | $@ flows to a logging call. | test.go:163:12:163:19 | password | Sensitive data returned by an access to password | +| test.go:164:21:164:28 | password | test.go:164:21:164:28 | password | test.go:164:21:164:28 | password | $@ flows to a logging call. | test.go:164:21:164:28 | password | Sensitive data returned by an access to password | +| test.go:165:14:165:21 | password | test.go:165:14:165:21 | password | test.go:165:14:165:21 | password | $@ flows to a logging call. | test.go:165:14:165:21 | password | Sensitive data returned by an access to password | +| test.go:166:13:166:20 | password | test.go:166:13:166:20 | password | test.go:166:13:166:20 | password | $@ flows to a logging call. | test.go:166:13:166:20 | password | Sensitive data returned by an access to password | +| test.go:167:12:167:19 | password | test.go:167:12:167:19 | password | test.go:167:12:167:19 | password | $@ flows to a logging call. | test.go:167:12:167:19 | password | Sensitive data returned by an access to password | +| test.go:168:15:168:22 | password | test.go:168:15:168:22 | password | test.go:168:15:168:22 | password | $@ flows to a logging call. | test.go:168:15:168:22 | password | Sensitive data returned by an access to password | +| test.go:169:15:169:22 | password | test.go:169:15:169:22 | password | test.go:169:15:169:22 | password | $@ flows to a logging call. | test.go:169:15:169:22 | password | Sensitive data returned by an access to password | +| test.go:170:18:170:25 | password | test.go:170:18:170:25 | password | test.go:170:18:170:25 | password | $@ flows to a logging call. | test.go:170:18:170:25 | password | Sensitive data returned by an access to password | +| test.go:171:15:171:22 | password | test.go:171:15:171:22 | password | test.go:171:15:171:22 | password | $@ flows to a logging call. | test.go:171:15:171:22 | password | Sensitive data returned by an access to password | +| test.go:172:19:172:26 | password | test.go:172:19:172:26 | password | test.go:172:19:172:26 | password | $@ flows to a logging call. | test.go:172:19:172:26 | password | Sensitive data returned by an access to password | +| test.go:173:15:173:22 | password | test.go:173:15:173:22 | password | test.go:173:15:173:22 | password | $@ flows to a logging call. | test.go:173:15:173:22 | password | Sensitive data returned by an access to password | +| test.go:174:14:174:21 | password | test.go:174:14:174:21 | password | test.go:174:14:174:21 | password | $@ flows to a logging call. | test.go:174:14:174:21 | password | Sensitive data returned by an access to password | +| test.go:175:23:175:30 | password | test.go:175:23:175:30 | password | test.go:175:23:175:30 | password | $@ flows to a logging call. | test.go:175:23:175:30 | password | Sensitive data returned by an access to password | +| test.go:176:16:176:23 | password | test.go:176:16:176:23 | password | test.go:176:16:176:23 | password | $@ flows to a logging call. | test.go:176:16:176:23 | password | Sensitive data returned by an access to password | +| test.go:177:15:177:22 | password | test.go:177:15:177:22 | password | test.go:177:15:177:22 | password | $@ flows to a logging call. | test.go:177:15:177:22 | password | Sensitive data returned by an access to password | +| test.go:178:14:178:21 | password | test.go:178:14:178:21 | password | test.go:178:14:178:21 | password | $@ flows to a logging call. | test.go:178:14:178:21 | password | Sensitive data returned by an access to password | +| test.go:179:17:179:24 | password | test.go:179:17:179:24 | password | test.go:179:17:179:24 | password | $@ flows to a logging call. | test.go:179:17:179:24 | password | Sensitive data returned by an access to password | +| test.go:180:16:180:23 | password | test.go:180:16:180:23 | password | test.go:180:16:180:23 | password | $@ flows to a logging call. | test.go:180:16:180:23 | password | Sensitive data returned by an access to password | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Beego/OpenRedirect.expected index 9d172f94403..ff1902aa72a 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/OpenRedirect.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/OpenRedirect.expected @@ -8,5 +8,5 @@ nodes | test.go:311:20:311:34 | call to URL | semmle.label | call to URL | subpaths #select -| test.go:246:13:246:34 | call to GetString | test.go:246:13:246:34 | call to GetString | test.go:246:13:246:34 | call to GetString | Untrusted URL redirection due to $@. | test.go:246:13:246:34 | call to GetString | user-provided value | -| test.go:247:20:247:41 | call to GetString | test.go:247:20:247:41 | call to GetString | test.go:247:20:247:41 | call to GetString | Untrusted URL redirection due to $@. | test.go:247:20:247:41 | call to GetString | user-provided value | +| test.go:246:13:246:34 | call to GetString | test.go:246:13:246:34 | call to GetString | test.go:246:13:246:34 | call to GetString | Untrusted URL redirection depends on a $@. | test.go:246:13:246:34 | call to GetString | user-provided value | +| test.go:247:20:247:41 | call to GetString | test.go:247:20:247:41 | call to GetString | test.go:247:20:247:41 | call to GetString | Untrusted URL redirection depends on a $@. | test.go:247:20:247:41 | call to GetString | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/TaintedPath.expected b/go/ql/test/library-tests/semmle/go/frameworks/Beego/TaintedPath.expected index 1ebdc8c4797..76fec9f68d4 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/TaintedPath.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/TaintedPath.expected @@ -9,6 +9,6 @@ nodes | test.go:211:35:211:43 | untrusted | semmle.label | untrusted | subpaths #select -| test.go:209:18:209:26 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:209:18:209:26 | untrusted | $@ flows to here and is used in a path. | test.go:208:15:208:26 | call to Data | User-provided value | -| test.go:210:10:210:18 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:210:10:210:18 | untrusted | $@ flows to here and is used in a path. | test.go:208:15:208:26 | call to Data | User-provided value | -| test.go:211:35:211:43 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:211:35:211:43 | untrusted | $@ flows to here and is used in a path. | test.go:208:15:208:26 | call to Data | User-provided value | +| test.go:209:18:209:26 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:209:18:209:26 | untrusted | This path depends on a $@. | test.go:208:15:208:26 | call to Data | user-provided value | +| test.go:210:10:210:18 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:210:10:210:18 | untrusted | This path depends on a $@. | test.go:208:15:208:26 | call to Data | user-provided value | +| test.go:211:35:211:43 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:211:35:211:43 | untrusted | This path depends on a $@. | test.go:208:15:208:26 | call to Data | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected index 1b3b1fa3533..873eed34f41 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected @@ -71,35 +71,35 @@ nodes | test.go:62:19:62:27 | untrusted | semmle.label | untrusted | subpaths #select -| test.go:12:11:12:19 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:12:11:12:19 | untrusted | This query depends on $@. | test.go:10:15:10:41 | call to UserAgent | a user-provided value | -| test.go:13:23:13:31 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:13:23:13:31 | untrusted | This query depends on $@. | test.go:10:15:10:41 | call to UserAgent | a user-provided value | -| test.go:14:14:14:22 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:14:14:14:22 | untrusted | This query depends on $@. | test.go:10:15:10:41 | call to UserAgent | a user-provided value | -| test.go:15:26:15:34 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:15:26:15:34 | untrusted | This query depends on $@. | test.go:10:15:10:41 | call to UserAgent | a user-provided value | -| test.go:16:12:16:20 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:16:12:16:20 | untrusted | This query depends on $@. | test.go:10:15:10:41 | call to UserAgent | a user-provided value | -| test.go:17:24:17:32 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:17:24:17:32 | untrusted | This query depends on $@. | test.go:10:15:10:41 | call to UserAgent | a user-provided value | -| test.go:18:15:18:23 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:18:15:18:23 | untrusted | This query depends on $@. | test.go:10:15:10:41 | call to UserAgent | a user-provided value | -| test.go:19:27:19:35 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:19:27:19:35 | untrusted | This query depends on $@. | test.go:10:15:10:41 | call to UserAgent | a user-provided value | -| test.go:26:12:26:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:26:12:26:20 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:27:10:27:18 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:27:10:27:18 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:28:15:28:23 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:28:15:28:23 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:29:14:29:22 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:29:14:29:22 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:30:15:30:23 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:30:15:30:23 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:31:8:31:16 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:31:8:31:16 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:32:11:32:19 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:32:11:32:19 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:33:9:33:17 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:33:9:33:17 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:34:8:34:16 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:34:8:34:16 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:35:8:35:16 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:35:8:35:16 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:36:13:36:21 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:36:13:36:21 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:37:13:37:21 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:37:13:37:21 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:38:12:38:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:38:12:38:20 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:39:12:39:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:39:12:39:20 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:40:9:40:17 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:40:9:40:17 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:41:12:41:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:41:12:41:20 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:42:16:42:24 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:42:16:42:24 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:42:27:42:35 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:42:27:42:35 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:43:12:43:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:43:12:43:20 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:44:14:44:22 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:44:14:44:22 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:44:25:44:33 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:44:25:44:33 | untrusted | This query depends on $@. | test.go:24:15:24:41 | call to UserAgent | a user-provided value | -| test.go:49:12:49:20 | untrusted | test.go:48:15:48:41 | call to UserAgent : string | test.go:49:12:49:20 | untrusted | This query depends on $@. | test.go:48:15:48:41 | call to UserAgent | a user-provided value | -| test.go:56:31:56:39 | untrusted | test.go:54:15:54:41 | call to UserAgent : string | test.go:56:31:56:39 | untrusted | This query depends on $@. | test.go:54:15:54:41 | call to UserAgent | a user-provided value | -| test.go:62:19:62:27 | untrusted | test.go:60:15:60:41 | call to UserAgent : string | test.go:62:19:62:27 | untrusted | This query depends on $@. | test.go:60:15:60:41 | call to UserAgent | a user-provided value | +| test.go:12:11:12:19 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:12:11:12:19 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:13:23:13:31 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:13:23:13:31 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:14:14:14:22 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:14:14:14:22 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:15:26:15:34 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:15:26:15:34 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:16:12:16:20 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:16:12:16:20 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:17:24:17:32 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:17:24:17:32 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:18:15:18:23 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:18:15:18:23 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:19:27:19:35 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:19:27:19:35 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:26:12:26:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:26:12:26:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:27:10:27:18 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:27:10:27:18 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:28:15:28:23 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:28:15:28:23 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:29:14:29:22 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:29:14:29:22 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:30:15:30:23 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:30:15:30:23 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:31:8:31:16 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:31:8:31:16 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:32:11:32:19 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:32:11:32:19 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:33:9:33:17 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:33:9:33:17 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:34:8:34:16 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:34:8:34:16 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:35:8:35:16 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:35:8:35:16 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:36:13:36:21 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:36:13:36:21 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:37:13:37:21 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:37:13:37:21 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:38:12:38:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:38:12:38:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:39:12:39:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:39:12:39:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:40:9:40:17 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:40:9:40:17 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:41:12:41:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:41:12:41:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:42:16:42:24 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:42:16:42:24 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:42:27:42:35 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:42:27:42:35 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:43:12:43:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:43:12:43:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:44:14:44:22 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:44:14:44:22 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:44:25:44:33 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:44:25:44:33 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:49:12:49:20 | untrusted | test.go:48:15:48:41 | call to UserAgent : string | test.go:49:12:49:20 | untrusted | This query depends on a $@. | test.go:48:15:48:41 | call to UserAgent | user-provided value | +| test.go:56:31:56:39 | untrusted | test.go:54:15:54:41 | call to UserAgent : string | test.go:56:31:56:39 | untrusted | This query depends on a $@. | test.go:54:15:54:41 | call to UserAgent | user-provided value | +| test.go:62:19:62:27 | untrusted | test.go:60:15:60:41 | call to UserAgent : string | test.go:62:19:62:27 | untrusted | This query depends on a $@. | test.go:60:15:60:41 | call to UserAgent | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected index 9dba5209887..e29c066c9b5 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected @@ -16,5 +16,5 @@ nodes | test.go:191:21:191:32 | call to String | semmle.label | call to String | subpaths #select -| test.go:171:20:171:24 | param | test.go:170:11:170:32 | call to Param : string | test.go:171:20:171:24 | param | Untrusted URL redirection due to $@. | test.go:170:11:170:32 | call to Param | user-provided value | -| test.go:180:20:180:28 | ...+... | test.go:176:11:176:32 | call to Param : string | test.go:180:20:180:28 | ...+... | Untrusted URL redirection due to $@. | test.go:176:11:176:32 | call to Param | user-provided value | +| test.go:171:20:171:24 | param | test.go:170:11:170:32 | call to Param : string | test.go:171:20:171:24 | param | Untrusted URL redirection depends on a $@. | test.go:170:11:170:32 | call to Param | user-provided value | +| test.go:180:20:180:28 | ...+... | test.go:176:11:176:32 | call to Param : string | test.go:180:20:180:28 | ...+... | Untrusted URL redirection depends on a $@. | test.go:176:11:176:32 | call to Param | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/ElazarlGoproxy/test.ql b/go/ql/test/library-tests/semmle/go/frameworks/ElazarlGoproxy/test.ql index 106d28b48f5..0b07a0a20f0 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/ElazarlGoproxy/test.ql +++ b/go/ql/test/library-tests/semmle/go/frameworks/ElazarlGoproxy/test.ql @@ -23,7 +23,7 @@ class HeaderWriteTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "headerwrite" and - exists(HTTP::HeaderWrite hw, string name, string val | element = hw.toString() | + exists(Http::HeaderWrite hw, string name, string val | element = hw.toString() | hw.definesHeader(name, val) and value = name + ":" + val and hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Macaron/Redirect.ql b/go/ql/test/library-tests/semmle/go/frameworks/Macaron/Redirect.ql index 813ad53f2e0..c73e0dac04c 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Macaron/Redirect.ql +++ b/go/ql/test/library-tests/semmle/go/frameworks/Macaron/Redirect.ql @@ -1,4 +1,4 @@ import go -from HTTP::Redirect redir +from Http::Redirect redir select redir, redir.getResponseWriter() diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected index e31719c2b6c..a1e94fbd058 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected @@ -11,4 +11,4 @@ nodes | EndToEnd.go:94:20:94:49 | call to Get | semmle.label | call to Get | subpaths #select -| EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params : pointer type | EndToEnd.go:94:20:94:49 | call to Get | Untrusted URL redirection due to $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value | +| EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params : pointer type | EndToEnd.go:94:20:94:49 | call to Get | Untrusted URL redirection depends on a $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected index 13ae22543a4..7f1596dbbf8 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected @@ -49,6 +49,6 @@ subpaths #select | EndToEnd.go:37:24:37:26 | buf | EndToEnd.go:36:18:36:25 | selection of Params : pointer type | EndToEnd.go:37:24:37:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:36:18:36:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | | EndToEnd.go:69:22:69:51 | call to Get | EndToEnd.go:69:22:69:29 | selection of Params : pointer type | EndToEnd.go:69:22:69:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:69:22:69:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | -| Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params : pointer type | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. This template argument is instantiated raw $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | here | +| Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params : pointer type | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. The value is $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | instantiated as a raw template | | examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | | examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected index 1a066ff92d4..fc24c4a73ca 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected @@ -20,5 +20,5 @@ nodes | EndToEnd.go:64:26:64:55 | call to Get | semmle.label | call to Get | subpaths #select -| EndToEnd.go:58:18:58:47 | call to Get | EndToEnd.go:58:18:58:25 | selection of Params : pointer type | EndToEnd.go:58:18:58:47 | call to Get | $@ flows to here and is used in a path. | EndToEnd.go:58:18:58:25 | selection of Params | User-provided value | -| EndToEnd.go:64:26:64:55 | call to Get | EndToEnd.go:64:26:64:33 | selection of Params : pointer type | EndToEnd.go:64:26:64:55 | call to Get | $@ flows to here and is used in a path. | EndToEnd.go:64:26:64:33 | selection of Params | User-provided value | +| EndToEnd.go:58:18:58:47 | call to Get | EndToEnd.go:58:18:58:25 | selection of Params : pointer type | EndToEnd.go:58:18:58:47 | call to Get | This path depends on a $@. | EndToEnd.go:58:18:58:25 | selection of Params | user-provided value | +| EndToEnd.go:64:26:64:55 | call to Get | EndToEnd.go:64:26:64:33 | selection of Params : pointer type | EndToEnd.go:64:26:64:55 | call to Get | This path depends on a $@. | EndToEnd.go:64:26:64:33 | selection of Params | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/test.ql b/go/ql/test/library-tests/semmle/go/frameworks/Revel/test.ql index e3d2cd16be4..9d2b876d803 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/test.ql +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/test.ql @@ -39,7 +39,7 @@ class HttpResponseBodyTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "responsebody" and - exists(HTTP::ResponseBody rb | + exists(Http::ResponseBody rb | rb.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and element = rb.toString() and diff --git a/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.expected b/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.expected index 06dbbbf4a52..b3e042e30ce 100644 --- a/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.expected +++ b/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.expected @@ -1 +1 @@ -| ConstantLengthComparison.go:5:6:5:17 | ...==... | This checks the length against a constant, but it is indexed using a variable $@. | ConstantLengthComparison.go:5:31:5:35 | index expression | here | +| ConstantLengthComparison.go:5:6:5:17 | ...==... | This checks the length against a constant, but it $@. | ConstantLengthComparison.go:5:31:5:35 | index expression | is indexed using a variable | diff --git a/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/MissingErrorCheck.expected b/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/MissingErrorCheck.expected index ec1545a4a16..b4bd7b815d5 100644 --- a/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/MissingErrorCheck.expected +++ b/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/MissingErrorCheck.expected @@ -1,2 +1,2 @@ -| tests.go:61:30:61:35 | result | result may be nil here, because $@ may not have been checked. | tests.go:59:10:59:12 | definition of err | err | -| tests.go:243:27:243:32 | result | result may be nil here, because $@ may not have been checked. | tests.go:241:10:241:12 | definition of err | err | +| tests.go:61:30:61:35 | result | $@ may be nil at this dereference because $@ may not have been checked. | tests.go:59:2:59:7 | definition of result | result | tests.go:59:10:59:12 | definition of err | err | +| tests.go:243:27:243:32 | result | $@ may be nil at this dereference because $@ may not have been checked. | tests.go:241:2:241:7 | definition of result | result | tests.go:241:10:241:12 | definition of err | err | diff --git a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.expected b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.expected index d116669ad77..80ecc4ff1cc 100644 --- a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.expected +++ b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.expected @@ -1,4 +1,4 @@ -| CompareIdenticalValues.go:9:3:9:8 | ...<=... | This expression compares $@ to itself. | CompareIdenticalValues.go:9:3:9:3 | y | an expression | -| tst.go:6:9:6:14 | ...==... | This expression compares $@ to itself. | tst.go:6:9:6:9 | x | an expression | -| tst.go:60:9:60:14 | ...==... | This expression compares $@ to itself. | tst.go:60:9:60:9 | y | an expression | -| vp.go:16:9:16:38 | ...!=... | This expression compares $@ to itself. | vp.go:16:9:16:21 | call to GetLength | an expression | +| CompareIdenticalValues.go:9:3:9:8 | ...<=... | This expression compares an $@ to itself. | CompareIdenticalValues.go:9:3:9:3 | y | expression | +| tst.go:6:9:6:14 | ...==... | This expression compares an $@ to itself. | tst.go:6:9:6:9 | x | expression | +| tst.go:60:9:60:14 | ...==... | This expression compares an $@ to itself. | tst.go:60:9:60:9 | y | expression | +| vp.go:16:9:16:38 | ...!=... | This expression compares an $@ to itself. | vp.go:16:9:16:21 | call to GetLength | expression | diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.expected b/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.expected index c01d55f05b7..2f09d045ba5 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.expected +++ b/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.expected @@ -1,2 +1,2 @@ -| DuplicateCondition.go:6:12:6:25 | ...==... | This condition is a duplicate of $@. | DuplicateCondition.go:4:5:4:18 | ...==... | an earlier condition | -| tst.go:9:12:9:13 | ok | This condition is a duplicate of $@. | tst.go:8:22:8:23 | ok | an earlier condition | +| DuplicateCondition.go:6:12:6:25 | ...==... | This condition is a duplicate of an $@. | DuplicateCondition.go:4:5:4:18 | ...==... | earlier condition | +| tst.go:9:12:9:13 | ok | This condition is a duplicate of an $@. | tst.go:8:22:8:23 | ok | earlier condition | diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.expected b/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.expected index 936ff519def..279afc30c31 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.expected +++ b/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.expected @@ -1,2 +1,2 @@ -| DuplicateSwitchCase.go:7:7:7:20 | ...==... | This case is a duplicate of $@. | DuplicateSwitchCase.go:5:7:5:20 | ...==... | an earlier case | -| tst.go:9:7:9:12 | ...<... | This case is a duplicate of $@. | tst.go:5:7:5:12 | ...<... | an earlier case | +| DuplicateSwitchCase.go:7:7:7:20 | ...==... | This case is a duplicate of an $@. | DuplicateSwitchCase.go:5:7:5:20 | ...==... | earlier case | +| tst.go:9:7:9:12 | ...<... | This case is a duplicate of an $@. | tst.go:5:7:5:12 | ...<... | earlier case | diff --git a/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.expected b/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.expected index 993110b2d5f..283c62816d1 100644 --- a/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.expected +++ b/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.expected @@ -1,2 +1,2 @@ -| SelfAssignment.go:12:2:12:16 | ... = ... | This statement assigns $@ to itself. | SelfAssignment.go:12:11:12:16 | height | an expression | -| tst.go:5:2:5:6 | ... = ... | This statement assigns $@ to itself. | tst.go:5:6:5:6 | x | an expression | +| SelfAssignment.go:12:2:12:16 | ... = ... | This statement assigns an $@ to itself. | SelfAssignment.go:12:11:12:16 | height | expression | +| tst.go:5:2:5:6 | ... = ... | This statement assigns an $@ to itself. | tst.go:5:6:5:6 | x | expression | diff --git a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.expected b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.expected index af16db3e0d5..f73dd03f976 100644 --- a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.expected +++ b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.expected @@ -7,6 +7,6 @@ nodes | main.go:44:15:44:39 | `https://www.example.com` | semmle.label | `https://www.example.com` | subpaths #select -| IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" : string | IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" : string | IncompleteHostnameRegexp.go:12:38:12:39 | re | This regular expression has an unescaped dot before ')?example.com', so it might match more hosts than expected when used $@. | IncompleteHostnameRegexp.go:12:38:12:39 | re | here | -| main.go:39:60:39:79 | "^test2.github.com$" | main.go:39:60:39:79 | "^test2.github.com$" | main.go:39:60:39:79 | "^test2.github.com$" | This regular expression has an unescaped dot before 'github.com', so it might match more hosts than expected when used $@. | main.go:39:60:39:79 | "^test2.github.com$" | here | -| main.go:44:15:44:39 | `https://www.example.com` | main.go:44:15:44:39 | `https://www.example.com` | main.go:44:15:44:39 | `https://www.example.com` | This regular expression has an unescaped dot before 'example.com', so it might match more hosts than expected when used $@. | main.go:44:15:44:39 | `https://www.example.com` | here | +| IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" : string | IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" : string | IncompleteHostnameRegexp.go:12:38:12:39 | re | This regular expression has an unescaped dot before ')?example.com', so it might match more hosts than expected when $@. | IncompleteHostnameRegexp.go:12:38:12:39 | re | the regular expression is used | +| main.go:39:60:39:79 | "^test2.github.com$" | main.go:39:60:39:79 | "^test2.github.com$" | main.go:39:60:39:79 | "^test2.github.com$" | This regular expression has an unescaped dot before 'github.com', so it might match more hosts than expected when $@. | main.go:39:60:39:79 | "^test2.github.com$" | the regular expression is used | +| main.go:44:15:44:39 | `https://www.example.com` | main.go:44:15:44:39 | `https://www.example.com` | main.go:44:15:44:39 | `https://www.example.com` | This regular expression has an unescaped dot before 'example.com', so it might match more hosts than expected when $@. | main.go:44:15:44:39 | `https://www.example.com` | the regular expression is used | diff --git a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected index 933e3be3fa3..130894d0639 100644 --- a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected +++ b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected @@ -13,14 +13,14 @@ nodes | test.go:23:21:23:36 | "hello\\\\\\bworld" | semmle.label | "hello\\\\\\bworld" | subpaths #select -| SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | $@ used $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | A regular expression | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | here | -| test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:7:21:7:24 | "\\a" | A regular expression | test.go:7:21:7:24 | "\\a" | here | -| test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:9:21:9:26 | "\\\\\\a" | A regular expression | test.go:9:21:9:26 | "\\\\\\a" | here | -| test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:10:21:10:27 | "x\\\\\\a" | A regular expression | test.go:10:21:10:27 | "x\\\\\\a" | here | -| test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:12:21:12:28 | "\\\\\\\\\\a" | A regular expression | test.go:12:21:12:28 | "\\\\\\\\\\a" | here | -| test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | A regular expression | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | here | -| test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | A regular expression | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | here | -| test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:20:21:20:34 | "hello\\aworld" | A regular expression | test.go:20:21:20:34 | "hello\\aworld" | here | -| test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:21:21:21:36 | "hello\\\\\\aworld" | A regular expression | test.go:21:21:21:36 | "hello\\\\\\aworld" | here | -| test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | $@ used $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:22:21:22:34 | "hello\\bworld" | A regular expression | test.go:22:21:22:34 | "hello\\bworld" | here | -| test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | $@ used $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:23:21:23:36 | "hello\\\\\\bworld" | A regular expression | test.go:23:21:23:36 | "hello\\\\\\bworld" | here | +| SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | $@ that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | A string literal | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | used as a regular expression | +| test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:7:21:7:24 | "\\a" | A string literal | test.go:7:21:7:24 | "\\a" | used as a regular expression | +| test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:9:21:9:26 | "\\\\\\a" | A string literal | test.go:9:21:9:26 | "\\\\\\a" | used as a regular expression | +| test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:10:21:10:27 | "x\\\\\\a" | A string literal | test.go:10:21:10:27 | "x\\\\\\a" | used as a regular expression | +| test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:12:21:12:28 | "\\\\\\\\\\a" | A string literal | test.go:12:21:12:28 | "\\\\\\\\\\a" | used as a regular expression | +| test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | A string literal | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | used as a regular expression | +| test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | A string literal | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | used as a regular expression | +| test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:20:21:20:34 | "hello\\aworld" | A string literal | test.go:20:21:20:34 | "hello\\aworld" | used as a regular expression | +| test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:21:21:21:36 | "hello\\\\\\aworld" | A string literal | test.go:21:21:21:36 | "hello\\\\\\aworld" | used as a regular expression | +| test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | $@ that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:22:21:22:34 | "hello\\bworld" | A string literal | test.go:22:21:22:34 | "hello\\bworld" | used as a regular expression | +| test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | $@ that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:23:21:23:36 | "hello\\\\\\bworld" | A string literal | test.go:23:21:23:36 | "hello\\\\\\bworld" | used as a regular expression | diff --git a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.expected b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.expected index 8bd09ca706f..acbcbcdeb31 100644 --- a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.expected +++ b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.expected @@ -14,6 +14,6 @@ nodes | tst.go:17:41:17:56 | selection of Filename | semmle.label | selection of Filename | subpaths #select -| TaintedPath.go:16:29:16:40 | tainted_path | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:16:29:16:40 | tainted_path | $@ flows to here and is used in a path. | TaintedPath.go:13:18:13:22 | selection of URL | User-provided value | -| TaintedPath.go:20:28:20:69 | call to Join | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:20:28:20:69 | call to Join | $@ flows to here and is used in a path. | TaintedPath.go:13:18:13:22 | selection of URL | User-provided value | -| tst.go:17:41:17:56 | selection of Filename | tst.go:14:2:14:39 | ... := ...[1] : pointer type | tst.go:17:41:17:56 | selection of Filename | $@ flows to here and is used in a path. | tst.go:14:2:14:39 | ... := ...[1] | User-provided value | +| TaintedPath.go:16:29:16:40 | tainted_path | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:16:29:16:40 | tainted_path | This path depends on a $@. | TaintedPath.go:13:18:13:22 | selection of URL | user-provided value | +| TaintedPath.go:20:28:20:69 | call to Join | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:20:28:20:69 | call to Join | This path depends on a $@. | TaintedPath.go:13:18:13:22 | selection of URL | user-provided value | +| tst.go:17:41:17:56 | selection of Filename | tst.go:14:2:14:39 | ... := ...[1] : pointer type | tst.go:17:41:17:56 | selection of Filename | This path depends on a $@. | tst.go:14:2:14:39 | ... := ...[1] | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 6262aa06127..02c56107106 100644 --- a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -55,25 +55,25 @@ nodes | SanitizingDoubleDash.go:152:24:152:30 | tainted | semmle.label | tainted | subpaths #select -| CommandInjection.go:10:22:10:28 | cmdName | CommandInjection.go:9:13:9:19 | selection of URL : pointer type | CommandInjection.go:10:22:10:28 | cmdName | This command depends on $@. | CommandInjection.go:9:13:9:19 | selection of URL | a user-provided value | -| GitSubcommands.go:12:31:12:37 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:12:31:12:37 | tainted | This command depends on $@. | GitSubcommands.go:10:13:10:19 | selection of URL | a user-provided value | -| GitSubcommands.go:13:31:13:37 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:13:31:13:37 | tainted | This command depends on $@. | GitSubcommands.go:10:13:10:19 | selection of URL | a user-provided value | -| GitSubcommands.go:14:30:14:36 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:14:30:14:36 | tainted | This command depends on $@. | GitSubcommands.go:10:13:10:19 | selection of URL | a user-provided value | -| GitSubcommands.go:15:35:15:41 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:15:35:15:41 | tainted | This command depends on $@. | GitSubcommands.go:10:13:10:19 | selection of URL | a user-provided value | -| GitSubcommands.go:16:36:16:42 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:16:36:16:42 | tainted | This command depends on $@. | GitSubcommands.go:10:13:10:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:14:23:14:33 | slice expression | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:14:23:14:33 | slice expression | This command depends on $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:40:23:40:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:40:23:40:30 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:54:23:54:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:54:23:54:30 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:70:23:70:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:70:23:70:30 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:80:23:80:29 | tainted | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:80:23:80:29 | tainted | This command depends on $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:96:24:96:34 | slice expression | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:96:24:96:34 | slice expression | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:101:24:101:34 | slice expression | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:101:24:101:34 | slice expression | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:106:24:106:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:106:24:106:31 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:112:24:112:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:112:24:112:31 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:118:24:118:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:118:24:118:31 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:124:24:124:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:124:24:124:31 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:130:24:130:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:130:24:130:31 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:137:24:137:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:137:24:137:31 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:144:24:144:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:144:24:144:31 | arrayLit | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:148:30:148:36 | tainted | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:148:30:148:36 | tainted | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | -| SanitizingDoubleDash.go:152:24:152:30 | tainted | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:152:24:152:30 | tainted | This command depends on $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | a user-provided value | +| CommandInjection.go:10:22:10:28 | cmdName | CommandInjection.go:9:13:9:19 | selection of URL : pointer type | CommandInjection.go:10:22:10:28 | cmdName | This command depends on a $@. | CommandInjection.go:9:13:9:19 | selection of URL | user-provided value | +| GitSubcommands.go:12:31:12:37 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:12:31:12:37 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| GitSubcommands.go:13:31:13:37 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:13:31:13:37 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| GitSubcommands.go:14:30:14:36 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:14:30:14:36 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| GitSubcommands.go:15:35:15:41 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:15:35:15:41 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| GitSubcommands.go:16:36:16:42 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:16:36:16:42 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:14:23:14:33 | slice expression | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:14:23:14:33 | slice expression | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:40:23:40:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:40:23:40:30 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:54:23:54:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:54:23:54:30 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:70:23:70:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:70:23:70:30 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:80:23:80:29 | tainted | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:80:23:80:29 | tainted | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:96:24:96:34 | slice expression | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:96:24:96:34 | slice expression | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:101:24:101:34 | slice expression | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:101:24:101:34 | slice expression | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:106:24:106:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:106:24:106:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:112:24:112:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:112:24:112:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:118:24:118:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:118:24:118:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:124:24:124:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:124:24:124:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:130:24:130:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:130:24:130:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:137:24:137:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:137:24:137:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:144:24:144:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:144:24:144:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:148:30:148:36 | tainted | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:148:30:148:36 | tainted | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:152:24:152:30 | tainted | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:152:24:152:30 | tainted | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-078/StoredCommand.expected b/go/ql/test/query-tests/Security/CWE-078/StoredCommand.expected index c37d8af7e64..a01ffb68838 100644 --- a/go/ql/test/query-tests/Security/CWE-078/StoredCommand.expected +++ b/go/ql/test/query-tests/Security/CWE-078/StoredCommand.expected @@ -5,4 +5,4 @@ nodes | StoredCommand.go:14:22:14:28 | cmdName | semmle.label | cmdName | subpaths #select -| StoredCommand.go:14:22:14:28 | cmdName | StoredCommand.go:11:2:11:27 | ... := ...[0] : pointer type | StoredCommand.go:14:22:14:28 | cmdName | This command depends on $@. | StoredCommand.go:11:2:11:27 | ... := ...[0] | a stored value | +| StoredCommand.go:14:22:14:28 | cmdName | StoredCommand.go:11:2:11:27 | ... := ...[0] : pointer type | StoredCommand.go:14:22:14:28 | cmdName | This command depends on a $@. | StoredCommand.go:11:2:11:27 | ... := ...[0] | stored value | diff --git a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected index fda1f774b78..521824433a2 100644 --- a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected +++ b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected @@ -123,28 +123,28 @@ nodes | mongoDB.go:81:18:81:25 | pipeline | semmle.label | pipeline | subpaths #select -| SqlInjection.go:12:11:12:11 | q | SqlInjection.go:11:3:11:9 | selection of URL : pointer type | SqlInjection.go:12:11:12:11 | q | This query depends on $@. | SqlInjection.go:11:3:11:9 | selection of URL | a user-provided value | -| issue48.go:22:11:22:12 | q3 | issue48.go:17:25:17:32 | selection of Body : ReadCloser | issue48.go:22:11:22:12 | q3 | This query depends on $@. | issue48.go:17:25:17:32 | selection of Body | a user-provided value | -| issue48.go:32:11:32:12 | q4 | issue48.go:27:26:27:33 | selection of Body : ReadCloser | issue48.go:32:11:32:12 | q4 | This query depends on $@. | issue48.go:27:26:27:33 | selection of Body | a user-provided value | -| issue48.go:41:11:41:12 | q5 | issue48.go:37:24:37:30 | selection of URL : pointer type | issue48.go:41:11:41:12 | q5 | This query depends on $@. | issue48.go:37:24:37:30 | selection of URL | a user-provided value | -| main.go:10:11:10:28 | index expression | main.go:10:11:10:16 | selection of Form : Values | main.go:10:11:10:28 | index expression | This query depends on $@. | main.go:10:11:10:16 | selection of Form | a user-provided value | -| main.go:14:11:14:84 | call to Sprintf | main.go:14:63:14:67 | selection of URL : pointer type | main.go:14:11:14:84 | call to Sprintf | This query depends on $@. | main.go:14:63:14:67 | selection of URL | a user-provided value | -| main.go:15:11:15:85 | call to Sprintf | main.go:15:63:15:70 | selection of Header : Header | main.go:15:11:15:85 | call to Sprintf | This query depends on $@. | main.go:15:63:15:70 | selection of Header | a user-provided value | -| main.go:34:11:34:11 | q | main.go:29:13:29:19 | selection of URL : pointer type | main.go:34:11:34:11 | q | This query depends on $@. | main.go:29:13:29:19 | selection of URL | a user-provided value | -| main.go:43:11:43:11 | q | main.go:39:25:39:31 | selection of URL : pointer type | main.go:43:11:43:11 | q | This query depends on $@. | main.go:39:25:39:31 | selection of URL | a user-provided value | -| main.go:52:11:52:11 | q | main.go:48:28:48:34 | selection of URL : pointer type | main.go:52:11:52:11 | q | This query depends on $@. | main.go:48:28:48:34 | selection of URL | a user-provided value | -| main.go:61:11:61:11 | q | main.go:57:28:57:34 | selection of URL : pointer type | main.go:61:11:61:11 | q | This query depends on $@. | main.go:57:28:57:34 | selection of URL | a user-provided value | -| mongoDB.go:57:22:57:29 | pipeline | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:57:22:57:29 | pipeline | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:61:27:61:32 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:61:27:61:32 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:63:23:63:28 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:63:23:63:28 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:64:22:64:27 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:64:22:64:27 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:66:32:66:37 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:66:32:66:37 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:69:17:69:22 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:69:17:69:22 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:70:20:70:25 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:70:20:70:25 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:71:29:71:34 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:71:29:71:34 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:72:30:72:35 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:72:30:72:35 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:73:29:73:34 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:73:29:73:34 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:78:23:78:28 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:78:23:78:28 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:79:23:79:28 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:79:23:79:28 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:80:22:80:27 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:80:22:80:27 | filter | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | -| mongoDB.go:81:18:81:25 | pipeline | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:81:18:81:25 | pipeline | This query depends on $@. | mongoDB.go:40:20:40:30 | call to Referer | a user-provided value | +| SqlInjection.go:12:11:12:11 | q | SqlInjection.go:11:3:11:9 | selection of URL : pointer type | SqlInjection.go:12:11:12:11 | q | This query depends on a $@. | SqlInjection.go:11:3:11:9 | selection of URL | user-provided value | +| issue48.go:22:11:22:12 | q3 | issue48.go:17:25:17:32 | selection of Body : ReadCloser | issue48.go:22:11:22:12 | q3 | This query depends on a $@. | issue48.go:17:25:17:32 | selection of Body | user-provided value | +| issue48.go:32:11:32:12 | q4 | issue48.go:27:26:27:33 | selection of Body : ReadCloser | issue48.go:32:11:32:12 | q4 | This query depends on a $@. | issue48.go:27:26:27:33 | selection of Body | user-provided value | +| issue48.go:41:11:41:12 | q5 | issue48.go:37:24:37:30 | selection of URL : pointer type | issue48.go:41:11:41:12 | q5 | This query depends on a $@. | issue48.go:37:24:37:30 | selection of URL | user-provided value | +| main.go:10:11:10:28 | index expression | main.go:10:11:10:16 | selection of Form : Values | main.go:10:11:10:28 | index expression | This query depends on a $@. | main.go:10:11:10:16 | selection of Form | user-provided value | +| main.go:14:11:14:84 | call to Sprintf | main.go:14:63:14:67 | selection of URL : pointer type | main.go:14:11:14:84 | call to Sprintf | This query depends on a $@. | main.go:14:63:14:67 | selection of URL | user-provided value | +| main.go:15:11:15:85 | call to Sprintf | main.go:15:63:15:70 | selection of Header : Header | main.go:15:11:15:85 | call to Sprintf | This query depends on a $@. | main.go:15:63:15:70 | selection of Header | user-provided value | +| main.go:34:11:34:11 | q | main.go:29:13:29:19 | selection of URL : pointer type | main.go:34:11:34:11 | q | This query depends on a $@. | main.go:29:13:29:19 | selection of URL | user-provided value | +| main.go:43:11:43:11 | q | main.go:39:25:39:31 | selection of URL : pointer type | main.go:43:11:43:11 | q | This query depends on a $@. | main.go:39:25:39:31 | selection of URL | user-provided value | +| main.go:52:11:52:11 | q | main.go:48:28:48:34 | selection of URL : pointer type | main.go:52:11:52:11 | q | This query depends on a $@. | main.go:48:28:48:34 | selection of URL | user-provided value | +| main.go:61:11:61:11 | q | main.go:57:28:57:34 | selection of URL : pointer type | main.go:61:11:61:11 | q | This query depends on a $@. | main.go:57:28:57:34 | selection of URL | user-provided value | +| mongoDB.go:57:22:57:29 | pipeline | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:57:22:57:29 | pipeline | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:61:27:61:32 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:61:27:61:32 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:63:23:63:28 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:63:23:63:28 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:64:22:64:27 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:64:22:64:27 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:66:32:66:37 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:66:32:66:37 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:69:17:69:22 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:69:17:69:22 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:70:20:70:25 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:70:20:70:25 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:71:29:71:34 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:71:29:71:34 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:72:30:72:35 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:72:30:72:35 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:73:29:73:34 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:73:29:73:34 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:78:23:78:28 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:78:23:78:28 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:79:23:79:28 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:79:23:79:28 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:80:22:80:27 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:80:22:80:27 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:81:18:81:25 | pipeline | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:81:18:81:25 | pipeline | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.expected b/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.expected index ad949478a18..474cc5aa42c 100644 --- a/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.expected +++ b/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.expected @@ -30,13 +30,13 @@ nodes | tst.go:35:22:35:34 | call to len | semmle.label | call to len | subpaths #select -| AllocationSizeOverflow.go:10:10:10:22 | call to len | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] : slice type | AllocationSizeOverflow.go:10:10:10:22 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | AllocationSizeOverflow.go:11:25:11:28 | size | allocation | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] : slice type | value | -| tst2.go:10:22:10:30 | call to len | tst2.go:9:2:9:37 | ... := ...[0] : slice type | tst2.go:10:22:10:30 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | tst2.go:10:22:10:32 | ...+... | allocation | tst2.go:9:2:9:37 | ... := ...[0] : slice type | value | -| tst2.go:15:22:15:30 | call to len | tst2.go:14:2:14:29 | ... := ...[0] : slice type | tst2.go:15:22:15:30 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | tst2.go:15:22:15:32 | ...+... | allocation | tst2.go:14:2:14:29 | ... := ...[0] : slice type | value | -| tst3.go:7:22:7:34 | call to len | tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:7:22:7:34 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | tst3.go:7:22:7:36 | ...+... | allocation | tst3.go:6:2:6:31 | ... := ...[0] : slice type | value | -| tst3.go:24:16:24:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:24:16:24:28 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | tst3.go:27:24:27:32 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] : slice type | value | -| tst3.go:32:16:32:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:32:16:32:28 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | tst3.go:36:23:36:31 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] : slice type | value | -| tst.go:15:22:15:34 | call to len | tst.go:14:2:14:30 | ... = ...[0] : slice type | tst.go:15:22:15:34 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | tst.go:15:22:15:36 | ...+... | allocation | tst.go:14:2:14:30 | ... = ...[0] : slice type | value | -| tst.go:21:22:21:34 | call to len | tst.go:20:2:20:31 | ... = ...[0] : slice type | tst.go:21:22:21:34 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | tst.go:21:22:21:36 | ...+... | allocation | tst.go:20:2:20:31 | ... = ...[0] : slice type | value | -| tst.go:27:26:27:38 | call to len | tst.go:26:2:26:31 | ... = ...[0] : slice type | tst.go:27:26:27:38 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | tst.go:27:26:27:40 | ...+... | allocation | tst.go:26:2:26:31 | ... = ...[0] : slice type | value | -| tst.go:35:22:35:34 | call to len | tst.go:34:2:34:30 | ... = ...[0] : slice type | tst.go:35:22:35:34 | call to len | This operation, which is used in an $@, involves a potentially large $@ and might overflow. | tst.go:35:22:35:36 | ...+... | allocation | tst.go:34:2:34:30 | ... = ...[0] : slice type | value | +| AllocationSizeOverflow.go:10:10:10:22 | call to len | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] : slice type | AllocationSizeOverflow.go:10:10:10:22 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | AllocationSizeOverflow.go:11:25:11:28 | size | allocation | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] : slice type | potentially large value | +| tst2.go:10:22:10:30 | call to len | tst2.go:9:2:9:37 | ... := ...[0] : slice type | tst2.go:10:22:10:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:10:22:10:32 | ...+... | allocation | tst2.go:9:2:9:37 | ... := ...[0] : slice type | potentially large value | +| tst2.go:15:22:15:30 | call to len | tst2.go:14:2:14:29 | ... := ...[0] : slice type | tst2.go:15:22:15:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:15:22:15:32 | ...+... | allocation | tst2.go:14:2:14:29 | ... := ...[0] : slice type | potentially large value | +| tst3.go:7:22:7:34 | call to len | tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:7:22:7:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:7:22:7:36 | ...+... | allocation | tst3.go:6:2:6:31 | ... := ...[0] : slice type | potentially large value | +| tst3.go:24:16:24:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:24:16:24:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:27:24:27:32 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] : slice type | potentially large value | +| tst3.go:32:16:32:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:32:16:32:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:36:23:36:31 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] : slice type | potentially large value | +| tst.go:15:22:15:34 | call to len | tst.go:14:2:14:30 | ... = ...[0] : slice type | tst.go:15:22:15:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:15:22:15:36 | ...+... | allocation | tst.go:14:2:14:30 | ... = ...[0] : slice type | potentially large value | +| tst.go:21:22:21:34 | call to len | tst.go:20:2:20:31 | ... = ...[0] : slice type | tst.go:21:22:21:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:21:22:21:36 | ...+... | allocation | tst.go:20:2:20:31 | ... = ...[0] : slice type | potentially large value | +| tst.go:27:26:27:38 | call to len | tst.go:26:2:26:31 | ... = ...[0] : slice type | tst.go:27:26:27:38 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:27:26:27:40 | ...+... | allocation | tst.go:26:2:26:31 | ... = ...[0] : slice type | potentially large value | +| tst.go:35:22:35:34 | call to len | tst.go:34:2:34:30 | ... = ...[0] : slice type | tst.go:35:22:35:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:35:22:35:36 | ...+... | allocation | tst.go:34:2:34:30 | ... = ...[0] : slice type | potentially large value | diff --git a/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected b/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected index 8ef001d1a29..ff8c7a9f72f 100644 --- a/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected +++ b/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected @@ -5,4 +5,4 @@ nodes | test.go:17:10:17:12 | buf | semmle.label | buf | subpaths #select -| test.go:17:10:17:12 | buf | test.go:14:2:14:4 | definition of buf : slice type | test.go:17:10:17:12 | buf | Stack trace information from $@ may be exposed to an external user here. | test.go:14:2:14:4 | definition of buf | here | +| test.go:17:10:17:12 | buf | test.go:14:2:14:4 | definition of buf : slice type | test.go:17:10:17:12 | buf | HTTP response depends on $@ and may be exposed to an external user. | test.go:14:2:14:4 | definition of buf | stack trace information | diff --git a/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected index 3a51b06b20e..b7aa675b58e 100644 --- a/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected +++ b/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected @@ -80,34 +80,34 @@ nodes | util.go:16:9:16:18 | selection of password : string | semmle.label | selection of password : string | subpaths #select -| klog.go:22:15:22:20 | header | klog.go:20:30:20:37 | selection of Header : Header | klog.go:22:15:22:20 | header | Sensitive data returned by $@ is logged here. | klog.go:20:30:20:37 | selection of Header | HTTP request headers | -| klog.go:28:13:28:41 | call to Get | klog.go:28:13:28:20 | selection of Header : Header | klog.go:28:13:28:41 | call to Get | Sensitive data returned by $@ is logged here. | klog.go:28:13:28:20 | selection of Header | HTTP request headers | -| main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | Sensitive data returned by $@ is logged here. | main.go:15:14:15:21 | password | an access to password | -| main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | Sensitive data returned by $@ is logged here. | main.go:17:12:17:19 | password | an access to password | -| main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | Sensitive data returned by $@ is logged here. | main.go:18:17:18:24 | password | an access to password | -| main.go:22:29:22:34 | fields | main.go:21:19:21:26 | password : string | main.go:22:29:22:34 | fields | Sensitive data returned by $@ is logged here. | main.go:21:19:21:26 | password | an access to password | -| main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | Sensitive data returned by $@ is logged here. | main.go:25:35:25:42 | password | an access to password | -| overrides.go:13:14:13:23 | call to String | overrides.go:9:9:9:16 | password : string | overrides.go:13:14:13:23 | call to String | Sensitive data returned by $@ is logged here. | overrides.go:9:9:9:16 | password | an access to password | -| passwords.go:9:14:9:14 | x | passwords.go:30:8:30:15 | password : string | passwords.go:9:14:9:14 | x | Sensitive data returned by $@ is logged here. | passwords.go:30:8:30:15 | password | an access to password | -| passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | Sensitive data returned by $@ is logged here. | passwords.go:25:14:25:21 | password | an access to password | -| passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by $@ is logged here. | passwords.go:26:14:26:23 | selection of password | an access to password | -| passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by $@ is logged here. | passwords.go:27:14:27:26 | call to getPassword | a call to getPassword | -| passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by $@ is logged here. | passwords.go:28:14:28:28 | call to getPassword | a call to getPassword | -| passwords.go:28:14:28:28 | call to getPassword | util.go:16:9:16:18 | selection of password : string | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by $@ is logged here. | util.go:16:9:16:18 | selection of password | an access to password | -| passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | Sensitive data returned by $@ is logged here. | passwords.go:32:12:32:19 | password | an access to password | -| passwords.go:34:14:34:35 | ...+... | passwords.go:34:28:34:35 | password : string | passwords.go:34:14:34:35 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:34:28:34:35 | password | an access to password | -| passwords.go:39:14:39:17 | obj1 | passwords.go:37:13:37:13 | x : string | passwords.go:39:14:39:17 | obj1 | Sensitive data returned by $@ is logged here. | passwords.go:37:13:37:13 | x | an access to password | -| passwords.go:44:14:44:17 | obj2 | passwords.go:42:6:42:13 | password : string | passwords.go:44:14:44:17 | obj2 | Sensitive data returned by $@ is logged here. | passwords.go:42:6:42:13 | password | an access to password | -| passwords.go:47:14:47:17 | obj3 | passwords.go:48:11:48:18 | password : string | passwords.go:47:14:47:17 | obj3 | Sensitive data returned by $@ is logged here. | passwords.go:48:11:48:18 | password | an access to password | -| passwords.go:51:14:51:27 | fixed_password | passwords.go:51:14:51:27 | fixed_password | passwords.go:51:14:51:27 | fixed_password | Sensitive data returned by $@ is logged here. | passwords.go:51:14:51:27 | fixed_password | an access to fixed_password | -| passwords.go:88:14:88:26 | utilityObject | passwords.go:86:16:86:36 | call to make : map type | passwords.go:88:14:88:26 | utilityObject | Sensitive data returned by $@ is logged here. | passwords.go:86:16:86:36 | call to make | an access to passwordSet | -| passwords.go:91:23:91:28 | secret | passwords.go:90:12:90:19 | password : string | passwords.go:91:23:91:28 | secret | Sensitive data returned by $@ is logged here. | passwords.go:90:12:90:19 | password | an access to password | -| passwords.go:101:15:101:40 | ...+... | passwords.go:101:33:101:40 | password : string | passwords.go:101:15:101:40 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:101:33:101:40 | password | an access to password | -| passwords.go:107:16:107:41 | ...+... | passwords.go:107:34:107:41 | password : string | passwords.go:107:16:107:41 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:107:34:107:41 | password | an access to password | -| passwords.go:112:15:112:40 | ...+... | passwords.go:112:33:112:40 | password : string | passwords.go:112:15:112:40 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:112:33:112:40 | password | an access to password | -| passwords.go:116:14:116:45 | ...+... | passwords.go:116:28:116:36 | password1 : stringable | passwords.go:116:14:116:45 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:116:28:116:36 | password1 | an access to password1 | -| passwords.go:125:14:125:19 | config | passwords.go:119:13:119:13 | x : string | passwords.go:125:14:125:19 | config | Sensitive data returned by $@ is logged here. | passwords.go:119:13:119:13 | x | an access to password | -| passwords.go:125:14:125:19 | config | passwords.go:121:13:121:20 | password : string | passwords.go:125:14:125:19 | config | Sensitive data returned by $@ is logged here. | passwords.go:121:13:121:20 | password | an access to password | -| passwords.go:125:14:125:19 | config | passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:125:14:125:19 | config | Sensitive data returned by $@ is logged here. | passwords.go:122:13:122:25 | call to getPassword | a call to getPassword | -| passwords.go:126:14:126:21 | selection of x | passwords.go:121:13:121:20 | password : string | passwords.go:126:14:126:21 | selection of x | Sensitive data returned by $@ is logged here. | passwords.go:121:13:121:20 | password | an access to password | -| passwords.go:127:14:127:21 | selection of y | passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:127:14:127:21 | selection of y | Sensitive data returned by $@ is logged here. | passwords.go:122:13:122:25 | call to getPassword | a call to getPassword | +| klog.go:22:15:22:20 | header | klog.go:20:30:20:37 | selection of Header : Header | klog.go:22:15:22:20 | header | $@ flows to a logging call. | klog.go:20:30:20:37 | selection of Header | Sensitive data returned by HTTP request headers | +| klog.go:28:13:28:41 | call to Get | klog.go:28:13:28:20 | selection of Header : Header | klog.go:28:13:28:41 | call to Get | $@ flows to a logging call. | klog.go:28:13:28:20 | selection of Header | Sensitive data returned by HTTP request headers | +| main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | $@ flows to a logging call. | main.go:15:14:15:21 | password | Sensitive data returned by an access to password | +| main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | $@ flows to a logging call. | main.go:17:12:17:19 | password | Sensitive data returned by an access to password | +| main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | $@ flows to a logging call. | main.go:18:17:18:24 | password | Sensitive data returned by an access to password | +| main.go:22:29:22:34 | fields | main.go:21:19:21:26 | password : string | main.go:22:29:22:34 | fields | $@ flows to a logging call. | main.go:21:19:21:26 | password | Sensitive data returned by an access to password | +| main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | $@ flows to a logging call. | main.go:25:35:25:42 | password | Sensitive data returned by an access to password | +| overrides.go:13:14:13:23 | call to String | overrides.go:9:9:9:16 | password : string | overrides.go:13:14:13:23 | call to String | $@ flows to a logging call. | overrides.go:9:9:9:16 | password | Sensitive data returned by an access to password | +| passwords.go:9:14:9:14 | x | passwords.go:30:8:30:15 | password : string | passwords.go:9:14:9:14 | x | $@ flows to a logging call. | passwords.go:30:8:30:15 | password | Sensitive data returned by an access to password | +| passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | $@ flows to a logging call. | passwords.go:25:14:25:21 | password | Sensitive data returned by an access to password | +| passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | $@ flows to a logging call. | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by an access to password | +| passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | $@ flows to a logging call. | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by a call to getPassword | +| passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by a call to getPassword | +| passwords.go:28:14:28:28 | call to getPassword | util.go:16:9:16:18 | selection of password : string | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | util.go:16:9:16:18 | selection of password | Sensitive data returned by an access to password | +| passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | $@ flows to a logging call. | passwords.go:32:12:32:19 | password | Sensitive data returned by an access to password | +| passwords.go:34:14:34:35 | ...+... | passwords.go:34:28:34:35 | password : string | passwords.go:34:14:34:35 | ...+... | $@ flows to a logging call. | passwords.go:34:28:34:35 | password | Sensitive data returned by an access to password | +| passwords.go:39:14:39:17 | obj1 | passwords.go:37:13:37:13 | x : string | passwords.go:39:14:39:17 | obj1 | $@ flows to a logging call. | passwords.go:37:13:37:13 | x | Sensitive data returned by an access to password | +| passwords.go:44:14:44:17 | obj2 | passwords.go:42:6:42:13 | password : string | passwords.go:44:14:44:17 | obj2 | $@ flows to a logging call. | passwords.go:42:6:42:13 | password | Sensitive data returned by an access to password | +| passwords.go:47:14:47:17 | obj3 | passwords.go:48:11:48:18 | password : string | passwords.go:47:14:47:17 | obj3 | $@ flows to a logging call. | passwords.go:48:11:48:18 | password | Sensitive data returned by an access to password | +| passwords.go:51:14:51:27 | fixed_password | passwords.go:51:14:51:27 | fixed_password | passwords.go:51:14:51:27 | fixed_password | $@ flows to a logging call. | passwords.go:51:14:51:27 | fixed_password | Sensitive data returned by an access to fixed_password | +| passwords.go:88:14:88:26 | utilityObject | passwords.go:86:16:86:36 | call to make : map type | passwords.go:88:14:88:26 | utilityObject | $@ flows to a logging call. | passwords.go:86:16:86:36 | call to make | Sensitive data returned by an access to passwordSet | +| passwords.go:91:23:91:28 | secret | passwords.go:90:12:90:19 | password : string | passwords.go:91:23:91:28 | secret | $@ flows to a logging call. | passwords.go:90:12:90:19 | password | Sensitive data returned by an access to password | +| passwords.go:101:15:101:40 | ...+... | passwords.go:101:33:101:40 | password : string | passwords.go:101:15:101:40 | ...+... | $@ flows to a logging call. | passwords.go:101:33:101:40 | password | Sensitive data returned by an access to password | +| passwords.go:107:16:107:41 | ...+... | passwords.go:107:34:107:41 | password : string | passwords.go:107:16:107:41 | ...+... | $@ flows to a logging call. | passwords.go:107:34:107:41 | password | Sensitive data returned by an access to password | +| passwords.go:112:15:112:40 | ...+... | passwords.go:112:33:112:40 | password : string | passwords.go:112:15:112:40 | ...+... | $@ flows to a logging call. | passwords.go:112:33:112:40 | password | Sensitive data returned by an access to password | +| passwords.go:116:14:116:45 | ...+... | passwords.go:116:28:116:36 | password1 : stringable | passwords.go:116:14:116:45 | ...+... | $@ flows to a logging call. | passwords.go:116:28:116:36 | password1 | Sensitive data returned by an access to password1 | +| passwords.go:125:14:125:19 | config | passwords.go:119:13:119:13 | x : string | passwords.go:125:14:125:19 | config | $@ flows to a logging call. | passwords.go:119:13:119:13 | x | Sensitive data returned by an access to password | +| passwords.go:125:14:125:19 | config | passwords.go:121:13:121:20 | password : string | passwords.go:125:14:125:19 | config | $@ flows to a logging call. | passwords.go:121:13:121:20 | password | Sensitive data returned by an access to password | +| passwords.go:125:14:125:19 | config | passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:125:14:125:19 | config | $@ flows to a logging call. | passwords.go:122:13:122:25 | call to getPassword | Sensitive data returned by a call to getPassword | +| passwords.go:126:14:126:21 | selection of x | passwords.go:121:13:121:20 | password : string | passwords.go:126:14:126:21 | selection of x | $@ flows to a logging call. | passwords.go:121:13:121:20 | password | Sensitive data returned by an access to password | +| passwords.go:127:14:127:21 | selection of y | passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:127:14:127:21 | selection of y | $@ flows to a logging call. | passwords.go:122:13:122:25 | call to getPassword | Sensitive data returned by a call to getPassword | diff --git a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected index 39e882bdba7..c27f575acc3 100644 --- a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected +++ b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected @@ -119,14 +119,14 @@ nodes | stdlib.go:194:23:194:42 | call to EscapedPath | semmle.label | call to EscapedPath | subpaths #select -| OpenUrlRedirect.go:10:23:10:42 | call to Get | OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | OpenUrlRedirect.go:10:23:10:42 | call to Get | Untrusted URL redirection due to $@. | OpenUrlRedirect.go:10:23:10:28 | selection of Form | user-provided value | -| stdlib.go:15:30:15:35 | target | stdlib.go:13:13:13:18 | selection of Form : Values | stdlib.go:15:30:15:35 | target | Untrusted URL redirection due to $@. | stdlib.go:13:13:13:18 | selection of Form | user-provided value | -| stdlib.go:24:30:24:35 | target | stdlib.go:22:13:22:18 | selection of Form : Values | stdlib.go:24:30:24:35 | target | Untrusted URL redirection due to $@. | stdlib.go:22:13:22:18 | selection of Form | user-provided value | -| stdlib.go:35:30:35:39 | ...+... | stdlib.go:31:13:31:18 | selection of Form : Values | stdlib.go:35:30:35:39 | ...+... | Untrusted URL redirection due to $@. | stdlib.go:31:13:31:18 | selection of Form | user-provided value | -| stdlib.go:46:23:46:28 | target | stdlib.go:44:13:44:18 | selection of Form : Values | stdlib.go:46:23:46:28 | target | Untrusted URL redirection due to $@. | stdlib.go:44:13:44:18 | selection of Form | user-provided value | -| stdlib.go:67:23:67:40 | ...+... | stdlib.go:64:13:64:18 | selection of Form : Values | stdlib.go:67:23:67:40 | ...+... | Untrusted URL redirection due to $@. | stdlib.go:64:13:64:18 | selection of Form | user-provided value | -| stdlib.go:92:23:92:28 | target | stdlib.go:89:13:89:18 | selection of Form : Values | stdlib.go:92:23:92:28 | target | Untrusted URL redirection due to $@. | stdlib.go:89:13:89:18 | selection of Form | user-provided value | -| stdlib.go:152:23:152:28 | target | stdlib.go:146:13:146:18 | selection of Form : Values | stdlib.go:152:23:152:28 | target | Untrusted URL redirection due to $@. | stdlib.go:146:13:146:18 | selection of Form | user-provided value | -| stdlib.go:184:23:184:28 | target | stdlib.go:182:13:182:33 | call to FormValue : string | stdlib.go:184:23:184:28 | target | Untrusted URL redirection due to $@. | stdlib.go:182:13:182:33 | call to FormValue | user-provided value | -| stdlib.go:192:23:192:33 | selection of Path | stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:192:23:192:33 | selection of Path | Untrusted URL redirection due to $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | -| stdlib.go:194:23:194:42 | call to EscapedPath | stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:194:23:194:42 | call to EscapedPath | Untrusted URL redirection due to $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | +| OpenUrlRedirect.go:10:23:10:42 | call to Get | OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | OpenUrlRedirect.go:10:23:10:42 | call to Get | Untrusted URL redirection depends on a $@. | OpenUrlRedirect.go:10:23:10:28 | selection of Form | user-provided value | +| stdlib.go:15:30:15:35 | target | stdlib.go:13:13:13:18 | selection of Form : Values | stdlib.go:15:30:15:35 | target | Untrusted URL redirection depends on a $@. | stdlib.go:13:13:13:18 | selection of Form | user-provided value | +| stdlib.go:24:30:24:35 | target | stdlib.go:22:13:22:18 | selection of Form : Values | stdlib.go:24:30:24:35 | target | Untrusted URL redirection depends on a $@. | stdlib.go:22:13:22:18 | selection of Form | user-provided value | +| stdlib.go:35:30:35:39 | ...+... | stdlib.go:31:13:31:18 | selection of Form : Values | stdlib.go:35:30:35:39 | ...+... | Untrusted URL redirection depends on a $@. | stdlib.go:31:13:31:18 | selection of Form | user-provided value | +| stdlib.go:46:23:46:28 | target | stdlib.go:44:13:44:18 | selection of Form : Values | stdlib.go:46:23:46:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:44:13:44:18 | selection of Form | user-provided value | +| stdlib.go:67:23:67:40 | ...+... | stdlib.go:64:13:64:18 | selection of Form : Values | stdlib.go:67:23:67:40 | ...+... | Untrusted URL redirection depends on a $@. | stdlib.go:64:13:64:18 | selection of Form | user-provided value | +| stdlib.go:92:23:92:28 | target | stdlib.go:89:13:89:18 | selection of Form : Values | stdlib.go:92:23:92:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:89:13:89:18 | selection of Form | user-provided value | +| stdlib.go:152:23:152:28 | target | stdlib.go:146:13:146:18 | selection of Form : Values | stdlib.go:152:23:152:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:146:13:146:18 | selection of Form | user-provided value | +| stdlib.go:184:23:184:28 | target | stdlib.go:182:13:182:33 | call to FormValue : string | stdlib.go:184:23:184:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:182:13:182:33 | call to FormValue | user-provided value | +| stdlib.go:192:23:192:33 | selection of Path | stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:192:23:192:33 | selection of Path | Untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | +| stdlib.go:194:23:194:42 | call to EscapedPath | stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:194:23:194:42 | call to EscapedPath | Untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected index 42c6f9cda2a..081b1a2cdba 100644 --- a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected +++ b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected @@ -85,43 +85,43 @@ nodes | tst.go:180:27:180:122 | ...+... | semmle.label | ...+... | subpaths #select -| XPathInjection.go:16:29:16:91 | ...+... | XPathInjection.go:13:14:13:19 | selection of Form : Values | XPathInjection.go:16:29:16:91 | ...+... | $@ flows to here and is used in an XPath expression. | XPathInjection.go:13:14:13:19 | selection of Form | User-provided value | -| tst.go:35:23:35:85 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:35:23:35:85 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:32:14:32:19 | selection of Form | User-provided value | -| tst.go:38:24:38:86 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:38:24:38:86 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:32:14:32:19 | selection of Form | User-provided value | -| tst.go:41:24:41:82 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:41:24:41:82 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:32:14:32:19 | selection of Form | User-provided value | -| tst.go:49:26:49:84 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:49:26:49:84 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | User-provided value | -| tst.go:52:29:52:87 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:52:29:52:87 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | User-provided value | -| tst.go:55:33:55:91 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:55:33:55:91 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | User-provided value | -| tst.go:58:30:58:88 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:58:30:58:88 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | User-provided value | -| tst.go:66:25:66:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:66:25:66:83 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value | -| tst.go:69:28:69:86 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:69:28:69:86 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value | -| tst.go:72:25:72:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:72:25:72:83 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value | -| tst.go:75:34:75:92 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:75:34:75:92 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value | -| tst.go:78:32:78:90 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:78:32:78:90 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value | -| tst.go:81:29:81:87 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:81:29:81:87 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value | -| tst.go:84:23:84:85 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:84:23:84:85 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value | -| tst.go:87:22:87:84 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:87:22:87:84 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value | -| tst.go:95:26:95:84 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:95:26:95:84 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | User-provided value | -| tst.go:98:29:98:87 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:98:29:98:87 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | User-provided value | -| tst.go:101:33:101:91 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:101:33:101:91 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | User-provided value | -| tst.go:104:30:104:88 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:104:30:104:88 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | User-provided value | -| tst.go:112:25:112:87 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:112:25:112:87 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:109:14:109:19 | selection of Form | User-provided value | -| tst.go:115:26:115:88 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:115:26:115:88 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:109:14:109:19 | selection of Form | User-provided value | -| tst.go:124:23:124:126 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:120:14:120:19 | selection of Form | User-provided value | -| tst.go:124:23:124:126 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:121:14:121:19 | selection of Form | User-provided value | -| tst.go:127:24:127:127 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:120:14:120:19 | selection of Form | User-provided value | -| tst.go:127:24:127:127 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:121:14:121:19 | selection of Form | User-provided value | -| tst.go:130:27:130:122 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:120:14:120:19 | selection of Form | User-provided value | -| tst.go:130:27:130:122 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:121:14:121:19 | selection of Form | User-provided value | -| tst.go:141:27:141:89 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:141:27:141:89 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:138:14:138:19 | selection of Form | User-provided value | -| tst.go:144:28:144:90 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:144:28:144:90 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:138:14:138:19 | selection of Form | User-provided value | -| tst.go:153:33:153:136 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value | -| tst.go:153:33:153:136 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value | -| tst.go:156:18:156:121 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value | -| tst.go:156:18:156:121 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value | -| tst.go:162:31:162:126 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value | -| tst.go:162:31:162:126 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value | -| tst.go:171:21:171:116 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value | -| tst.go:171:21:171:116 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value | -| tst.go:180:27:180:122 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value | -| tst.go:180:27:180:122 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value | +| XPathInjection.go:16:29:16:91 | ...+... | XPathInjection.go:13:14:13:19 | selection of Form : Values | XPathInjection.go:16:29:16:91 | ...+... | XPath expression depends on a $@. | XPathInjection.go:13:14:13:19 | selection of Form | user-provided value | +| tst.go:35:23:35:85 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:35:23:35:85 | ...+... | XPath expression depends on a $@. | tst.go:32:14:32:19 | selection of Form | user-provided value | +| tst.go:38:24:38:86 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:38:24:38:86 | ...+... | XPath expression depends on a $@. | tst.go:32:14:32:19 | selection of Form | user-provided value | +| tst.go:41:24:41:82 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:41:24:41:82 | ...+... | XPath expression depends on a $@. | tst.go:32:14:32:19 | selection of Form | user-provided value | +| tst.go:49:26:49:84 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:49:26:49:84 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | +| tst.go:52:29:52:87 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:52:29:52:87 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | +| tst.go:55:33:55:91 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:55:33:55:91 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | +| tst.go:58:30:58:88 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:58:30:58:88 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | +| tst.go:66:25:66:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:66:25:66:83 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:69:28:69:86 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:69:28:69:86 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:72:25:72:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:72:25:72:83 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:75:34:75:92 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:75:34:75:92 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:78:32:78:90 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:78:32:78:90 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:81:29:81:87 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:81:29:81:87 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:84:23:84:85 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:84:23:84:85 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:87:22:87:84 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:87:22:87:84 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:95:26:95:84 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:95:26:95:84 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | +| tst.go:98:29:98:87 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:98:29:98:87 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | +| tst.go:101:33:101:91 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:101:33:101:91 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | +| tst.go:104:30:104:88 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:104:30:104:88 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | +| tst.go:112:25:112:87 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:112:25:112:87 | ...+... | XPath expression depends on a $@. | tst.go:109:14:109:19 | selection of Form | user-provided value | +| tst.go:115:26:115:88 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:115:26:115:88 | ...+... | XPath expression depends on a $@. | tst.go:109:14:109:19 | selection of Form | user-provided value | +| tst.go:124:23:124:126 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | XPath expression depends on a $@. | tst.go:120:14:120:19 | selection of Form | user-provided value | +| tst.go:124:23:124:126 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | XPath expression depends on a $@. | tst.go:121:14:121:19 | selection of Form | user-provided value | +| tst.go:127:24:127:127 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | XPath expression depends on a $@. | tst.go:120:14:120:19 | selection of Form | user-provided value | +| tst.go:127:24:127:127 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | XPath expression depends on a $@. | tst.go:121:14:121:19 | selection of Form | user-provided value | +| tst.go:130:27:130:122 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | XPath expression depends on a $@. | tst.go:120:14:120:19 | selection of Form | user-provided value | +| tst.go:130:27:130:122 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | XPath expression depends on a $@. | tst.go:121:14:121:19 | selection of Form | user-provided value | +| tst.go:141:27:141:89 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:141:27:141:89 | ...+... | XPath expression depends on a $@. | tst.go:138:14:138:19 | selection of Form | user-provided value | +| tst.go:144:28:144:90 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:144:28:144:90 | ...+... | XPath expression depends on a $@. | tst.go:138:14:138:19 | selection of Form | user-provided value | +| tst.go:153:33:153:136 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:153:33:153:136 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | +| tst.go:156:18:156:121 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:156:18:156:121 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | +| tst.go:162:31:162:126 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:162:31:162:126 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | +| tst.go:171:21:171:116 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:171:21:171:116 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | +| tst.go:180:27:180:122 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:180:27:180:122 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected index d29e72e3862..7751054abbd 100644 --- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected +++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected @@ -56,20 +56,20 @@ nodes | websocket.go:204:11:204:24 | untrustedInput | semmle.label | untrustedInput | subpaths #select -| RequestForgery.go:11:15:11:66 | call to Get | RequestForgery.go:8:12:8:34 | call to FormValue : string | RequestForgery.go:11:24:11:65 | ...+... | The $@ of this request depends on $@. | RequestForgery.go:11:24:11:65 | ...+... | URL | RequestForgery.go:8:12:8:34 | call to FormValue : string | a user-provided value | -| tst.go:14:2:14:18 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:14:11:14:17 | tainted | The $@ of this request depends on $@. | tst.go:14:11:14:17 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:18:2:18:38 | call to Post | tst.go:10:13:10:35 | call to FormValue : string | tst.go:18:12:18:18 | tainted | The $@ of this request depends on $@. | tst.go:18:12:18:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:22:2:22:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:21:34:21:40 | tainted | The $@ of this request depends on $@. | tst.go:21:34:21:40 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:25:2:25:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:24:66:24:72 | tainted | The $@ of this request depends on $@. | tst.go:24:66:24:72 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:27:2:27:30 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:27:11:27:29 | ...+... | The $@ of this request depends on $@. | tst.go:27:11:27:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:29:2:29:41 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:29:11:29:40 | ...+... | The $@ of this request depends on $@. | tst.go:29:11:29:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:37:2:37:21 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:37:11:37:20 | call to String | The $@ of this request depends on $@. | tst.go:37:11:37:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| websocket.go:65:12:65:53 | call to Dial | websocket.go:60:21:60:31 | call to Referer : string | websocket.go:65:27:65:40 | untrustedInput | The $@ of this request depends on $@. | websocket.go:65:27:65:40 | untrustedInput | WebSocket URL | websocket.go:60:21:60:31 | call to Referer : string | a user-provided value | -| websocket.go:79:13:79:40 | call to DialConfig | websocket.go:74:21:74:31 | call to Referer : string | websocket.go:78:36:78:49 | untrustedInput | The $@ of this request depends on $@. | websocket.go:78:36:78:49 | untrustedInput | WebSocket URL | websocket.go:74:21:74:31 | call to Referer : string | a user-provided value | -| websocket.go:91:3:91:50 | call to Dial | websocket.go:88:21:88:31 | call to Referer : string | websocket.go:91:31:91:44 | untrustedInput | The $@ of this request depends on $@. | websocket.go:91:31:91:44 | untrustedInput | WebSocket URL | websocket.go:88:21:88:31 | call to Referer : string | a user-provided value | -| websocket.go:110:3:110:39 | call to Dial | websocket.go:107:21:107:31 | call to Referer : string | websocket.go:110:15:110:28 | untrustedInput | The $@ of this request depends on $@. | websocket.go:110:15:110:28 | untrustedInput | WebSocket URL | websocket.go:107:21:107:31 | call to Referer : string | a user-provided value | -| websocket.go:129:3:129:62 | call to DialContext | websocket.go:126:21:126:31 | call to Referer : string | websocket.go:129:38:129:51 | untrustedInput | The $@ of this request depends on $@. | websocket.go:129:38:129:51 | untrustedInput | WebSocket URL | websocket.go:126:21:126:31 | call to Referer : string | a user-provided value | -| websocket.go:155:3:155:45 | call to Dial | websocket.go:154:21:154:31 | call to Referer : string | websocket.go:155:31:155:44 | untrustedInput | The $@ of this request depends on $@. | websocket.go:155:31:155:44 | untrustedInput | WebSocket URL | websocket.go:154:21:154:31 | call to Referer : string | a user-provided value | -| websocket.go:162:3:162:45 | call to Dial | websocket.go:160:21:160:31 | call to Referer : string | websocket.go:162:31:162:44 | untrustedInput | The $@ of this request depends on $@. | websocket.go:162:31:162:44 | untrustedInput | WebSocket URL | websocket.go:160:21:160:31 | call to Referer : string | a user-provided value | -| websocket.go:197:3:197:32 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer : string | websocket.go:197:18:197:31 | untrustedInput | The $@ of this request depends on $@. | websocket.go:197:18:197:31 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer : string | a user-provided value | -| websocket.go:204:3:204:25 | call to New | websocket.go:202:21:202:31 | call to Referer : string | websocket.go:204:11:204:24 | untrustedInput | The $@ of this request depends on $@. | websocket.go:204:11:204:24 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer : string | a user-provided value | +| RequestForgery.go:11:15:11:66 | call to Get | RequestForgery.go:8:12:8:34 | call to FormValue : string | RequestForgery.go:11:24:11:65 | ...+... | The $@ of this request depends on a $@. | RequestForgery.go:11:24:11:65 | ...+... | URL | RequestForgery.go:8:12:8:34 | call to FormValue : string | user-provided value | +| tst.go:14:2:14:18 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:14:11:14:17 | tainted | The $@ of this request depends on a $@. | tst.go:14:11:14:17 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | +| tst.go:18:2:18:38 | call to Post | tst.go:10:13:10:35 | call to FormValue : string | tst.go:18:12:18:18 | tainted | The $@ of this request depends on a $@. | tst.go:18:12:18:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | +| tst.go:22:2:22:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:21:34:21:40 | tainted | The $@ of this request depends on a $@. | tst.go:21:34:21:40 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | +| tst.go:25:2:25:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:24:66:24:72 | tainted | The $@ of this request depends on a $@. | tst.go:24:66:24:72 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | +| tst.go:27:2:27:30 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:27:11:27:29 | ...+... | The $@ of this request depends on a $@. | tst.go:27:11:27:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | +| tst.go:29:2:29:41 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:29:11:29:40 | ...+... | The $@ of this request depends on a $@. | tst.go:29:11:29:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | +| tst.go:37:2:37:21 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:37:11:37:20 | call to String | The $@ of this request depends on a $@. | tst.go:37:11:37:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | +| websocket.go:65:12:65:53 | call to Dial | websocket.go:60:21:60:31 | call to Referer : string | websocket.go:65:27:65:40 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:65:27:65:40 | untrustedInput | WebSocket URL | websocket.go:60:21:60:31 | call to Referer : string | user-provided value | +| websocket.go:79:13:79:40 | call to DialConfig | websocket.go:74:21:74:31 | call to Referer : string | websocket.go:78:36:78:49 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:78:36:78:49 | untrustedInput | WebSocket URL | websocket.go:74:21:74:31 | call to Referer : string | user-provided value | +| websocket.go:91:3:91:50 | call to Dial | websocket.go:88:21:88:31 | call to Referer : string | websocket.go:91:31:91:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:91:31:91:44 | untrustedInput | WebSocket URL | websocket.go:88:21:88:31 | call to Referer : string | user-provided value | +| websocket.go:110:3:110:39 | call to Dial | websocket.go:107:21:107:31 | call to Referer : string | websocket.go:110:15:110:28 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:110:15:110:28 | untrustedInput | WebSocket URL | websocket.go:107:21:107:31 | call to Referer : string | user-provided value | +| websocket.go:129:3:129:62 | call to DialContext | websocket.go:126:21:126:31 | call to Referer : string | websocket.go:129:38:129:51 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:129:38:129:51 | untrustedInput | WebSocket URL | websocket.go:126:21:126:31 | call to Referer : string | user-provided value | +| websocket.go:155:3:155:45 | call to Dial | websocket.go:154:21:154:31 | call to Referer : string | websocket.go:155:31:155:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:155:31:155:44 | untrustedInput | WebSocket URL | websocket.go:154:21:154:31 | call to Referer : string | user-provided value | +| websocket.go:162:3:162:45 | call to Dial | websocket.go:160:21:160:31 | call to Referer : string | websocket.go:162:31:162:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:162:31:162:44 | untrustedInput | WebSocket URL | websocket.go:160:21:160:31 | call to Referer : string | user-provided value | +| websocket.go:197:3:197:32 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer : string | websocket.go:197:18:197:31 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:197:18:197:31 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer : string | user-provided value | +| websocket.go:204:3:204:25 | call to New | websocket.go:202:21:202:31 | call to Referer : string | websocket.go:204:11:204:24 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:204:11:204:24 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer : string | user-provided value | diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index 029f1b41e91..425da54f994 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -1,123 +1,130 @@ -package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jdbc-url,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:regex-use[-1],sink:regex-use[0],sink:regex-use[],sink:regex-use[f-1],sink:regex-use[f1],sink:regex-use[f],sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:android-external-storage-dir,source:android-widget,source:contentprovider,source:remote,summary:taint,summary:value -android.app,24,,103,,,,,,7,,,,,,,,,17,,,,,,,,,,,,,,,,,,,18,85 -android.content,24,31,154,,,,,,16,,,,,,,,,,,,,,,,,8,,,,,,,4,,27,,63,91 -android.database,59,,39,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,39, -android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,45,15 -android.os,,2,122,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,41,81 -android.util,6,16,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,16,, -android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,2,, -android.widget,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,1, -androidx.core.app,6,,95,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,12,83 -androidx.slice,2,5,88,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,5,,27,61 -cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6, -com.google.common.base,4,,85,,,,,,,,,,,,,,,,,3,1,,,,,,,,,,,,,,,,62,23 -com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17 -com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,551 -com.google.common.flogger,29,,,,,,,,,,,,,29,,,,,,,,,,,,,,,,,,,,,,,, -com.google.common.io,6,,73,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,72,1 -com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,,,,, -com.rabbitmq.client,,21,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,7, -com.unboundid.ldap.sdk,17,,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,,,, -com.zaxxer.hikari,2,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,, -flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 -groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, -jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 -jakarta.ws.rs.client,1,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,, -jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,, -jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55 -java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -java.io,37,,39,,15,,,,,,,,,,,,,,,,,,,,,,,,22,,,,,,,,39, -java.lang,13,,66,,,,,,,,,,,8,,,,,4,,,1,,,,,,,,,,,,,,,54,12 -java.net,10,3,7,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,3,7, -java.nio,15,,11,,13,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,11, -java.sql,11,,,,,,,,,4,,,,,,,,,,,,,,,,7,,,,,,,,,,,, -java.util,44,,461,,,,,,,,,,,34,,,,,,5,2,,1,2,,,,,,,,,,,,,36,425 -javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, -javax.jms,,9,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,57, -javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 -javax.management.remote,2,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,, -javax.naming,7,,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,,,,,,,,, -javax.net.ssl,2,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,, -javax.script,1,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,, -javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,2, -javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,, -javax.ws.rs.client,1,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,, -javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,, -javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55 -javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,6, -javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,, -jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10 -kotlin,12,,1835,,10,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,1828,7 -net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,, -ognl,6,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,, -okhttp3,2,,47,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,22,25 -org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6, -org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783 -org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783 -org.apache.commons.io,106,,556,,91,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,542,14 -org.apache.commons.jexl2,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.commons.jexl3,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,293,131 -org.apache.commons.logging,6,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.commons.ognl,6,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,, -org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,220,52 -org.apache.directory.ldap.client.api,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,2,39, -org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2, -org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,18,6 -org.apache.http,27,3,70,,,,,,,,,,,,,,25,,,,,,,,,,,,,,,2,,,,3,62,8 -org.apache.ibatis.jdbc,6,,57,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,57, -org.apache.log4j,11,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.logging.log4j,359,,8,,,,,,,,,,,359,,,,,,,,,,,,,,,,,,,,,,,4,4 -org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -org.apache.shiro.jndi,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,, -org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,, -org.hibernate,7,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,, -org.jboss.logging,324,,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,,,,,,,, -org.jdbi.v3.core,6,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.jooq,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,, -org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,198,38 -org.mvel2,16,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,,,,,,,, -org.scijava.log,13,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,,, -org.slf4j,55,,6,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,2,4 -org.springframework.beans,,,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30 -org.springframework.boot.jdbc,1,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13 -org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, -org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 -org.springframework.http,14,,70,,,,,,,,,,,,,,14,,,,,,,,,,,,,,,,,,,,60,10 -org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,, -org.springframework.jdbc.datasource,4,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,, -org.springframework.jndi,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,, -org.springframework.ldap,47,,,,,,,,,,,33,14,,,,,,,,,,,,,,,,,,,,,,,,, -org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,, -org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32 -org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,87,52 -org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13, -org.springframework.web.client,13,3,,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,3,, -org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,, -org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,12,13, -org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,, -org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,138,25 -org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,, -play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,, -ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, -ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4, -ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10, -ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,48 -ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, -ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35 -ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4, -ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10, -ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35 -retrofit2,1,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,, +package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jdbc-url,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:regex-use[-1],sink:regex-use[0],sink:regex-use[],sink:regex-use[f-1],sink:regex-use[f1],sink:regex-use[f],sink:set-hostname-verifier,sink:sql,sink:ssti,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:android-external-storage-dir,source:android-widget,source:contentprovider,source:remote,summary:taint,summary:value +android.app,24,,103,,,,,,7,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,18,85 +android.content,24,31,154,,,,,,16,,,,,,,,,,,,,,,,,8,,,,,,,,4,,27,,63,91 +android.database,59,,39,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,39, +android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,45,15 +android.os,,2,122,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,41,81 +android.util,6,16,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,16,, +android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,2,, +android.widget,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,1, +androidx.core.app,6,,95,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,12,83 +androidx.slice,2,5,88,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,5,,27,61 +cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6, +com.google.common.base,4,,85,,,,,,,,,,,,,,,,,3,1,,,,,,,,,,,,,,,,,62,23 +com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17 +com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,551 +com.google.common.flogger,29,,,,,,,,,,,,,29,,,,,,,,,,,,,,,,,,,,,,,,, +com.google.common.io,6,,73,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,72,1 +com.hubspot.jinjava,2,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,, +com.mitchellbosecke.pebble,2,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,, +com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,, +com.rabbitmq.client,,21,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,7, +com.unboundid.ldap.sdk,17,,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,,,,, +com.zaxxer.hikari,2,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 +freemarker.cache,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,, +freemarker.template,7,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,, +groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, +jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 +jakarta.ws.rs.client,1,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,, +jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,, +jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55 +java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +java.io,37,,39,,15,,,,,,,,,,,,,,,,,,,,,,,,,22,,,,,,,,39, +java.lang,13,,66,,,,,,,,,,,8,,,,,4,,,1,,,,,,,,,,,,,,,,54,12 +java.net,10,3,7,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,,3,7, +java.nio,15,,11,,13,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,11, +java.sql,11,,,,,,,,,4,,,,,,,,,,,,,,,,7,,,,,,,,,,,,, +java.util,44,,461,,,,,,,,,,,34,,,,,,5,2,,1,2,,,,,,,,,,,,,,36,425 +javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, +javax.jms,,9,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,57, +javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 +javax.management.remote,2,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,, +javax.naming,7,,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,,,,,,,,,, +javax.net.ssl,2,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,, +javax.script,1,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, +javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,2, +javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,, +javax.ws.rs.client,1,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,, +javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,, +javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55 +javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,6, +javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,, +jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10 +kotlin,12,,1835,,10,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,1828,7 +net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,, +ognl,6,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,, +okhttp3,2,,47,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,22,25 +org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6, +org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783 +org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783 +org.apache.commons.io,106,,556,,91,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,542,14 +org.apache.commons.jexl2,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.commons.jexl3,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,293,131 +org.apache.commons.logging,6,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.commons.ognl,6,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,, +org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,220,52 +org.apache.directory.ldap.client.api,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,2,39, +org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2, +org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,18,6 +org.apache.http,27,3,70,,,,,,,,,,,,,,25,,,,,,,,,,,,,,,,2,,,,3,62,8 +org.apache.ibatis.jdbc,6,,57,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,57, +org.apache.log4j,11,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.logging.log4j,359,,8,,,,,,,,,,,359,,,,,,,,,,,,,,,,,,,,,,,,4,4 +org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +org.apache.shiro.jndi,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.velocity.app,4,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,, +org.apache.velocity.runtime,4,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,, +org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,, +org.hibernate,7,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,, +org.jboss.logging,324,,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,,,,,,,,, +org.jdbi.v3.core,6,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.jooq,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,, +org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,198,38 +org.mvel2,16,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,,,,,,,,, +org.scijava.log,13,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,,,, +org.slf4j,55,,6,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,2,4 +org.springframework.beans,,,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30 +org.springframework.boot.jdbc,1,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13 +org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, +org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 +org.springframework.http,14,,70,,,,,,,,,,,,,,14,,,,,,,,,,,,,,,,,,,,,60,10 +org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,, +org.springframework.jdbc.datasource,4,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,, +org.springframework.jndi,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.springframework.ldap,47,,,,,,,,,,,33,14,,,,,,,,,,,,,,,,,,,,,,,,,, +org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,, +org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32 +org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,87,52 +org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13, +org.springframework.web.client,13,3,,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,3,, +org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,, +org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,12,13, +org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,, +org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,138,25 +org.thymeleaf,2,,2,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,2, +org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,, +play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,, +ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, +ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4, +ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10, +ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,48 +ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, +ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35 +ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4, +ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10, +ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35 +retrofit2,1,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,, diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index a9b34147fbb..4c4e0c96d86 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -18,6 +18,6 @@ Java framework & library support Java Standard Library,``java.*``,3,585,130,28,,,7,,,10 Java extensions,"``javax.*``, ``jakarta.*``",63,609,32,,,4,,1,1,2 `Spring `_,``org.springframework.*``,29,477,101,,,,19,14,,29 - Others,"``androidx.core.app``, ``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``kotlin``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",65,2324,950,10,,,14,18,,5 - Totals,,217,8426,1502,129,6,10,107,33,1,86 + Others,"``androidx.core.app``, ``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.hubspot.jinjava``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``kotlin``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",65,2326,972,10,,,14,18,,5 + Totals,,217,8428,1524,129,6,10,107,33,1,86 diff --git a/java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java b/java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java index 22fcbdf0011..b307fd60aa6 100644 --- a/java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java +++ b/java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java @@ -266,10 +266,7 @@ public class OdasaOutput { * Any unique suffix needed to distinguish `sym` from other declarations with the same name. * For functions for example, this means its parameter signature. */ - private TrapFileManager getMembersWriterForDecl(IrDeclaration sym, String signature) { - File trap = getTrapFileForDecl(sym, signature); - if (trap==null) - return null; + private TrapFileManager getMembersWriterForDecl(File trap, IrDeclaration sym, String signature) { TrapClassVersion currVersion = TrapClassVersion.fromSymbol(sym, log); String shortName = sym instanceof IrDeclarationWithName ? ((IrDeclarationWithName)sym).getName().asString() : "(name unknown)"; if (trap.exists()) { @@ -424,33 +421,30 @@ public class OdasaOutput { private final IrDeclaration sym; private final File trapFile; private final String signature; - private final boolean isNonSourceTrapFile; private TrapLocker(IrDeclaration decl, String signature) { this.sym = decl; this.signature = signature; if (sym==null) { - trapFile = getTrapFileForCurrentSourceFile(); + log.error("Null symbol passed for Kotlin TRAP locker"); + trapFile = null; } else { trapFile = getTrapFileForDecl(sym, signature); } - isNonSourceTrapFile = false; } private TrapLocker(File jarFile) { sym = null; signature = null; trapFile = getTrapFileForJarFile(jarFile); - isNonSourceTrapFile = true; } private TrapLocker(String moduleName) { sym = null; signature = null; trapFile = getTrapFileForModule(moduleName); - isNonSourceTrapFile = true; } public TrapFileManager getTrapFileManager() { if (trapFile!=null) { lockTrapFile(trapFile); - return getMembersWriterForDecl(sym, signature); + return getMembersWriterForDecl(trapFile, sym, signature); } else { return null; } diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 45636455806..de60f9e7487 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -101,8 +101,15 @@ open class KotlinFileExtractor( if (d.isFakeOverride) { return true } - if ((d as? IrFunction)?.descriptor?.isHiddenToOvercomeSignatureClash == true) { - return true + try { + if ((d as? IrFunction)?.descriptor?.isHiddenToOvercomeSignatureClash == true) { + return true + } + } + catch (e: NotImplementedError) { + // `org.jetbrains.kotlin.ir.descriptors.IrBasedClassConstructorDescriptor.isHiddenToOvercomeSignatureClash` throws the exception + logger.warnElement("Couldn't query if element is fake, deciding it's not.", d, e) + return false } return false } @@ -910,6 +917,9 @@ open class KotlinFileExtractor( if (f is IrSimpleFunction && f.overriddenSymbols.isNotEmpty()) { addModifiers(id, "override") } + if (f.isSuspend) { + addModifiers(id, "suspend") + } return id } @@ -1461,7 +1471,7 @@ open class KotlinFileExtractor( val (isFunctionInvoke, isBigArityFunctionInvoke) = if (drType is IrSimpleType && - drType.isFunctionOrKFunction() && + (drType.isFunctionOrKFunction() || drType.isSuspendFunctionOrKFunction()) && callTarget.name.asString() == OperatorNameConventions.INVOKE.asString()) { Pair(true, drType.arguments.size > BuiltInFunctionArity.BIG_ARITY) } else { @@ -4516,17 +4526,17 @@ open class KotlinFileExtractor( ``` */ - if (!e.argument.type.isFunctionOrKFunction()) { - logger.errorElement("Expected to find expression with function type in SAM conversion.", e) - return - } - val st = e.argument.type as? IrSimpleType if (st == null) { logger.errorElement("Expected to find a simple type in SAM conversion.", e) return } + if (!st.isFunctionOrKFunction() && !st.isSuspendFunctionOrKFunction()) { + logger.errorElement("Expected to find expression with function type in SAM conversion.", e) + return + } + // Either Function1, ... Function22 or FunctionN type, but not Function23 or above. val functionType = getFunctionalInterfaceTypeWithTypeArgs(st.arguments) if (functionType == null) { @@ -4589,6 +4599,10 @@ open class KotlinFileExtractor( // the real underlying R Function.apply(T t). forceExtractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, typeSub, classTypeArgs, ids.function, tw.getLocation(e)) + if (st.isSuspendFunctionOrKFunction()) { + addModifiers(ids.function, "suspend") + } + //body val blockId = tw.getFreshIdLabel() tw.writeStmts_block(blockId, ids.function, 0, ids.function) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/Logger.kt b/java/kotlin-extractor/src/main/kotlin/utils/Logger.kt index ca27217ac6c..43c6ee4cc10 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/Logger.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/Logger.kt @@ -248,15 +248,15 @@ open class Logger(val loggerBase: LoggerBase, open val tw: TrapWriter) { } class FileLogger(loggerBase: LoggerBase, override val tw: FileTrapWriter): Logger(loggerBase, tw) { - fun warnElement(msg: String, element: IrElement) { + fun warnElement(msg: String, element: IrElement, exn: Throwable? = null) { val locationString = tw.getLocationString(element) val mkLocationId = { tw.getLocation(element) } - loggerBase.diagnostic(tw, Severity.Warn, msg, null, locationString, mkLocationId) + loggerBase.diagnostic(tw, Severity.Warn, msg, exn?.stackTraceToString(), locationString, mkLocationId) } - fun errorElement(msg: String, element: IrElement) { + fun errorElement(msg: String, element: IrElement, exn: Throwable? = null) { val locationString = tw.getLocationString(element) val mkLocationId = { tw.getLocation(element) } - loggerBase.diagnostic(tw, Severity.Error, msg, null, locationString, mkLocationId) + loggerBase.diagnostic(tw, Severity.Error, msg, exn?.stackTraceToString(), locationString, mkLocationId) } } diff --git a/java/ql/lib/CHANGELOG.md b/java/ql/lib/CHANGELOG.md index 6409aa6a1e7..08015c8974b 100644 --- a/java/ql/lib/CHANGELOG.md +++ b/java/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.5 + ## 0.3.4 ### Deprecated APIs diff --git a/java/ql/lib/change-notes/2022-04-01-annotation-deprecations.md b/java/ql/lib/change-notes/2022-04-01-annotation-deprecations.md new file mode 100644 index 00000000000..8c8046670a1 --- /dev/null +++ b/java/ql/lib/change-notes/2022-04-01-annotation-deprecations.md @@ -0,0 +1,7 @@ +--- +category: deprecated +--- +* The predicate `Annotation.getAValue()` has been deprecated because it might lead to obtaining the value of the wrong annotation element by accident. `getValue(string)` (or one of the value type specific predicates) should be used to explicitly specify the name of the annotation element. +* The predicate `Annotation.getAValue(string)` has been renamed to `getAnArrayValue(string)`. +* The predicate `SuppressWarningsAnnotation.getASuppressedWarningLiteral()` has been deprecated because it unnecessarily restricts the result type; `getASuppressedWarning()` should be used instead. +* The predicates `TargetAnnotation.getATargetExpression()` and `RetentionAnnotation.getRetentionPolicyExpression()` have been deprecated because getting the enum constant read expression is rarely useful, instead the corresponding predicates for getting the name of the referenced enum constants should be used. diff --git a/java/ql/lib/change-notes/2022-04-01-annotation-features.md b/java/ql/lib/change-notes/2022-04-01-annotation-features.md new file mode 100644 index 00000000000..3a2d6e2561c --- /dev/null +++ b/java/ql/lib/change-notes/2022-04-01-annotation-features.md @@ -0,0 +1,9 @@ +--- +category: feature +--- +* The predicates of the CodeQL class `Annotation` have been improved: + * Convenience value type specific predicates have been added, such as `getEnumConstantValue(string)` or `getStringValue(string)`. + * Convenience predicates for elements with array values have been added, such as `getAnEnumConstantArrayValue(string)`. While the behavior of the existing predicates has not changed, usage of them should be reviewed (or replaced with the newly added predicate) to make sure they work correctly for elements with array values. + * Some internal CodeQL usage of the `Annotation` predicates has been adjusted and corrected; this might affect the results of some queries. +* New predicates have been added to the CodeQL class `Annotatable` to support getting declared and associated annotations. As part of that, `hasAnnotation()` has been changed to also consider inherited annotations, to be consistent with `hasAnnotation(string, string)` and `getAnAnnotation()`. The newly added predicate `hasDeclaredAnnotation()` can be used as replacement for the old functionality. +* New predicates have been added to the CodeQL class `AnnotationType` to simplify getting information about usage of JDK meta-annotations, such as `@Retention`. diff --git a/java/ql/lib/change-notes/released/0.3.5.md b/java/ql/lib/change-notes/released/0.3.5.md new file mode 100644 index 00000000000..88b60b4e980 --- /dev/null +++ b/java/ql/lib/change-notes/released/0.3.5.md @@ -0,0 +1 @@ +## 0.3.5 diff --git a/java/ql/lib/codeql-pack.release.yml b/java/ql/lib/codeql-pack.release.yml index 5ed15c24b9c..468917f2543 100644 --- a/java/ql/lib/codeql-pack.release.yml +++ b/java/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.4 +lastReleaseVersion: 0.3.5 diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index 00b39029b01..03b3ee513e8 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 0.3.5-dev +version: 0.3.6-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/lib/semmle/code/Location.qll b/java/ql/lib/semmle/code/Location.qll index c906b9f2407..256b831a8ad 100644 --- a/java/ql/lib/semmle/code/Location.qll +++ b/java/ql/lib/semmle/code/Location.qll @@ -216,7 +216,7 @@ private predicate fixedHasLocation(Top l, Location loc, File f) { min(Location candidateLoc | hasLocation(l, candidateLoc) | - candidateLoc order by candidateLoc.getFile().toString() + candidateLoc order by candidateLoc.getFile().getAbsolutePath() ) and not hasSourceLocation(l, _, _) and locations_default(loc, f, _, _, _, _) diff --git a/java/ql/lib/semmle/code/java/Annotation.qll b/java/ql/lib/semmle/code/java/Annotation.qll index 0b83d3b435e..28f994053a2 100644 --- a/java/ql/lib/semmle/code/java/Annotation.qll +++ b/java/ql/lib/semmle/code/java/Annotation.qll @@ -44,12 +44,100 @@ class Annotation extends @annotation, Expr { result = this.getType().getAnnotationElement(name) } - /** Gets a value of an annotation element. */ - Expr getAValue() { filteredAnnotValue(this, _, result) } + /** + * DEPRECATED: Getting the value of _any_ annotation element is error-prone because + * it could lead to selecting the value of the wrong element by accident (for example + * when an annotation type is extended in the future). Prefer the predicate `getValue(string)` + * and explicitly specify the element name. Use `getValue(_)` if it is really desired to + * get the value of any element. + * + * Gets a value of an annotation element. This includes default values in case + * no explicit value is specified. For elements with an array value type this + * might have an `ArrayInit` as result. To properly handle array values, prefer + * the predicate `getAnArrayValue`. + */ + deprecated Expr getAValue() { filteredAnnotValue(this, _, result) } - /** Gets the value of the annotation element with the specified `name`. */ + /** + * Gets the value of the annotation element with the specified `name`. + * This includes default values in case no explicit value is specified. + * For elements with an array value type this might get an `ArrayInit` instance. + * To properly handle array values, prefer the predicate `getAnArrayValue`. + */ Expr getValue(string name) { filteredAnnotValue(this, this.getAnnotationElement(name), result) } + /** + * Gets the value of the annotation element, if its type is not an array. + * This guarantees that for consistency even elements of type array with a + * single value have no result, to prevent accidental error-prone usage. + */ + private Expr getNonArrayValue(string name) { + result = this.getValue(name) and + not this.getAnnotationElement(name).getType() instanceof Array + } + + /** + * If the value type of the annotation element with the specified `name` is an enum type, + * gets the enum constant used as value for that element. This includes default values in + * case no explicit value is specified. + * + * If the element value type is an enum type array, use `getAnEnumConstantArrayValue`. + */ + EnumConstant getEnumConstantValue(string name) { + result = this.getNonArrayValue(name).(FieldRead).getField() + } + + /** + * If the value type of the annotation element with the specified `name` is `String`, + * gets the string value used for that element. This includes default values in case no + * explicit value is specified. + * + * If the element value type is a string array, use `getAStringArrayValue`. + */ + string getStringValue(string name) { + // Uses CompileTimeConstantExpr instead of StringLiteral because this can for example + // be a read from a final variable as well. + result = this.getNonArrayValue(name).(CompileTimeConstantExpr).getStringValue() + } + + /** + * If the value type of the annotation element with the specified `name` is `int` or + * a smaller integral type or `char`, gets the int value used for that element. + * This includes default values in case no explicit value is specified. + * + * If the element value type is an `int` array or an array of a smaller integral + * type or `char`, use `getAnIntArrayValue`. + */ + int getIntValue(string name) { + // Uses CompileTimeConstantExpr instead of IntegerLiteral because this can for example + // be a read from a final variable as well. + result = this.getNonArrayValue(name).(CompileTimeConstantExpr).getIntValue() and + // Verify that type is integral; ignore floating point elements with IntegerLiteral as value + this.getAnnotationElement(name).getType().hasName(["byte", "short", "int", "char"]) + } + + /** + * If the value type of the annotation element with the specified `name` is `boolean`, + * gets the boolean value used for that element. This includes default values in case + * no explicit value is specified. + */ + boolean getBooleanValue(string name) { + // Uses CompileTimeConstantExpr instead of BooleanLiteral because this can for example + // be a read from a final variable as well. + result = this.getNonArrayValue(name).(CompileTimeConstantExpr).getBooleanValue() + } + + /** + * If the value type of the annotation element with the specified `name` is `java.lang.Class`, + * gets the type referred to by that `Class`. This includes default values in case no explicit + * value is specified. + * + * If the element value type is a `Class` array, use `getATypeArrayValue`. + */ + Type getTypeValue(string name) { + result = this.getNonArrayValue(name).(TypeLiteral).getReferencedType() + } + /** Gets the element being annotated. */ Element getTarget() { result = this.getAnnotatedElement() } @@ -60,16 +148,83 @@ class Annotation extends @annotation, Expr { /** * Gets a value of the annotation element with the specified `name`, which must be declared as an array - * type. + * type. This includes default values in case no explicit value is specified. * - * If the annotation element is defined with an array initializer, then the returned value will - * be one of the elements of that array. Otherwise, the returned value will be the single - * expression defined for the value. + * If the annotation element is defined with an array initializer, then the result will be one of the + * elements of that array. Otherwise, the result will be the single expression used as value. */ - Expr getAValue(string name) { + Expr getAnArrayValue(string name) { result = this.getArrayValue(name, _) } + + /** + * DEPRECATED: Predicate has been renamed to `getAnArrayValue` + */ + deprecated Expr getAValue(string name) { result = this.getAnArrayValue(name) } + + /** + * Gets a value of the annotation element with the specified `name`, which must be declared as an enum + * type array. This includes default values in case no explicit value is specified. + * + * If the annotation element is defined with an array initializer, then the result will be one of the + * elements of that array. Otherwise, the result will be the single expression used as value. + */ + EnumConstant getAnEnumConstantArrayValue(string name) { + result = this.getAnArrayValue(name).(FieldRead).getField() + } + + /** + * Gets a value of the annotation element with the specified `name`, which must be declared as a string + * array. This includes default values in case no explicit value is specified. + * + * If the annotation element is defined with an array initializer, then the result will be one of the + * elements of that array. Otherwise, the result will be the single expression used as value. + */ + string getAStringArrayValue(string name) { + result = this.getAnArrayValue(name).(CompileTimeConstantExpr).getStringValue() + } + + /** + * Gets a value of the annotation element with the specified `name`, which must be declared as an `int` + * array or an array of a smaller integral type or `char`. This includes default values in case no + * explicit value is specified. + * + * If the annotation element is defined with an array initializer, then the result will be one of the + * elements of that array. Otherwise, the result will be the single expression used as value. + */ + int getAnIntArrayValue(string name) { + result = this.getAnArrayValue(name).(CompileTimeConstantExpr).getIntValue() and + // Verify that type is integral; ignore floating point elements with IntegerLiteral as value + this.getAnnotationElement(name).getType().hasName(["byte[]", "short[]", "int[]", "char[]"]) + } + + /** + * Gets a value of the annotation element with the specified `name`, which must be declared as a `Class` + * array. This includes default values in case no explicit value is specified. + * + * If the annotation element is defined with an array initializer, then the result will be one of the + * elements of that array. Otherwise, the result will be the single expression used as value. + */ + Type getATypeArrayValue(string name) { + result = this.getAnArrayValue(name).(TypeLiteral).getReferencedType() + } + + /** + * Gets the value at a given index of the annotation element with the specified `name`, which must be + * declared as an array type. This includes default values in case no explicit value is specified. + * + * If the annotation element is defined with an array initializer, then the result will be the element + * at the given index of that array, starting at 0. Otherwise, the result will be the single expression + * defined for the value and the `index` will be 0. + */ + Expr getArrayValue(string name, int index) { this.getType().getAnnotationElement(name).getType() instanceof Array and exists(Expr value | value = this.getValue(name) | - if value instanceof ArrayInit then result = value.(ArrayInit).getAnInit() else result = value + if value instanceof ArrayInit + then + // TODO: Currently reports incorrect index values in some cases, see https://github.com/github/codeql/issues/8645 + result = value.(ArrayInit).getInit(index) + else ( + index = 0 and result = value + ) ) } @@ -99,19 +254,86 @@ private predicate sourceAnnotValue(Annotation a, Method m, Expr val) { /** An abstract representation of language elements that can be annotated. */ class Annotatable extends Element { - /** Holds if this element has an annotation. */ - predicate hasAnnotation() { exists(Annotation a | a.getAnnotatedElement() = this) } + /** + * Holds if this element has an annotation, including inherited annotations. + * The retention policy of the annotation type is not considered. + */ + predicate hasAnnotation() { exists(this.getAnAnnotation()) } - /** Holds if this element has the specified annotation. */ + /** + * Holds if this element has a declared annotation, excluding inherited annotations. + * The retention policy of the annotation type is not considered. + */ + predicate hasDeclaredAnnotation() { exists(this.getADeclaredAnnotation()) } + + /** + * Holds if this element has the specified annotation, including inherited + * annotations. The retention policy of the annotation type is not considered. + */ predicate hasAnnotation(string package, string name) { exists(AnnotationType at | at = this.getAnAnnotation().getType() | at.nestedName() = name and at.getPackage().getName() = package ) } - /** Gets an annotation that applies to this element. */ + /** + * Gets an annotation that applies to this element, including inherited annotations. + * The results only include _direct_ annotations; _indirect_ annotations, that is + * repeated annotations in an (implicit) container annotation, are not included. + * The retention policy of the annotation type is not considered. + */ cached - Annotation getAnAnnotation() { result.getAnnotatedElement() = this } + Annotation getAnAnnotation() { + // This predicate is overridden by Class to consider inherited annotations + result = this.getADeclaredAnnotation() + } + + /** + * Gets an annotation that is declared on this element, excluding inherited annotations. + * The retention policy of the annotation type is not considered. + */ + Annotation getADeclaredAnnotation() { result.getAnnotatedElement() = this } + + /** Gets an _indirect_ (= repeated) annotation. */ + private Annotation getAnIndirectAnnotation() { + // 'indirect' as defined by https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/reflect/AnnotatedElement.html + exists(AnnotationType t, Annotation containerAnn | + t = result.getType() and + containerAnn = this.getADeclaredAnnotation() and + containerAnn.getType() = t.getContainingAnnotationType() + | + result = containerAnn.getAnArrayValue("value") + ) + } + + private Annotation getADeclaredAssociatedAnnotation(AnnotationType t) { + // Direct or indirect annotation + result.getType() = t and + result = [this.getADeclaredAnnotation(), this.getAnIndirectAnnotation()] + } + + private Annotation getAnAssociatedAnnotation(AnnotationType t) { + // 'associated' as defined by https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/reflect/AnnotatedElement.html + if exists(this.getADeclaredAssociatedAnnotation(t)) + then result = this.getADeclaredAssociatedAnnotation(t) + else ( + // Only if neither a direct nor an indirect annotation is present look for an inherited one + t.isInherited() and + // @Inherited only works for classes; cast to Annotatable is necessary because predicate is private + result = this.(Class).getASupertype().(Class).(Annotatable).getAnAssociatedAnnotation(t) + ) + } + + /** + * Gets an annotation _associated_ with this element, that is: + * - An annotation directly present on this element, or + * - An annotation indirectly present on this element (in the form of a repeated annotation), or + * - If an annotation of a type is neither directly nor indirectly present + * the result is an associated inherited annotation (recursively) + * + * The retention policy of the annotation type is not considered. + */ + Annotation getAnAssociatedAnnotation() { result = this.getAnAssociatedAnnotation(_) } /** * Holds if this or any enclosing `Annotatable` has a `@SuppressWarnings("")` @@ -128,6 +350,11 @@ class Annotatable extends Element { or this.(NestedClass).getEnclosingType().suppressesWarningsAbout(category) or + this.(LocalClassOrInterface) + .getLocalTypeDeclStmt() + .getEnclosingCallable() + .suppressesWarningsAbout(category) + or this.(LocalVariableDecl).getCallable().suppressesWarningsAbout(category) } } @@ -146,10 +373,79 @@ class AnnotationType extends Interface { /** Holds if this annotation type is annotated with the meta-annotation `@Inherited`. */ predicate isInherited() { - exists(Annotation ann | - ann.getAnnotatedElement() = this and - ann.getType().hasQualifiedName("java.lang.annotation", "Inherited") - ) + this.getADeclaredAnnotation().getType().hasQualifiedName("java.lang.annotation", "Inherited") + } + + /** Holds if this annotation type is annotated with the meta-annotation `@Documented`. */ + predicate isDocumented() { + this.getADeclaredAnnotation().getType().hasQualifiedName("java.lang.annotation", "Documented") + } + + /** + * Gets the retention policy of this annotation type, that is, the name of one of the + * enum constants of `java.lang.annotation.RetentionPolicy`. If this annotation type + * has no `@Retention` annotation, the result is `CLASS`. + */ + string getRetentionPolicy() { + if this.getADeclaredAnnotation() instanceof RetentionAnnotation + then result = this.getADeclaredAnnotation().(RetentionAnnotation).getRetentionPolicy() + else + // If not explicitly specified retention is CLASS + result = "CLASS" + } + + /** + * Holds if the element type is a possible target for this annotation type. + * The `elementType` is the name of one of the `java.lang.annotation.ElementType` + * enum constants. + * + * If this annotation type has no `@Target` annotation, it is considered to be applicable + * in all declaration contexts. This matches the behavior of the latest Java versions + * but differs from the behavior of older Java versions. This predicate must only be + * called with names of `ElementType` enum constants; for other values it might hold + * erroneously. + */ + bindingset[elementType] + predicate isATargetType(string elementType) { + /* + * Note: Cannot use a predicate with string as result because annotation type without + * explicit @Target can be applied in all declaration contexts, requiring to hardcode + * element types here; then the results could become outdated if this predicate is not + * updated for future JDK versions, or it could have irritating results, e.g. RECORD_COMPONENT + * for a database created for Java 8. + * + * Could in theory read java.lang.annotation.ElementType constants from database, but might + * be brittle in case ElementType is not present in the database for whatever reason. + */ + + if this.getADeclaredAnnotation() instanceof TargetAnnotation + then elementType = this.getADeclaredAnnotation().(TargetAnnotation).getATargetElementType() + else + /* + * Behavior for missing @Target annotation changed between Java versions. In older Java + * versions it allowed usage in most (but not all) declaration contexts. Then for Java 14 + * JDK-8231435 changed it to allow usage in all declaration and type contexts. In Java 17 + * it was changed by JDK-8261610 to only allow usage in all declaration contexts, but not + * in type contexts anymore. However, during these changes javac did not always comply with + * the specification, see for example JDK-8254023. + * + * For simplicity pretend the latest behavior defined by the JLS applied in all versions; + * that means any declaration context is allowed, but type contexts (represented by TYPE_USE, + * see JLS 17 section 9.6.4.1) are not allowed. + */ + + elementType != "TYPE_USE" + } + + /** Holds if this annotation type is annotated with the meta-annotation `@Repeatable`. */ + predicate isRepeatable() { this.getADeclaredAnnotation() instanceof RepeatableAnnotation } + + /** + * If this annotation type is annotated with the meta-annotation `@Repeatable`, + * gets the annotation type which acts as _containing annotation type_. + */ + AnnotationType getContainingAnnotationType() { + result = this.getADeclaredAnnotation().(RepeatableAnnotation).getContainingType() } } diff --git a/java/ql/lib/semmle/code/java/Dependency.qll b/java/ql/lib/semmle/code/java/Dependency.qll index a2bd8a84fdc..17236c6d05e 100644 --- a/java/ql/lib/semmle/code/java/Dependency.qll +++ b/java/ql/lib/semmle/code/java/Dependency.qll @@ -71,7 +71,8 @@ predicate depends(RefType t, RefType dep) { a.getAnnotatedElement().(Member).getDeclaringType() = t | usesType(a.getType(), dep) or - usesType(a.getAValue().getType(), dep) + usesType(a.getValue(_).getType(), dep) or + usesType(a.getAnArrayValue(_).getType(), dep) ) or // the type accessed in an `instanceof` expression in `t`. diff --git a/java/ql/lib/semmle/code/java/DependencyCounts.qll b/java/ql/lib/semmle/code/java/DependencyCounts.qll index b775e5fcf06..1010be48055 100644 --- a/java/ql/lib/semmle/code/java/DependencyCounts.qll +++ b/java/ql/lib/semmle/code/java/DependencyCounts.qll @@ -90,7 +90,7 @@ predicate numDepends(RefType t, RefType dep, int value) { | elem = a and usesType(a.getType(), dep) or - elem = a.getAValue() and + elem = [a.getValue(_), a.getAnArrayValue(_)] and elem.getFile().getExtension() = "java" and usesType(elem.(Expr).getType(), dep) ) diff --git a/java/ql/lib/semmle/code/java/JDKAnnotations.qll b/java/ql/lib/semmle/code/java/JDKAnnotations.qll index 2dff70c4d8e..502aef09075 100644 --- a/java/ql/lib/semmle/code/java/JDKAnnotations.qll +++ b/java/ql/lib/semmle/code/java/JDKAnnotations.qll @@ -18,14 +18,16 @@ class OverrideAnnotation extends Annotation { class SuppressWarningsAnnotation extends Annotation { SuppressWarningsAnnotation() { this.getType().hasQualifiedName("java.lang", "SuppressWarnings") } - /** Gets the `StringLiteral` of a warning suppressed by this annotation. */ - StringLiteral getASuppressedWarningLiteral() { - result = this.getAValue() or - result = this.getAValue().(ArrayInit).getAnInit() - } + /** + * DEPRECATED: This predicate restricts the results to `StringLiteral`; prefer `getASuppressedWarning()` + * to get the name of a suppressed warning. + * + * Gets the `StringLiteral` of a warning suppressed by this annotation. + */ + deprecated StringLiteral getASuppressedWarningLiteral() { result = this.getAnArrayValue("value") } /** Gets the name of a warning suppressed by this annotation. */ - string getASuppressedWarning() { result = this.getASuppressedWarningLiteral().getValue() } + string getASuppressedWarning() { result = this.getAStringArrayValue("value") } } /** A `@Target` annotation. */ @@ -33,18 +35,15 @@ class TargetAnnotation extends Annotation { TargetAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Target") } /** + * DEPRECATED: Getting the field access expression is rarely useful. Use `getATargetElementType()` + * to get the name of the target element. + * * Gets a target expression within this annotation. * * For example, the field access `ElementType.FIELD` is a target expression in * `@Target({ElementType.FIELD, ElementType.METHOD})`. */ - Expr getATargetExpression() { - not result instanceof ArrayInit and - ( - result = this.getAValue() or - result = this.getAValue().(ArrayInit).getAnInit() - ) - } + deprecated Expr getATargetExpression() { result = this.getAnArrayValue("value") } /** * Gets the name of a target element type. @@ -52,14 +51,7 @@ class TargetAnnotation extends Annotation { * For example, `METHOD` is the name of a target element type in * `@Target({ElementType.FIELD, ElementType.METHOD})`. */ - string getATargetElementType() { - exists(EnumConstant ec | - ec = this.getATargetExpression().(VarAccess).getVariable() and - ec.getDeclaringType().hasQualifiedName("java.lang.annotation", "ElementType") - | - result = ec.getName() - ) - } + string getATargetElementType() { result = this.getAnEnumConstantArrayValue("value").getName() } } /** A `@Retention` annotation. */ @@ -67,12 +59,15 @@ class RetentionAnnotation extends Annotation { RetentionAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Retention") } /** + * DEPRECATED: Getting the field access expression is rarely useful. Use `getRetentionPolicy()` + * to get the name of the retention policy. + * * Gets the retention policy expression within this annotation. * * For example, the field access `RetentionPolicy.RUNTIME` is the * retention policy expression in `@Retention(RetentionPolicy.RUNTIME)`. */ - Expr getRetentionPolicyExpression() { result = this.getValue("value") } + deprecated Expr getRetentionPolicyExpression() { result = this.getValue("value") } /** * Gets the name of the retention policy of this annotation. @@ -80,14 +75,18 @@ class RetentionAnnotation extends Annotation { * For example, `RUNTIME` is the name of the retention policy * in `@Retention(RetentionPolicy.RUNTIME)`. */ - string getRetentionPolicy() { - exists(EnumConstant ec | - ec = this.getRetentionPolicyExpression().(VarAccess).getVariable() and - ec.getDeclaringType().hasQualifiedName("java.lang.annotation", "RetentionPolicy") - | - result = ec.getName() - ) - } + string getRetentionPolicy() { result = this.getEnumConstantValue("value").getName() } +} + +/** A `@Repeatable` annotation. */ +class RepeatableAnnotation extends Annotation { + RepeatableAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Repeatable") } + + /** + * Gets the annotation type which acts as _containing type_, grouping multiple + * repeatable annotations together. + */ + AnnotationType getContainingType() { result = this.getTypeValue("value") } } /** @@ -119,11 +118,7 @@ abstract class NonReflectiveAnnotation extends Annotation { } library class StandardNonReflectiveAnnotation extends NonReflectiveAnnotation { StandardNonReflectiveAnnotation() { - exists(AnnotationType anntp | anntp = this.getType() | - anntp.hasQualifiedName("java.lang", "Override") or - anntp.hasQualifiedName("java.lang", "Deprecated") or - anntp.hasQualifiedName("java.lang", "SuppressWarnings") or - anntp.hasQualifiedName("java.lang", "SafeVarargs") - ) + this.getType() + .hasQualifiedName("java.lang", ["Override", "Deprecated", "SuppressWarnings", "SafeVarargs"]) } } diff --git a/java/ql/lib/semmle/code/java/Modifier.qll b/java/ql/lib/semmle/code/java/Modifier.qll index 3d03851fcf5..3f69550d44b 100644 --- a/java/ql/lib/semmle/code/java/Modifier.qll +++ b/java/ql/lib/semmle/code/java/Modifier.qll @@ -67,6 +67,9 @@ abstract class Modifiable extends Element { /** Holds if this element has an `inline` modifier. */ predicate isInline() { this.hasModifier("inline") } + /** Holds if this element has a `suspend` modifier. */ + predicate isSuspend() { this.hasModifier("suspend") } + /** Holds if this element has a `volatile` modifier. */ predicate isVolatile() { this.hasModifier("volatile") } diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index 9d88550faa3..b2937d67940 100644 --- a/java/ql/lib/semmle/code/java/PrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrintAst.qll @@ -120,7 +120,7 @@ private newtype TPrintAstNode = shouldPrint(lvde, _) and lvde.getParent() instanceof SingleLocalVarDeclParent } or TAnnotationsNode(Annotatable ann) { - shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann) + shouldPrint(ann, _) and ann.hasDeclaredAnnotation() and not partOfAnnotation(ann) } or TParametersNode(Callable c) { shouldPrint(c, _) and not c.hasNoParameters() } or TBaseTypesNode(ClassOrInterface ty) { shouldPrint(ty, _) } or diff --git a/java/ql/lib/semmle/code/java/UnitTests.qll b/java/ql/lib/semmle/code/java/UnitTests.qll index e56b9a6dc23..38f37fa4ff0 100644 --- a/java/ql/lib/semmle/code/java/UnitTests.qll +++ b/java/ql/lib/semmle/code/java/UnitTests.qll @@ -161,15 +161,13 @@ class TestNGTestMethod extends Method { exists(TestNGTestAnnotation testAnnotation | testAnnotation = this.getAnAnnotation() and // The data provider must have the same name as the referenced data provider - result.getDataProviderName() = - testAnnotation.getValue("dataProvider").(StringLiteral).getValue() + result.getDataProviderName() = testAnnotation.getStringValue("dataProvider") | // Either the data provider should be on the current class, or a supertype this.getDeclaringType().getAnAncestor() = result.getDeclaringType() or // Or the data provider class should be declared - result.getDeclaringType() = - testAnnotation.getValue("dataProviderClass").(TypeLiteral).getReferencedType() + result.getDeclaringType() = testAnnotation.getTypeValue("dataProviderClass") ) } } @@ -227,9 +225,7 @@ class TestNGListenersAnnotation extends TestNGAnnotation { /** * Gets a listener defined in this annotation. */ - TestNGListenerImpl getAListener() { - result = this.getAValue("value").(TypeLiteral).getReferencedType() - } + TestNGListenerImpl getAListener() { result = this.getATypeArrayValue("value") } } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index 6ee18ccb9cf..5dada4f8532 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -117,6 +117,7 @@ private module Frameworks { private import semmle.code.java.frameworks.Retrofit private import semmle.code.java.frameworks.Stream private import semmle.code.java.frameworks.Strings + private import semmle.code.java.frameworks.Thymeleaf private import semmle.code.java.frameworks.ratpack.Ratpack private import semmle.code.java.frameworks.ratpack.RatpackExec private import semmle.code.java.frameworks.spring.SpringCache @@ -141,6 +142,7 @@ private module Frameworks { private import semmle.code.java.security.LdapInjection private import semmle.code.java.security.MvelInjection private import semmle.code.java.security.OgnlInjection + private import semmle.code.java.security.TemplateInjection private import semmle.code.java.security.XPath private import semmle.code.java.security.XsltInjection private import semmle.code.java.frameworks.Jdbc @@ -625,7 +627,7 @@ module CsvValidation { "open-url", "jndi-injection", "ldap", "sql", "jdbc-url", "logging", "mvel", "xpath", "groovy", "xss", "ognl-injection", "intent-start", "pending-intent-sent", "url-open-stream", "url-redirect", "create-file", "write-file", "set-hostname-verifier", - "header-splitting", "information-leak", "xslt", "jexl", "bean-validation" + "header-splitting", "information-leak", "xslt", "jexl", "bean-validation", "ssti" ] and not kind.matches("regex-use%") and not kind.matches("qltest%") and diff --git a/java/ql/lib/semmle/code/java/frameworks/JAXB.qll b/java/ql/lib/semmle/code/java/frameworks/JAXB.qll index 8fe204ad846..c9c9aee71b5 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JAXB.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JAXB.qll @@ -60,7 +60,7 @@ class JaxbType extends Class { this.getAnAnnotation() = a and a.getType().(JaxbAnnotationType).hasName("XmlAccessorType") | - result.getAnAccess() = a.getValue("value") + result = a.getEnumConstantValue("value") ) } diff --git a/java/ql/lib/semmle/code/java/frameworks/JUnitAnnotations.qll b/java/ql/lib/semmle/code/java/frameworks/JUnitAnnotations.qll index 8716f7d625c..d74fe683f06 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JUnitAnnotations.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JUnitAnnotations.qll @@ -64,5 +64,5 @@ class RunWithAnnotation extends Annotation { /** * Gets the runner that will be used. */ - Type getRunner() { result = this.getValue("value").(TypeLiteral).getReferencedType() } + Type getRunner() { result = this.getTypeValue("value") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll b/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll index ab83bab8049..c60c3ff0369 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll @@ -296,11 +296,7 @@ class JaxRSProducesAnnotation extends JaxRSAnnotation { /** * Gets a declared content type that can be produced by this resource. */ - Expr getADeclaredContentTypeExpr() { - result = this.getAValue() and not result instanceof ArrayInit - or - result = this.getAValue().(ArrayInit).getAnInit() - } + Expr getADeclaredContentTypeExpr() { result = this.getAnArrayValue("value") } } /** An `@Consumes` annotation that describes content types can be consumed by this resource. */ diff --git a/java/ql/lib/semmle/code/java/frameworks/MyBatis.qll b/java/ql/lib/semmle/code/java/frameworks/MyBatis.qll index 19744ca2c68..6c16bb168bb 100644 --- a/java/ql/lib/semmle/code/java/frameworks/MyBatis.qll +++ b/java/ql/lib/semmle/code/java/frameworks/MyBatis.qll @@ -85,9 +85,7 @@ class IbatisSqlOperationAnnotation extends Annotation { /** * Gets this annotation's SQL statement string. */ - string getSqlValue() { - result = this.getAValue("value").(CompileTimeConstantExpr).getStringValue() - } + string getSqlValue() { result = this.getAStringArrayValue("value") } } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/Thymeleaf.qll b/java/ql/lib/semmle/code/java/frameworks/Thymeleaf.qll new file mode 100644 index 00000000000..3c550d5441c --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/Thymeleaf.qll @@ -0,0 +1,16 @@ +/** + * Provides classes and predicates for working with the Thymeleaf template engine. + */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +private class ThymeleafSummaryModels extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.thymeleaf;TemplateSpec;false;TemplateSpec;;;Argument[0];Argument[-1];taint;manual", + "org.thymeleaf;TemplateSpec;false;getTemplate;;;Argument[-1];ReturnValue;taint;manual", + ] + } +} 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 82569754394..e60659426e5 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/Persistence.qll @@ -33,12 +33,12 @@ class PersistentEntity extends RefType { } /** - * Gets the access type for this entity as defined by a `@javax.persistence.Access` annotation, if any. + * Gets the access type for this entity as defined by a `@javax.persistence.Access` annotation, + * if any, in lower case. */ string getAccessTypeFromAnnotation() { exists(AccessAnnotation accessType | accessType = this.getAnAnnotation() | - result = - accessType.getValue("value").(FieldRead).getField().(EnumConstant).getName().toLowerCase() + result = accessType.getEnumConstantValue("value").getName().toLowerCase() ) } } 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 b99dafecc65..1dd6dfd292f 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll @@ -311,9 +311,7 @@ class SpringQualifierDefinitionAnnotation extends Annotation { /** * Gets the value of the qualifier field for this qualifier. */ - string getQualifierValue() { - result = this.getValue("value").(CompileTimeConstantExpr).getStringValue() - } + string getQualifierValue() { result = this.getStringValue("value") } } /** @@ -325,9 +323,7 @@ class SpringQualifierAnnotation extends Annotation { /** * Gets the value of the qualifier field for this qualifier. */ - string getQualifierValue() { - result = this.getValue("value").(CompileTimeConstantExpr).getStringValue() - } + string getQualifierValue() { result = this.getStringValue("value") } /** * Gets the bean definition in an XML file that this qualifier resolves to, if any. @@ -350,9 +346,7 @@ class SpringResourceAnnotation extends Annotation { /** * Gets the specified name value, if any. */ - string getNameValue() { - result = this.getValue("name").(CompileTimeConstantExpr).getStringValue() - } + string getNameValue() { result = this.getStringValue("name") } /** * Gets the bean definition in an XML file that the resource resolves to, if any. diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringComponentScan.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringComponentScan.qll index 1c037adefd6..f3380c45458 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringComponentScan.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringComponentScan.qll @@ -40,16 +40,10 @@ class SpringComponentScan extends Annotation { */ string getBasePackages() { // "value" and "basePackages" are synonymous, and are simple strings - result = this.getAValue("basePackages").(StringLiteral).getValue() + result = this.getAStringArrayValue(["basePackages", "value"]) or - result = this.getAValue("value").(StringLiteral).getValue() - or - exists(TypeLiteral typeLiteral | - // Base package classes are type literals whose package should be considered a base package. - typeLiteral = this.getAValue("basePackageClasses") - | - result = typeLiteral.getReferencedType().(RefType).getPackage().getName() - ) + // Base package classes are type literals whose package should be considered a base package. + result = this.getATypeArrayValue("basePackageClasses").(RefType).getPackage().getName() } } @@ -144,8 +138,7 @@ class SpringComponent extends RefType { if exists(this.getComponentAnnotation().getValue("value")) then // If the name has been specified in the component annotation, use that. - result = - this.getComponentAnnotation().getValue("value").(CompileTimeConstantExpr).getStringValue() + result = this.getComponentAnnotation().getStringValue("value") else // Otherwise use the name of the class, with the initial letter lower cased. exists(string name | name = this.getName() | @@ -204,7 +197,7 @@ class SpringComponent extends RefType { .getType() .hasQualifiedName("org.springframework.context.annotation", "Profile") | - result = profileAnnotation.getAValue("value").(StringLiteral).getValue() + result = profileAnnotation.getAStringArrayValue("value") ) } } 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 53829d02752..d40d1608969 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -154,9 +154,7 @@ class SpringRequestMappingMethod extends SpringControllerMethod { } /** Gets the "value" @RequestMapping annotation value, if present. */ - string getValue() { - result = requestMappingAnnotation.getValue("value").(CompileTimeConstantExpr).getStringValue() - } + string getValue() { result = requestMappingAnnotation.getStringValue("value") } /** Holds if this is considered an `@ResponseBody` method. */ predicate isResponseBody() { diff --git a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsAnnotations.qll b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsAnnotations.qll index 27ada4d6ff0..d97415354b3 100644 --- a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsAnnotations.qll +++ b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsAnnotations.qll @@ -34,5 +34,5 @@ class StrutsActionsAnnotation extends StrutsAnnotation { /** * Gets an Action annotation contained in this Actions annotation. */ - StrutsActionAnnotation getAnAction() { result = this.getAValue("value") } + StrutsActionAnnotation getAnAction() { result = this.getAnArrayValue("value") } } diff --git a/java/ql/lib/semmle/code/java/security/TemplateInjection.qll b/java/ql/lib/semmle/code/java/security/TemplateInjection.qll new file mode 100644 index 00000000000..079ef551bb3 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/TemplateInjection.qll @@ -0,0 +1,108 @@ +/** Definitions related to the server-side template injection (SST) query. */ + +import java +private import semmle.code.java.dataflow.FlowSources +private import semmle.code.java.dataflow.ExternalFlow +private import semmle.code.java.dataflow.TaintTracking + +/** + * A source for server-side template injection (SST) vulnerabilities. + */ +abstract class TemplateInjectionSource extends DataFlow::Node { + /** Holds if this source has the specified `state`. */ + predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty } +} + +/** + * A sink for server-side template injection (SST) vulnerabilities. + */ +abstract class TemplateInjectionSink extends DataFlow::Node { + /** Holds if this sink has the specified `state`. */ + predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty } +} + +/** + * A unit class for adding additional taint steps. + * + * Extend this class to add additional taint steps that should apply to flows related to + * server-side template injection (SST) vulnerabilities. + */ +class TemplateInjectionAdditionalTaintStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a taint + * step for flows related to server-side template injection (SST) vulnerabilities. + */ + predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } + + /** + * Holds if the step from `node1` to `node2` should be considered a taint + * step for flows related toserver-side template injection (SST) vulnerabilities. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalTaintStep( + DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, + DataFlow::FlowState state2 + ) { + none() + } +} + +/** + * A sanitizer for server-side template injection (SST) vulnerabilities. + */ +abstract class TemplateInjectionSanitizer extends DataFlow::Node { } + +/** + * A sanitizer for server-side template injection (SST) vulnerabilities. + * This sanitizer is only applicable when `TemplateInjectionSanitizerWithState::hasState` + * holds for the flow state. + */ +abstract class TemplateInjectionSanitizerWithState extends DataFlow::Node { + /** Holds if this sanitizer has the specified `state`. */ + abstract predicate hasState(DataFlow::FlowState state); +} + +private class DefaultTemplateInjectionSource extends TemplateInjectionSource instanceof RemoteFlowSource { +} + +private class DefaultTemplateInjectionSink extends TemplateInjectionSink { + DefaultTemplateInjectionSink() { sinkNode(this, "ssti") } +} + +private class DefaultTemplateInjectionSanitizer extends TemplateInjectionSanitizer { + DefaultTemplateInjectionSanitizer() { + this.getType() instanceof PrimitiveType or + this.getType() instanceof BoxedType or + this.getType() instanceof NumericType + } +} + +private class TemplateInjectionSinkModels extends SinkModelCsv { + override predicate row(string row) { + row = + [ + "freemarker.template;Template;true;Template;(String,Reader);;Argument[1];ssti;manual", + "freemarker.template;Template;true;Template;(String,Reader,Configuration);;Argument[1];ssti;manual", + "freemarker.template;Template;true;Template;(String,Reader,Configuration,String);;Argument[1];ssti;manual", + "freemarker.template;Template;true;Template;(String,String,Reader,Configuration);;Argument[2];ssti;manual", + "freemarker.template;Template;true;Template;(String,String,Reader,Configuration,String);;Argument[2];ssti;manual", + "freemarker.template;Template;true;Template;(String,String,Reader,Configuration,ParserConfiguration,String);;Argument[2];ssti;manual", + "freemarker.template;Template;true;Template;(String,String,Configuration);;Argument[1];ssti;manual", + "freemarker.cache;StringTemplateLoader;true;putTemplate;;;Argument[1];ssti;manual", + "com.mitchellbosecke.pebble;PebbleEngine;true;getTemplate;;;Argument[0];ssti;manual", + "com.mitchellbosecke.pebble;PebbleEngine;true;getLiteralTemplate;;;Argument[0];ssti;manual", + "com.hubspot.jinjava;Jinjava;true;renderForResult;;;Argument[0];ssti;manual", + "com.hubspot.jinjava;Jinjava;true;render;;;Argument[0];ssti;manual", + "org.thymeleaf;ITemplateEngine;true;process;;;Argument[0];ssti;manual", + "org.thymeleaf;ITemplateEngine;true;processThrottled;;;Argument[0];ssti;manual", + "org.apache.velocity.app;Velocity;true;evaluate;;;Argument[3];ssti;manual", + "org.apache.velocity.app;Velocity;true;mergeTemplate;;;Argument[2];ssti;manual", + "org.apache.velocity.app;VelocityEngine;true;evaluate;;;Argument[3];ssti;manual", + "org.apache.velocity.app;VelocityEngine;true;mergeTemplate;;;Argument[2];ssti;manual", + "org.apache.velocity.runtime.resource.util;StringResourceRepository;true;putStringResource;;;Argument[1];ssti;manual", + "org.apache.velocity.runtime;RuntimeServices;true;evaluate;;;Argument[3];ssti;manual", + "org.apache.velocity.runtime;RuntimeServices;true;parse;;;Argument[0];ssti;manual", + "org.apache.velocity.runtime;RuntimeSingleton;true;parse;;;Argument[0];ssti;manual" + ] + } +} diff --git a/java/ql/lib/semmle/code/java/security/TemplateInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/TemplateInjectionQuery.qll new file mode 100644 index 00000000000..e8ed6f5aea9 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/TemplateInjectionQuery.qll @@ -0,0 +1,38 @@ +/** Provides a taint tracking configuration for server-side template injection (SST) vulnerabilities */ + +import java +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.security.TemplateInjection + +/** A taint tracking configuration to reason about server-side template injection (SST) vulnerabilities */ +class TemplateInjectionFlowConfig extends TaintTracking::Configuration { + TemplateInjectionFlowConfig() { this = "TemplateInjectionFlowConfig" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + source.(TemplateInjectionSource).hasState(state) + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + sink.(TemplateInjectionSink).hasState(state) + } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer instanceof TemplateInjectionSanitizer + } + + override predicate isSanitizer(DataFlow::Node sanitizer, DataFlow::FlowState state) { + sanitizer.(TemplateInjectionSanitizerWithState).hasState(state) + } + + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + any(TemplateInjectionAdditionalTaintStep a).isAdditionalTaintStep(node1, node2) + } + + override predicate isAdditionalTaintStep( + DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, + DataFlow::FlowState state2 + ) { + any(TemplateInjectionAdditionalTaintStep a).isAdditionalTaintStep(node1, state1, node2, state2) + } +} diff --git a/java/ql/src/AlertSuppressionAnnotations.ql b/java/ql/src/AlertSuppressionAnnotations.ql index aa9fd275ad1..7f0ee74a0d8 100644 --- a/java/ql/src/AlertSuppressionAnnotations.ql +++ b/java/ql/src/AlertSuppressionAnnotations.ql @@ -23,7 +23,7 @@ class SuppressionAnnotation extends SuppressWarningsAnnotation { string text; SuppressionAnnotation() { - text = this.getASuppressedWarningLiteral().getValue() and + text = this.getASuppressedWarning() and exists(getAnnotationText(text)) } diff --git a/java/ql/src/CHANGELOG.md b/java/ql/src/CHANGELOG.md index 7a2df51efce..add95173a56 100644 --- a/java/ql/src/CHANGELOG.md +++ b/java/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.4 + ## 0.3.3 ### New Queries diff --git a/java/ql/src/Likely Bugs/Reflection/AnnotationPresentCheck.ql b/java/ql/src/Likely Bugs/Reflection/AnnotationPresentCheck.ql index 22729eebd66..2bffa1ea4f4 100644 --- a/java/ql/src/Likely Bugs/Reflection/AnnotationPresentCheck.ql +++ b/java/ql/src/Likely Bugs/Reflection/AnnotationPresentCheck.ql @@ -19,8 +19,5 @@ where m.getNumberOfParameters() = 1 and c.getArgument(0).getType() = p and p.getATypeArgument() = t and - not exists(RetentionAnnotation a | - t.getAnAnnotation() = a and - a.getAValue().(VarAccess).getVariable().hasName("RUNTIME") - ) + t.getRetentionPolicy() != "RUNTIME" select c, "Call to isAnnotationPresent where no annotation has the RUNTIME retention policy." diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SSTIBad.java b/java/ql/src/Security/CWE/CWE-094/SSTIBad.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-094/SSTIBad.java rename to java/ql/src/Security/CWE/CWE-094/SSTIBad.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SSTIGood.java b/java/ql/src/Security/CWE/CWE-094/SSTIGood.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-094/SSTIGood.java rename to java/ql/src/Security/CWE/CWE-094/SSTIGood.java diff --git a/java/ql/src/Security/CWE/CWE-094/TemplateInjection.qhelp b/java/ql/src/Security/CWE/CWE-094/TemplateInjection.qhelp new file mode 100644 index 00000000000..c14fa5784de --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-094/TemplateInjection.qhelp @@ -0,0 +1,32 @@ + + + +

    +Template injection occurs when user input is embedded in a template's code in an unsafe manner. +An attacker can use native template syntax to inject a malicious payload into a template, which is then executed server-side. +This permits the attacker to run arbitrary code in the server's context. +

    +
    + +

    +To fix this, ensure that untrusted input is not used as part of a template's code. If the application requirements do not allow this, +use a sandboxed environment where access to unsafe attributes and methods is prohibited. +

    +
    + +

    +In the example given below, an untrusted HTTP parameter code is used as a Velocity template string. +This can lead to remote code execution. +

    + + +

    +In the next example, the problem is avoided by using a fixed template string s. +Since the template's code is not attacker-controlled in this case, this solution prevents the execution of untrusted code. +

    + +
    + +
  • Portswigger: Server Side Template Injection.
  • +
    +
    \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql b/java/ql/src/Security/CWE/CWE-094/TemplateInjection.ql similarity index 66% rename from java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql rename to java/ql/src/Security/CWE/CWE-094/TemplateInjection.ql index 18e47d2c6b3..6ddd8cfd2c9 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql +++ b/java/ql/src/Security/CWE/CWE-094/TemplateInjection.ql @@ -1,16 +1,18 @@ /** - * @name Server Side Template Injection - * @description Untrusted input used as a template parameter can lead to remote code execution. + * @name Server-side template injection + * @description Untrusted input interpreted as a template can lead to remote code execution. * @kind path-problem * @problem.severity error + * @security-severity 9.3 * @precision high * @id java/server-side-template-injection * @tags security + * external/cwe/cwe-1336 * external/cwe/cwe-094 */ import java -import TemplateInjection +import semmle.code.java.security.TemplateInjectionQuery import DataFlow::PathGraph from TemplateInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/java/ql/src/change-notes/2022-09-08-server-side-template-injection-query.md b/java/ql/src/change-notes/2022-09-08-server-side-template-injection-query.md new file mode 100644 index 00000000000..a62dc864f44 --- /dev/null +++ b/java/ql/src/change-notes/2022-09-08-server-side-template-injection-query.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* The query "Server-side template injection" (`java/server-side-template-injection`) has been promoted from experimental to the main query pack. This query was originally [submitted as an experimental query by @porcupineyhairs](https://github.com/github/codeql/pull/5935). \ No newline at end of file diff --git a/java/ql/src/change-notes/released/0.3.4.md b/java/ql/src/change-notes/released/0.3.4.md new file mode 100644 index 00000000000..d62a8a1780d --- /dev/null +++ b/java/ql/src/change-notes/released/0.3.4.md @@ -0,0 +1 @@ +## 0.3.4 diff --git a/java/ql/src/codeql-pack.release.yml b/java/ql/src/codeql-pack.release.yml index 9da182d3394..5ed15c24b9c 100644 --- a/java/ql/src/codeql-pack.release.yml +++ b/java/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.3 +lastReleaseVersion: 0.3.4 diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp deleted file mode 100644 index 882e9cecab1..00000000000 --- a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp +++ /dev/null @@ -1,31 +0,0 @@ - - - -

    - Template Injection occurs when user input is embedded in a template in an unsafe manner. - An attacker can use native template syntax to inject a malicious payload into a template, which is then executed server-side. This permits the attacker to run arbitrary code in the server's context.

    -
    - -

    - To fix this, ensure that an untrusted value is not used as a template. If the application requirements do not allow this, use a sandboxed environment where access to unsafe attributes and methods is prohibited. -

    -
    - -

    - In the example given below, an untrusted HTTP parameter - code - is used as a Velocity template string. This can lead to remote code execution. -

    - - -

    - In the next example the problem is avoided by using a fixed template string - s - . Since, the template is not attacker controlled in this case, we prevent untrusted code execution. -

    - -
    - -
  • Portswigger : [Server Side Template Injection](https://portswigger.net/web-security/server-side-template-injection)
  • -
    -
    \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qll b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qll deleted file mode 100644 index 2f3113123aa..00000000000 --- a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qll +++ /dev/null @@ -1,209 +0,0 @@ -/** Definitions related to the Server Side Template Injection (SSTI) query. */ - -import java -import semmle.code.java.dataflow.TaintTracking -import semmle.code.java.dataflow.FlowSources -import experimental.semmle.code.java.frameworks.FreeMarker -import experimental.semmle.code.java.frameworks.Velocity -import experimental.semmle.code.java.frameworks.JinJava -import experimental.semmle.code.java.frameworks.Pebble -import experimental.semmle.code.java.frameworks.Thymeleaf - -/** A taint tracking configuration to reason about Server Side Template Injection (SSTI) vulnerabilities */ -class TemplateInjectionFlowConfig extends TaintTracking::Configuration { - TemplateInjectionFlowConfig() { this = "TemplateInjectionFlowConfig" } - - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType - } - - override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) { - exists(AdditionalFlowStep a | a.isAdditionalTaintStep(prev, succ)) - } -} - -/** - * A data flow sink for Server Side Template Injection (SSTI) vulnerabilities - */ -abstract private class Sink extends DataFlow::ExprNode { } - -/** - * A data flow step for Server Side Template Injection (SSTI) vulnerabilities - */ -private class AdditionalFlowStep extends Unit { - abstract predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ); -} - -/** - * An argument to FreeMarker template engine's `process` method call. - */ -private class FreeMarkerProcessSink extends Sink { - FreeMarkerProcessSink() { - exists(MethodAccess m | - m.getCallee() instanceof MethodFreeMarkerTemplateProcess and - m.getArgument(0) = this.getExpr() - ) - } -} - -/** - * An reader passed an argument to FreeMarker template engine's `Template` - * construtor call. - */ -private class FreeMarkerConstructorSink extends Sink { - FreeMarkerConstructorSink() { - // Template(java.lang.String name, java.io.Reader reader) - // Template(java.lang.String name, java.io.Reader reader, Configuration cfg) - // Template(java.lang.String name, java.io.Reader reader, Configuration cfg, java.lang.String encoding) - // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader reader, Configuration cfg) - // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader reader, Configuration cfg, ParserConfiguration customParserConfiguration, java.lang.String encoding) - // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader reader, Configuration cfg, java.lang.String encoding) - exists(ConstructorCall cc, Expr e | - cc.getConstructor().getDeclaringType() instanceof TypeFreeMarkerTemplate and - e = cc.getAnArgument() and - ( - e.getType().(RefType).hasQualifiedName("java.io", "Reader") and - this.asExpr() = e - ) - ) - or - exists(ConstructorCall cc | - cc.getConstructor().getDeclaringType() instanceof TypeFreeMarkerTemplate and - // Template(java.lang.String name, java.lang.String sourceCode, Configuration cfg) - cc.getNumArgument() = 3 and - cc.getArgument(1).getType() instanceof TypeString and - this.asExpr() = cc.getArgument(1) - ) - } -} - -/** - * An argument to FreeMarker template engine's `putTemplate` method call. - */ -private class FreeMarkerStringTemplateLoaderPutTemplateSink extends Sink { - FreeMarkerStringTemplateLoaderPutTemplateSink() { - exists(MethodAccess ma | - this.asExpr() = ma.getArgument(1) and - ma.getMethod() instanceof MethodFreeMarkerStringTemplateLoaderPutTemplate - ) - } -} - -/** - * An argument to Pebble template engine's `getLiteralTemplate` or `getTemplate` method call. - */ -private class PebbleGetTemplateSinkTemplateSink extends Sink { - PebbleGetTemplateSinkTemplateSink() { - exists(MethodAccess ma | - this.asExpr() = ma.getArgument(0) and - ma.getMethod() instanceof MethodPebbleGetTemplate - ) - } -} - -/** - * An argument to JinJava template engine's `render` or `renderForResult` method call. - */ -private class JinjavaRenderSink extends Sink { - JinjavaRenderSink() { - exists(MethodAccess ma | - this.asExpr() = ma.getArgument(0) and - ( - ma.getMethod() instanceof MethodJinjavaRenderForResult - or - ma.getMethod() instanceof MethodJinjavaRender - ) - ) - } -} - -/** - * An argument to ThymeLeaf template engine's `process` method call. - */ -private class ThymeLeafRenderSink extends Sink { - ThymeLeafRenderSink() { - exists(MethodAccess ma | - this.asExpr() = ma.getArgument(0) and - ma.getMethod() instanceof MethodThymeleafProcess - ) - } -} - -/** - * Tainted data flowing into a Velocity Context through `put` method taints the context. - */ -private class VelocityContextFlow extends AdditionalFlowStep { - override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) { - exists(MethodAccess m | m.getMethod() instanceof MethodVelocityContextPut | - m.getArgument(1) = prev.asExpr() and - succ.asExpr() = m.getQualifier() - ) - } -} - -/** - * An argument to Velocity template engine's `mergeTemplate` method call. - */ -private class VelocityMergeTempSink extends Sink { - VelocityMergeTempSink() { - exists(MethodAccess m | - // static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer) - m.getCallee() instanceof MethodVelocityMergeTemplate and - m.getArgument(2) = this.getExpr() - ) - } -} - -/** - * An argument to Velocity template engine's `mergeTemplate` method call. - */ -private class VelocityMergeSink extends Sink { - VelocityMergeSink() { - exists(MethodAccess m | - m.getCallee() instanceof MethodVelocityMerge and - // public void merge(Context context, Writer writer) - // public void merge(Context context, Writer writer, List macroLibraries) - m.getArgument(0) = this.getExpr() - ) - } -} - -/** - * An argument to Velocity template engine's `evaluate` method call. - */ -private class VelocityEvaluateSink extends Sink { - VelocityEvaluateSink() { - exists(MethodAccess m | - m.getCallee() instanceof MethodVelocityEvaluate and - m.getArgument([0, 3]) = this.getExpr() - ) - } -} - -/** - * An argument to Velocity template engine's `parse` method call. - */ -private class VelocityParseSink extends Sink { - VelocityParseSink() { - exists(MethodAccess ma | - this.asExpr() = ma.getArgument(0) and - ma.getMethod() instanceof MethodVelocityParse - ) - } -} - -/** - * An argument to Velocity template engine's `putStringResource` method call. - */ -private class VelocityPutStringResSink extends Sink { - VelocityPutStringResSink() { - exists(MethodAccess ma | - this.asExpr() = ma.getArgument(1) and - ma.getMethod() instanceof MethodVelocityPutStringResource - ) - } -} diff --git a/java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll b/java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll index bb16099ddc3..cc1552b59b9 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll @@ -47,8 +47,8 @@ class SpringControllerRequestMappingGetMethod extends SpringControllerGetMethod .getType() .hasQualifiedName("org.springframework.web.bind.annotation", "RequestMapping") and ( - this.getAnAnnotation().getValue("method").(VarAccess).getVariable().getName() = "GET" or - this.getAnAnnotation().getValue("method").(ArrayInit).getSize() = 0 //Java code example: @RequestMapping(value = "test") + this.getAnAnnotation().getAnEnumConstantArrayValue("method").getName() = "GET" or + not exists(this.getAnAnnotation().getAnArrayValue("method")) //Java code example: @RequestMapping(value = "test") ) and not this.getAParamType().getName() = "MultipartFile" } diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/FreeMarker.qll b/java/ql/src/experimental/semmle/code/java/frameworks/FreeMarker.qll deleted file mode 100644 index 84cea7f013e..00000000000 --- a/java/ql/src/experimental/semmle/code/java/frameworks/FreeMarker.qll +++ /dev/null @@ -1,29 +0,0 @@ -/** Definitions related to the FreeMarker Templating library. */ - -import java - -/** The `Template` class of the FreeMarker Template Engine */ -class TypeFreeMarkerTemplate extends Class { - TypeFreeMarkerTemplate() { this.hasQualifiedName("freemarker.template", "Template") } -} - -/** The `process` method of the FreeMarker Template Engine's `Template` class */ -class MethodFreeMarkerTemplateProcess extends Method { - MethodFreeMarkerTemplateProcess() { - this.getDeclaringType() instanceof TypeFreeMarkerTemplate and - this.hasName("process") - } -} - -/** The `StringTemplateLoader` class of the FreeMarker Template Engine */ -class TypeFreeMarkerStringLoader extends Class { - TypeFreeMarkerStringLoader() { this.hasQualifiedName("freemarker.cache", "StringTemplateLoader") } -} - -/** The `process` method of the FreeMarker Template Engine's `StringTemplateLoader` class */ -class MethodFreeMarkerStringTemplateLoaderPutTemplate extends Method { - MethodFreeMarkerStringTemplateLoaderPutTemplate() { - this.getDeclaringType() instanceof TypeFreeMarkerStringLoader and - this.hasName("putTemplate") - } -} diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/JinJava.qll b/java/ql/src/experimental/semmle/code/java/frameworks/JinJava.qll deleted file mode 100644 index f0f3bcf603b..00000000000 --- a/java/ql/src/experimental/semmle/code/java/frameworks/JinJava.qll +++ /dev/null @@ -1,24 +0,0 @@ -/** Definitions related to the Jinjava Templating library. */ - -import java - -/** The `Jinjava` class of the Jinjava Templating Engine. */ -class TypeJinjava extends Class { - TypeJinjava() { this.hasQualifiedName("com.hubspot.jinjava", "Jinjava") } -} - -/** The `render` method of the Jinjava Templating Engine. */ -class MethodJinjavaRender extends Method { - MethodJinjavaRender() { - this.getDeclaringType() instanceof TypeJinjava and - this.hasName("render") - } -} - -/** The `render` method of the Jinjava Templating Engine. */ -class MethodJinjavaRenderForResult extends Method { - MethodJinjavaRenderForResult() { - this.getDeclaringType() instanceof TypeJinjava and - this.hasName("renderForResult") - } -} diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/Pebble.qll b/java/ql/src/experimental/semmle/code/java/frameworks/Pebble.qll deleted file mode 100644 index 9850e5dbf4d..00000000000 --- a/java/ql/src/experimental/semmle/code/java/frameworks/Pebble.qll +++ /dev/null @@ -1,16 +0,0 @@ -/** Definitions related to the Pebble Templating library. */ - -import java - -/** The `PebbleEngine` class of the Pebble Templating Engine. */ -class TypePebbleEngine extends Class { - TypePebbleEngine() { this.hasQualifiedName("com.mitchellbosecke.pebble", "PebbleEngine") } -} - -/** The `getTemplate` method of the Pebble Templating Engine. */ -class MethodPebbleGetTemplate extends Method { - MethodPebbleGetTemplate() { - this.getDeclaringType() instanceof TypePebbleEngine and - this.hasName(["getTemplate", "getLiteralTemplate"]) - } -} diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll b/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll deleted file mode 100644 index e93f2739be1..00000000000 --- a/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll +++ /dev/null @@ -1,25 +0,0 @@ -/** Definitions related to the Thymeleaf Templating library. */ - -import java - -/** - * A class implementing the `ITemplateEngine` interface of the Thymeleaf - * Templating Engine such as the `TemplateEngine` class. - */ -class TypeThymeleafTemplateEngine extends Class { - TypeThymeleafTemplateEngine() { - this.hasQualifiedName("org.thymeleaf", "TemplateEngine") - or - exists(Type t | this.getASupertype*().extendsOrImplements(t) | - t.hasName("org.thymeleaf.ITemplateEngine") - ) - } -} - -/** The `process` or `processThrottled` method of the Thymeleaf Templating Engine. */ -class MethodThymeleafProcess extends Method { - MethodThymeleafProcess() { - this.getDeclaringType() instanceof TypeThymeleafTemplateEngine and - this.hasName(["process", "processThrottled"]) - } -} diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/Velocity.qll b/java/ql/src/experimental/semmle/code/java/frameworks/Velocity.qll deleted file mode 100644 index f2d298833c6..00000000000 --- a/java/ql/src/experimental/semmle/code/java/frameworks/Velocity.qll +++ /dev/null @@ -1,119 +0,0 @@ -/** Definitions related to the Apache Velocity Templating library. */ - -import java - -/** The `org.apache.velocity.context.AbstractContext` class of the Velocity Templating Engine. */ -class TypeVelocityAbstractContext extends Class { - TypeVelocityAbstractContext() { - this.hasQualifiedName("org.apache.velocity.context", "AbstractContext") - } -} - -/** The `org.apache.velocity.runtime.RuntimeServices` class of the Velocity Templating Engine. */ -class TypeVelocityRuntimeRuntimeServices extends Class { - TypeVelocityRuntimeRuntimeServices() { - this.hasQualifiedName("org.apache.velocity.runtime", "RuntimeServices") - } -} - -/** The `org.apache.velocity.Template` class of the Velocity Templating Engine. */ -class TypeVelocityTemplate extends Class { - TypeVelocityTemplate() { this.hasQualifiedName("org.apache.velocity", "Template") } -} - -/** The `org.apache.velocity.runtime.RuntimeSingleton` classTemplating Engine. */ -class TypeVelocityRuntimeRuntimeSingleton extends Class { - TypeVelocityRuntimeRuntimeSingleton() { - this.hasQualifiedName("org.apache.velocity.runtime", "RuntimeSingleton") - } -} - -/** The `org.apache.velocity.VelocityEngine` class of the Velocity Templating Engine. */ -class TypeVelocityVelocityEngine extends Class { - TypeVelocityVelocityEngine() { this.hasQualifiedName("org.apache.velocity", "VelocityEngine") } -} - -/** The `org.apache.velocity.app.VelocityEngine` class of the Velocity Templating Engine. */ -class TypeVelocityAppVelocityEngine extends RefType { - TypeVelocityAppVelocityEngine() { - this.hasQualifiedName("org.apache.velocity.app", "VelocityEngine") - } -} - -/** The `org.apache.velocity.app.Velocity` class of the Velocity Templating Engine. */ -class TypeVelocityAppVelocity extends RefType { - TypeVelocityAppVelocity() { this.hasQualifiedName("org.apache.velocity.app", "Velocity") } -} - -/** - * The `org.apache.velocity.runtime.resource.util.StringResourceRepository` interface - * of the Velocity Templating Engine. - */ -class TypeVelocityStringResourceRepo extends RefType { - TypeVelocityStringResourceRepo() { - this.hasQualifiedName("org.apache.velocity.runtime.resource.util", "StringResourceRepository") - } -} - -/** The `internalPut` and `put` methods of the Velocity Templating Engine. */ -class MethodVelocityContextPut extends Method { - MethodVelocityContextPut() { - this.getDeclaringType().getASupertype*() instanceof TypeVelocityAbstractContext and - this.hasName(["put", "internalPut"]) - } -} - -/** The `evaluate` method of the Velocity Templating Engine. */ -class MethodVelocityEvaluate extends Method { - MethodVelocityEvaluate() { - // static boolean evaluate(Context context, Writer out, String logTag, String instring) - // static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) - ( - this.getDeclaringType() instanceof TypeVelocityAppVelocity or - this.getDeclaringType() instanceof TypeVelocityAppVelocityEngine or - this.getDeclaringType().getASupertype*() instanceof TypeVelocityRuntimeRuntimeServices - ) and - this.hasName("evaluate") - } -} - -/** The `mergeTemplate` method of the Velocity Templating Engine. */ -class MethodVelocityMergeTemplate extends Method { - MethodVelocityMergeTemplate() { - // static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer) - ( - this.getDeclaringType() instanceof TypeVelocityAppVelocity or - this.getDeclaringType() instanceof TypeVelocityAppVelocityEngine - ) and - this.hasName("mergeTemplate") - } -} - -/** The `merge` method of the Velocity Templating Engine. */ -class MethodVelocityMerge extends Method { - MethodVelocityMerge() { - // void merge(Context context, Writer writer) - // void merge(Context context, Writer writer, List macroLibraries) - this.getDeclaringType() instanceof TypeVelocityTemplate and - this.hasName("merge") - } -} - -/** The `parse` method of the Velocity Templating Engine. */ -class MethodVelocityParse extends Method { - MethodVelocityParse() { - ( - this.getDeclaringType().getASupertype*() instanceof TypeVelocityRuntimeRuntimeSingleton or - this.getDeclaringType().getASupertype*() instanceof TypeVelocityRuntimeRuntimeServices - ) and - this.hasName("parse") - } -} - -/** The `putStringResource` method of the Velocity Templating Engine. */ -class MethodVelocityPutStringResource extends Method { - MethodVelocityPutStringResource() { - this.getDeclaringType().getASupertype*() instanceof TypeVelocityStringResourceRepo and - this.hasName("putStringResource") - } -} diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index 3e24af43783..3396c56e727 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 0.3.4-dev +version: 0.3.5-dev groups: - java - queries diff --git a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql index 60bf8351de2..49ed16aa1dc 100644 --- a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql +++ b/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql @@ -6,9 +6,9 @@ * @tags model-generator */ -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string noflow +from DataFlowTargetApi api, string noflow where noflow = captureNoFlow(api) select noflow order by noflow diff --git a/java/ql/src/utils/model-generator/CaptureSinkModels.ql b/java/ql/src/utils/model-generator/CaptureSinkModels.ql index 405b9fab772..154c87928fc 100644 --- a/java/ql/src/utils/model-generator/CaptureSinkModels.ql +++ b/java/ql/src/utils/model-generator/CaptureSinkModels.ql @@ -6,8 +6,8 @@ * @tags model-generator */ -private import internal.CaptureModels +import internal.CaptureModels -from TargetApi api, string sink +from DataFlowTargetApi api, string sink where sink = captureSink(api) select sink order by sink diff --git a/java/ql/src/utils/model-generator/CaptureSourceModels.ql b/java/ql/src/utils/model-generator/CaptureSourceModels.ql index d37cf5e78fb..8c7de037a90 100644 --- a/java/ql/src/utils/model-generator/CaptureSourceModels.ql +++ b/java/ql/src/utils/model-generator/CaptureSourceModels.ql @@ -6,8 +6,8 @@ * @tags model-generator */ -private import internal.CaptureModels +import internal.CaptureModels -from TargetApi api, string source +from DataFlowTargetApi api, string source where source = captureSource(api) select source order by source diff --git a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql index a4eaea9c4e8..981c6fe73fc 100644 --- a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql +++ b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql @@ -6,9 +6,9 @@ * @tags model-generator */ -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string flow +from DataFlowTargetApi api, string flow where flow = captureFlow(api) select flow order by flow diff --git a/java/ql/src/utils/model-generator/internal/CaptureModels.qll b/java/ql/src/utils/model-generator/internal/CaptureModels.qll index c6ebc854edb..82c6fbd1bbb 100644 --- a/java/ql/src/utils/model-generator/internal/CaptureModels.qll +++ b/java/ql/src/utils/model-generator/internal/CaptureModels.qll @@ -5,7 +5,9 @@ private import CaptureModelsSpecific -class TargetApi = TargetApiSpecific; +class DataFlowTargetApi extends TargetApiSpecific { + DataFlowTargetApi() { isRelevantForDataFlowModels(this) } +} /** * Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`. @@ -40,7 +42,7 @@ private predicate isRelevantContent(DataFlow::Content c) { * Gets the summary model for `api` with `input`, `output` and `kind`. */ bindingset[input, output, kind] -private string asSummaryModel(TargetApi api, string input, string output, string kind) { +private string asSummaryModel(TargetApiSpecific api, string input, string output, string kind) { result = asPartialModel(api) + input + ";" // + output + ";" // @@ -48,13 +50,15 @@ private string asSummaryModel(TargetApi api, string input, string output, string + "generated" } -string asNegativeSummaryModel(TargetApi api) { result = asPartialNegativeModel(api) + "generated" } +string asNegativeSummaryModel(TargetApiSpecific api) { + result = asPartialNegativeModel(api) + "generated" +} /** * Gets the value summary model for `api` with `input` and `output`. */ bindingset[input, output] -private string asValueModel(TargetApi api, string input, string output) { +string asValueModel(TargetApiSpecific api, string input, string output) { result = asSummaryModel(api, input, output, "value") } @@ -62,7 +66,7 @@ private string asValueModel(TargetApi api, string input, string output) { * Gets the taint summary model for `api` with `input` and `output`. */ bindingset[input, output] -private string asTaintModel(TargetApi api, string input, string output) { +private string asTaintModel(TargetApiSpecific api, string input, string output) { result = asSummaryModel(api, input, output, "taint") } @@ -70,7 +74,7 @@ private string asTaintModel(TargetApi api, string input, string output) { * Gets the sink model for `api` with `input` and `kind`. */ bindingset[input, kind] -private string asSinkModel(TargetApi api, string input, string kind) { +private string asSinkModel(TargetApiSpecific api, string input, string kind) { result = asPartialModel(api) + input + ";" // + kind + ";" // @@ -81,7 +85,7 @@ private string asSinkModel(TargetApi api, string input, string kind) { * Gets the source model for `api` with `output` and `kind`. */ bindingset[output, kind] -private string asSourceModel(TargetApi api, string output, string kind) { +private string asSourceModel(TargetApiSpecific api, string output, string kind) { result = asPartialModel(api) + output + ";" // + kind + ";" // @@ -91,7 +95,7 @@ private string asSourceModel(TargetApi api, string output, string kind) { /** * Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`). */ -string captureQualifierFlow(TargetApi api) { +string captureQualifierFlow(TargetApiSpecific api) { exists(DataFlowImplCommon::ReturnNodeExt ret | api = returnNodeEnclosingCallable(ret) and isOwnInstanceAccessNode(ret) @@ -140,7 +144,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { source instanceof DataFlow::ParameterNode and - source.getEnclosingCallable() instanceof TargetApi and + source.getEnclosingCallable() instanceof DataFlowTargetApi and state.(TaintRead).getStep() = 0 } @@ -184,7 +188,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { /** * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. */ -string captureThroughFlow(TargetApi api) { +string captureThroughFlow(DataFlowTargetApi api) { exists( ThroughFlowConfig config, DataFlow::ParameterNode p, DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output @@ -211,7 +215,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) } override predicate isSink(DataFlow::Node sink) { - exists(TargetApi c | + exists(DataFlowTargetApi c | sink instanceof DataFlowImplCommon::ReturnNodeExt and sink.getEnclosingCallable() = c ) @@ -229,7 +233,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration { /** * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`. */ -string captureSource(TargetApi api) { +string captureSource(DataFlowTargetApi api) { exists(DataFlow::Node source, DataFlow::Node sink, FromSourceConfiguration config, string kind | config.hasFlow(source, sink) and ExternalFlow::sourceNode(source, kind) and @@ -259,7 +263,7 @@ private class PropagateToSinkConfiguration extends PropagateToSinkConfigurationS /** * Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink. */ -string captureSink(TargetApi api) { +string captureSink(DataFlowTargetApi api) { exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind | config.hasFlow(src, sink) and ExternalFlow::sinkNode(sink, kind) and diff --git a/java/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll index bcdd90caac5..2e630ec5214 100644 --- a/java/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll +++ b/java/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll @@ -59,6 +59,11 @@ private predicate isRelevantForModels(J::Callable api) { not api instanceof J::StaticInitializer } +/** + * Holds if it is relevant to generate models for `api` based on data flow analysis. + */ +predicate isRelevantForDataFlowModels = isRelevantForModels/1; + /** * A class of Callables that are relevant for generating summary, source and sinks models for. * diff --git a/java/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll b/java/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll index 196b2189e94..dce9ce9cfef 100644 --- a/java/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll +++ b/java/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll @@ -67,7 +67,7 @@ private import CaptureModels * Captured Model: * ```p;Foo;true;addToList;;Argument[0];Argument[1];taint``` */ -string captureFlow(TargetApi api) { +string captureFlow(DataFlowTargetApi api) { result = captureQualifierFlow(api) or result = captureThroughFlow(api) } @@ -76,7 +76,7 @@ string captureFlow(TargetApi api) { * Gets the negative summary for `api`, if any. * A negative summary is generated, if there does not exist any positive flow. */ -string captureNoFlow(TargetApi api) { +string captureNoFlow(DataFlowTargetApi api) { not exists(captureFlow(api)) and result = asNegativeSummaryModel(api) } diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected deleted file mode 100644 index 9b739f8d1da..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected +++ /dev/null @@ -1,136 +0,0 @@ -edges -| FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | FreemarkerSSTI.java:24:36:24:39 | code : String | -| FreemarkerSSTI.java:24:19:24:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:27:35:27:40 | reader | -| FreemarkerSSTI.java:24:36:24:39 | code : String | FreemarkerSSTI.java:24:19:24:40 | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | FreemarkerSSTI.java:34:36:34:39 | code : String | -| FreemarkerSSTI.java:34:19:34:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:38:35:38:40 | reader | -| FreemarkerSSTI.java:34:36:34:39 | code : String | FreemarkerSSTI.java:34:19:34:40 | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | FreemarkerSSTI.java:45:36:45:39 | code : String | -| FreemarkerSSTI.java:45:19:45:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:50:35:50:40 | reader | -| FreemarkerSSTI.java:45:36:45:39 | code : String | FreemarkerSSTI.java:45:19:45:40 | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:56:23:56:56 | getParameter(...) : String | FreemarkerSSTI.java:61:35:61:44 | sourceCode | -| FreemarkerSSTI.java:67:17:67:44 | getParameter(...) : String | FreemarkerSSTI.java:69:36:69:39 | code : String | -| FreemarkerSSTI.java:69:19:69:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:73:47:73:52 | reader | -| FreemarkerSSTI.java:69:36:69:39 | code : String | FreemarkerSSTI.java:69:19:69:40 | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:79:17:79:44 | getParameter(...) : String | FreemarkerSSTI.java:82:36:82:39 | code : String | -| FreemarkerSSTI.java:82:19:82:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:87:47:87:52 | reader | -| FreemarkerSSTI.java:82:36:82:39 | code : String | FreemarkerSSTI.java:82:19:82:40 | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:93:17:93:44 | getParameter(...) : String | FreemarkerSSTI.java:96:36:96:39 | code : String | -| FreemarkerSSTI.java:96:19:96:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:100:47:100:52 | reader | -| FreemarkerSSTI.java:96:36:96:39 | code : String | FreemarkerSSTI.java:96:19:96:40 | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:105:17:105:44 | getParameter(...) : String | FreemarkerSSTI.java:109:42:109:45 | code | -| FreemarkerSSTI.java:114:17:114:44 | getParameter(...) : String | FreemarkerSSTI.java:119:42:119:45 | code | -| FreemarkerSSTI.java:125:17:125:44 | getParameter(...) : String | FreemarkerSSTI.java:126:26:126:29 | code : String | -| FreemarkerSSTI.java:126:9:126:12 | root [post update] [] : String | FreemarkerSSTI.java:130:22:130:25 | root | -| FreemarkerSSTI.java:126:26:126:29 | code : String | FreemarkerSSTI.java:126:9:126:12 | root [post update] [] : String | -| JinJavaSSTI.java:21:21:21:52 | getParameter(...) : String | JinJavaSSTI.java:25:44:25:51 | template | -| JinJavaSSTI.java:30:21:30:52 | getParameter(...) : String | JinJavaSSTI.java:34:55:34:62 | template | -| JinJavaSSTI.java:39:21:39:52 | getParameter(...) : String | JinJavaSSTI.java:46:55:46:62 | template | -| PebbleSSTI.java:18:17:18:44 | getParameter(...) : String | PebbleSSTI.java:21:56:21:59 | code | -| PebbleSSTI.java:25:17:25:44 | getParameter(...) : String | PebbleSSTI.java:28:63:28:66 | code | -| ThymeleafSSTI.java:22:17:22:44 | getParameter(...) : String | ThymeleafSSTI.java:27:27:27:30 | code | -| VelocitySSTI.java:31:17:31:44 | getParameter(...) : String | VelocitySSTI.java:38:45:38:48 | code | -| VelocitySSTI.java:44:17:44:44 | getParameter(...) : String | VelocitySSTI.java:50:42:50:45 | code : String | -| VelocitySSTI.java:50:25:50:46 | new StringReader(...) : StringReader | VelocitySSTI.java:53:45:53:50 | reader | -| VelocitySSTI.java:50:42:50:45 | code : String | VelocitySSTI.java:50:25:50:46 | new StringReader(...) : StringReader | -| VelocitySSTI.java:59:17:59:44 | getParameter(...) : String | VelocitySSTI.java:62:42:62:45 | code : String | -| VelocitySSTI.java:62:25:62:46 | new StringReader(...) : StringReader | VelocitySSTI.java:63:25:63:30 | reader | -| VelocitySSTI.java:62:42:62:45 | code : String | VelocitySSTI.java:62:25:62:46 | new StringReader(...) : StringReader | -| VelocitySSTI.java:69:17:69:44 | getParameter(...) : String | VelocitySSTI.java:77:21:77:27 | context | -| VelocitySSTI.java:83:17:83:44 | getParameter(...) : String | VelocitySSTI.java:89:60:89:66 | context | -| VelocitySSTI.java:95:17:95:44 | getParameter(...) : String | VelocitySSTI.java:102:11:102:17 | context | -| VelocitySSTI.java:108:17:108:44 | getParameter(...) : String | VelocitySSTI.java:115:11:115:17 | context | -| VelocitySSTI.java:120:17:120:44 | getParameter(...) : String | VelocitySSTI.java:123:37:123:40 | code | -nodes -| FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:24:19:24:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:24:36:24:39 | code : String | semmle.label | code : String | -| FreemarkerSSTI.java:27:35:27:40 | reader | semmle.label | reader | -| FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:34:19:34:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:34:36:34:39 | code : String | semmle.label | code : String | -| FreemarkerSSTI.java:38:35:38:40 | reader | semmle.label | reader | -| FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:45:19:45:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:45:36:45:39 | code : String | semmle.label | code : String | -| FreemarkerSSTI.java:50:35:50:40 | reader | semmle.label | reader | -| FreemarkerSSTI.java:56:23:56:56 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:61:35:61:44 | sourceCode | semmle.label | sourceCode | -| FreemarkerSSTI.java:67:17:67:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:69:19:69:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:69:36:69:39 | code : String | semmle.label | code : String | -| FreemarkerSSTI.java:73:47:73:52 | reader | semmle.label | reader | -| FreemarkerSSTI.java:79:17:79:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:82:19:82:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:82:36:82:39 | code : String | semmle.label | code : String | -| FreemarkerSSTI.java:87:47:87:52 | reader | semmle.label | reader | -| FreemarkerSSTI.java:93:17:93:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:96:19:96:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader | -| FreemarkerSSTI.java:96:36:96:39 | code : String | semmle.label | code : String | -| FreemarkerSSTI.java:100:47:100:52 | reader | semmle.label | reader | -| FreemarkerSSTI.java:105:17:105:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:109:42:109:45 | code | semmle.label | code | -| FreemarkerSSTI.java:114:17:114:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:119:42:119:45 | code | semmle.label | code | -| FreemarkerSSTI.java:125:17:125:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| FreemarkerSSTI.java:126:9:126:12 | root [post update] [] : String | semmle.label | root [post update] [] : String | -| FreemarkerSSTI.java:126:26:126:29 | code : String | semmle.label | code : String | -| FreemarkerSSTI.java:130:22:130:25 | root | semmle.label | root | -| JinJavaSSTI.java:21:21:21:52 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| JinJavaSSTI.java:25:44:25:51 | template | semmle.label | template | -| JinJavaSSTI.java:30:21:30:52 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| JinJavaSSTI.java:34:55:34:62 | template | semmle.label | template | -| JinJavaSSTI.java:39:21:39:52 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| JinJavaSSTI.java:46:55:46:62 | template | semmle.label | template | -| PebbleSSTI.java:18:17:18:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| PebbleSSTI.java:21:56:21:59 | code | semmle.label | code | -| PebbleSSTI.java:25:17:25:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| PebbleSSTI.java:28:63:28:66 | code | semmle.label | code | -| ThymeleafSSTI.java:22:17:22:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| ThymeleafSSTI.java:27:27:27:30 | code | semmle.label | code | -| VelocitySSTI.java:31:17:31:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| VelocitySSTI.java:38:45:38:48 | code | semmle.label | code | -| VelocitySSTI.java:44:17:44:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| VelocitySSTI.java:50:25:50:46 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader | -| VelocitySSTI.java:50:42:50:45 | code : String | semmle.label | code : String | -| VelocitySSTI.java:53:45:53:50 | reader | semmle.label | reader | -| VelocitySSTI.java:59:17:59:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| VelocitySSTI.java:62:25:62:46 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader | -| VelocitySSTI.java:62:42:62:45 | code : String | semmle.label | code : String | -| VelocitySSTI.java:63:25:63:30 | reader | semmle.label | reader | -| VelocitySSTI.java:69:17:69:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| VelocitySSTI.java:77:21:77:27 | context | semmle.label | context | -| VelocitySSTI.java:83:17:83:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| VelocitySSTI.java:89:60:89:66 | context | semmle.label | context | -| VelocitySSTI.java:95:17:95:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| VelocitySSTI.java:102:11:102:17 | context | semmle.label | context | -| VelocitySSTI.java:108:17:108:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| VelocitySSTI.java:115:11:115:17 | context | semmle.label | context | -| VelocitySSTI.java:120:17:120:44 | getParameter(...) : String | semmle.label | getParameter(...) : String | -| VelocitySSTI.java:123:37:123:40 | code | semmle.label | code | -subpaths -#select -| FreemarkerSSTI.java:27:35:27:40 | reader | FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | FreemarkerSSTI.java:27:35:27:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:23:17:23:44 | getParameter(...) | a template value loaded from a remote source. | -| FreemarkerSSTI.java:38:35:38:40 | reader | FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | FreemarkerSSTI.java:38:35:38:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:33:17:33:44 | getParameter(...) | a template value loaded from a remote source. | -| FreemarkerSSTI.java:50:35:50:40 | reader | FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | FreemarkerSSTI.java:50:35:50:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:44:17:44:44 | getParameter(...) | a template value loaded from a remote source. | -| FreemarkerSSTI.java:61:35:61:44 | sourceCode | FreemarkerSSTI.java:56:23:56:56 | getParameter(...) : String | FreemarkerSSTI.java:61:35:61:44 | sourceCode | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:56:23:56:56 | getParameter(...) | a template value loaded from a remote source. | -| FreemarkerSSTI.java:73:47:73:52 | reader | FreemarkerSSTI.java:67:17:67:44 | getParameter(...) : String | FreemarkerSSTI.java:73:47:73:52 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:67:17:67:44 | getParameter(...) | a template value loaded from a remote source. | -| FreemarkerSSTI.java:87:47:87:52 | reader | FreemarkerSSTI.java:79:17:79:44 | getParameter(...) : String | FreemarkerSSTI.java:87:47:87:52 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:79:17:79:44 | getParameter(...) | a template value loaded from a remote source. | -| FreemarkerSSTI.java:100:47:100:52 | reader | FreemarkerSSTI.java:93:17:93:44 | getParameter(...) : String | FreemarkerSSTI.java:100:47:100:52 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:93:17:93:44 | getParameter(...) | a template value loaded from a remote source. | -| FreemarkerSSTI.java:109:42:109:45 | code | FreemarkerSSTI.java:105:17:105:44 | getParameter(...) : String | FreemarkerSSTI.java:109:42:109:45 | code | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:105:17:105:44 | getParameter(...) | a template value loaded from a remote source. | -| FreemarkerSSTI.java:119:42:119:45 | code | FreemarkerSSTI.java:114:17:114:44 | getParameter(...) : String | FreemarkerSSTI.java:119:42:119:45 | code | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:114:17:114:44 | getParameter(...) | a template value loaded from a remote source. | -| FreemarkerSSTI.java:130:22:130:25 | root | FreemarkerSSTI.java:125:17:125:44 | getParameter(...) : String | FreemarkerSSTI.java:130:22:130:25 | root | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:125:17:125:44 | getParameter(...) | a template value loaded from a remote source. | -| JinJavaSSTI.java:25:44:25:51 | template | JinJavaSSTI.java:21:21:21:52 | getParameter(...) : String | JinJavaSSTI.java:25:44:25:51 | template | Potential arbitrary code execution due to $@. | JinJavaSSTI.java:21:21:21:52 | getParameter(...) | a template value loaded from a remote source. | -| JinJavaSSTI.java:34:55:34:62 | template | JinJavaSSTI.java:30:21:30:52 | getParameter(...) : String | JinJavaSSTI.java:34:55:34:62 | template | Potential arbitrary code execution due to $@. | JinJavaSSTI.java:30:21:30:52 | getParameter(...) | a template value loaded from a remote source. | -| JinJavaSSTI.java:46:55:46:62 | template | JinJavaSSTI.java:39:21:39:52 | getParameter(...) : String | JinJavaSSTI.java:46:55:46:62 | template | Potential arbitrary code execution due to $@. | JinJavaSSTI.java:39:21:39:52 | getParameter(...) | a template value loaded from a remote source. | -| PebbleSSTI.java:21:56:21:59 | code | PebbleSSTI.java:18:17:18:44 | getParameter(...) : String | PebbleSSTI.java:21:56:21:59 | code | Potential arbitrary code execution due to $@. | PebbleSSTI.java:18:17:18:44 | getParameter(...) | a template value loaded from a remote source. | -| PebbleSSTI.java:28:63:28:66 | code | PebbleSSTI.java:25:17:25:44 | getParameter(...) : String | PebbleSSTI.java:28:63:28:66 | code | Potential arbitrary code execution due to $@. | PebbleSSTI.java:25:17:25:44 | getParameter(...) | a template value loaded from a remote source. | -| ThymeleafSSTI.java:27:27:27:30 | code | ThymeleafSSTI.java:22:17:22:44 | getParameter(...) : String | ThymeleafSSTI.java:27:27:27:30 | code | Potential arbitrary code execution due to $@. | ThymeleafSSTI.java:22:17:22:44 | getParameter(...) | a template value loaded from a remote source. | -| VelocitySSTI.java:38:45:38:48 | code | VelocitySSTI.java:31:17:31:44 | getParameter(...) : String | VelocitySSTI.java:38:45:38:48 | code | Potential arbitrary code execution due to $@. | VelocitySSTI.java:31:17:31:44 | getParameter(...) | a template value loaded from a remote source. | -| VelocitySSTI.java:53:45:53:50 | reader | VelocitySSTI.java:44:17:44:44 | getParameter(...) : String | VelocitySSTI.java:53:45:53:50 | reader | Potential arbitrary code execution due to $@. | VelocitySSTI.java:44:17:44:44 | getParameter(...) | a template value loaded from a remote source. | -| VelocitySSTI.java:63:25:63:30 | reader | VelocitySSTI.java:59:17:59:44 | getParameter(...) : String | VelocitySSTI.java:63:25:63:30 | reader | Potential arbitrary code execution due to $@. | VelocitySSTI.java:59:17:59:44 | getParameter(...) | a template value loaded from a remote source. | -| VelocitySSTI.java:77:21:77:27 | context | VelocitySSTI.java:69:17:69:44 | getParameter(...) : String | VelocitySSTI.java:77:21:77:27 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:69:17:69:44 | getParameter(...) | a template value loaded from a remote source. | -| VelocitySSTI.java:89:60:89:66 | context | VelocitySSTI.java:83:17:83:44 | getParameter(...) : String | VelocitySSTI.java:89:60:89:66 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:83:17:83:44 | getParameter(...) | a template value loaded from a remote source. | -| VelocitySSTI.java:102:11:102:17 | context | VelocitySSTI.java:95:17:95:44 | getParameter(...) : String | VelocitySSTI.java:102:11:102:17 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:95:17:95:44 | getParameter(...) | a template value loaded from a remote source. | -| VelocitySSTI.java:115:11:115:17 | context | VelocitySSTI.java:108:17:108:44 | getParameter(...) : String | VelocitySSTI.java:115:11:115:17 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:108:17:108:44 | getParameter(...) | a template value loaded from a remote source. | -| VelocitySSTI.java:123:37:123:40 | code | VelocitySSTI.java:120:17:120:44 | getParameter(...) : String | VelocitySSTI.java:123:37:123:40 | code | Potential arbitrary code execution due to $@. | VelocitySSTI.java:120:17:120:44 | getParameter(...) | a template value loaded from a remote source. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.qlref deleted file mode 100644 index 2febc9b780f..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-094/TemplateInjection.ql \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/ThymeleafSSTI.java b/java/ql/test/experimental/query-tests/security/CWE-094/ThymeleafSSTI.java deleted file mode 100644 index 2b32a4603c7..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-094/ThymeleafSSTI.java +++ /dev/null @@ -1,31 +0,0 @@ -import javax.imageio.stream.FileImageInputStream; -import javax.servlet.http.HttpServletRequest; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -import java.lang.String; -import java.io.File; -import java.io.FileWriter; -import java.io.Reader; -import java.io.StringReader; -import java.io.Writer; - -import org.thymeleaf.*; -import org.thymeleaf.context.Context; - -@Controller -public class ThymeleafSSTI { - String sourceName = "sourceName"; - - @GetMapping(value = "bad1") - public void bad1(HttpServletRequest request) { - String code = request.getParameter("code"); - Context ctx = new Context(); - try { - FileWriter fw = new FileWriter(new File("as")); - TemplateEngine templateEngine = new TemplateEngine(); - templateEngine.process(code, ctx, fw); - } catch (Exception e) { - } - } -} diff --git a/java/ql/test/kotlin/library-tests/dataflow/func/coroutine_async_await.kt b/java/ql/test/kotlin/library-tests/dataflow/func/coroutine_async_await.kt new file mode 100644 index 00000000000..c396533dee5 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/dataflow/func/coroutine_async_await.kt @@ -0,0 +1,8 @@ +import kotlinx.coroutines.* + +suspend fun fn() { + GlobalScope.launch { + val x: Deferred = async { Helper.taint() } + Helper.sink(x.await()) // TODO: not found + } +} diff --git a/java/ql/test/kotlin/library-tests/dataflow/func/functionReference.kt b/java/ql/test/kotlin/library-tests/dataflow/func/functionReference.kt index 4329c73f0b1..47dcbbf347a 100644 --- a/java/ql/test/kotlin/library-tests/dataflow/func/functionReference.kt +++ b/java/ql/test/kotlin/library-tests/dataflow/func/functionReference.kt @@ -2,10 +2,11 @@ class FunctionReference { fun fn1(s: String) = s - fun test() { + suspend fun test() { fun fn2(s: String) = s Helper.sink(Processor().process(this::fn1, Helper.taint())) + Helper.sink(Processor().processSusp(this::fn1Susp, Helper.taint())) Helper.sink(Processor().process(FunctionReference::fn1, this, Helper.taint())) Helper.sink(Processor().process(this::fn1, Helper.notaint())) Helper.sink(Processor().process(::fn2, Helper.taint())) @@ -16,4 +17,6 @@ class FunctionReference { val prop: String get() = Helper.taint() + + suspend fun fn1Susp(s: String) = s } diff --git a/java/ql/test/kotlin/library-tests/dataflow/func/kotlinx_coroutines_stubs.kt b/java/ql/test/kotlin/library-tests/dataflow/func/kotlinx_coroutines_stubs.kt new file mode 100644 index 00000000000..8fbafe86db0 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/dataflow/func/kotlinx_coroutines_stubs.kt @@ -0,0 +1,33 @@ +/** + * Stubs for `kotlinx.coroutines` + */ + +@file:JvmName("BuildersKt") // Required for `async` + +package kotlinx.coroutines + +public interface CoroutineScope +public interface CoroutineContext +public enum class CoroutineStart { DEFAULT } +public interface Job +public interface Deferred : Job { + public suspend fun await(): T +} + +public object GlobalScope : CoroutineScope + +public fun CoroutineScope.launch( + context: CoroutineContext = null!!, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> Unit +): Job { + return null!! +} + +public fun CoroutineScope.async( + context: CoroutineContext = null!!, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> T +): Deferred { + return null!! +} \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/dataflow/func/lambda.kt b/java/ql/test/kotlin/library-tests/dataflow/func/lambda.kt index 5d53bb2dcdb..fd57df63e51 100644 --- a/java/ql/test/kotlin/library-tests/dataflow/func/lambda.kt +++ b/java/ql/test/kotlin/library-tests/dataflow/func/lambda.kt @@ -1,7 +1,8 @@ class Lambda { - fun test() { + suspend fun test() { Helper.sink(Processor().process({ it: String -> Helper.notaint() }, "")) Helper.sink(Processor().process({ it: String -> Helper.taint() }, "")) + Helper.sink(Processor().processSusp({ it: String -> Helper.taint() }, "")) Helper.sink(Processor().process({ i -> i }, Helper.taint())) Helper.sink(Processor().process(fun (i: String) = i, Helper.taint())) @@ -29,4 +30,4 @@ class ManualBigLambda { Helper.sink(invoke(arrayOf(Helper.taint(), Helper.notaint()))) Helper.sink(invoke(arrayOf(Helper.notaint(), Helper.taint()))) // False positive } -} \ No newline at end of file +} diff --git a/java/ql/test/kotlin/library-tests/dataflow/func/localFunction.kt b/java/ql/test/kotlin/library-tests/dataflow/func/localFunction.kt index 1318e80701e..655fd3a9e3a 100644 --- a/java/ql/test/kotlin/library-tests/dataflow/func/localFunction.kt +++ b/java/ql/test/kotlin/library-tests/dataflow/func/localFunction.kt @@ -1,9 +1,15 @@ class LocalFunction { - fun test() { + suspend fun test() { fun fn1() = Helper.taint() fun fn2(s: String) = s Helper.sink(fn1()) Helper.sink(fn2(Helper.taint())) + + suspend fun fn3() = Helper.taint() + suspend fun fn4(s: String) = s + + Helper.sink(fn3()) + Helper.sink(fn4(Helper.taint())) } } diff --git a/java/ql/test/kotlin/library-tests/dataflow/func/samConversion.kt b/java/ql/test/kotlin/library-tests/dataflow/func/samConversion.kt index 26b2b817773..1f49f17837c 100644 --- a/java/ql/test/kotlin/library-tests/dataflow/func/samConversion.kt +++ b/java/ql/test/kotlin/library-tests/dataflow/func/samConversion.kt @@ -2,12 +2,22 @@ fun interface Predicate { fun go(s: String): String } +fun interface PredicateSusp { + suspend fun go(s: String): String +} + class SamConversion { - fun test() { + suspend fun test() { val p1 = Predicate { Helper.taint() } val p2 = Predicate { it -> it } Helper.sink(p1.go("")) - Helper.sink(p1.go(Helper.taint())) + Helper.sink(p2.go(Helper.taint())) + + val p3 = PredicateSusp { Helper.taint() } + val p4 = PredicateSusp { it -> it } + + Helper.sink(p3.go("")) + Helper.sink(p4.go(Helper.taint())) } } diff --git a/java/ql/test/kotlin/library-tests/dataflow/func/test.expected b/java/ql/test/kotlin/library-tests/dataflow/func/test.expected index 17717c27037..980d7c94215 100644 --- a/java/ql/test/kotlin/library-tests/dataflow/func/test.expected +++ b/java/ql/test/kotlin/library-tests/dataflow/func/test.expected @@ -1,18 +1,22 @@ | functionReference.kt:8:59:8:65 | taint(...) | functionReference.kt:8:33:8:66 | process(...) | -| functionReference.kt:9:78:9:84 | taint(...) | functionReference.kt:9:33:9:85 | process(...) | -| functionReference.kt:11:55:11:61 | taint(...) | functionReference.kt:11:33:11:62 | process(...) | -| functionReference.kt:18:24:18:30 | taint(...) | functionReference.kt:14:33:14:51 | process(...) | +| functionReference.kt:10:78:10:84 | taint(...) | functionReference.kt:10:33:10:85 | process(...) | +| functionReference.kt:12:55:12:61 | taint(...) | functionReference.kt:12:33:12:62 | process(...) | +| functionReference.kt:19:24:19:30 | taint(...) | functionReference.kt:15:33:15:51 | process(...) | | lambda.kt:4:64:4:70 | taint(...) | lambda.kt:4:33:4:77 | process(...) | -| lambda.kt:5:60:5:66 | taint(...) | lambda.kt:5:33:5:67 | process(...) | -| lambda.kt:6:69:6:75 | taint(...) | lambda.kt:6:33:6:76 | process(...) | -| lambda.kt:9:81:9:87 | taint(...) | lambda.kt:9:33:9:88 | processExt(...) | -| lambda.kt:10:66:10:72 | taint(...) | lambda.kt:10:33:10:91 | processExt(...) | -| lambda.kt:13:145:13:151 | taint(...) | lambda.kt:13:33:13:170 | process(...) | -| lambda.kt:14:163:14:169 | taint(...) | lambda.kt:14:33:14:170 | process(...) | -| lambda.kt:27:35:27:41 | taint(...) | lambda.kt:27:21:27:60 | invoke(...) | -| lambda.kt:29:43:29:49 | taint(...) | lambda.kt:29:21:29:69 | invoke(...) | -| lambda.kt:30:61:30:67 | taint(...) | lambda.kt:30:21:30:69 | invoke(...) | +| lambda.kt:6:60:6:66 | taint(...) | lambda.kt:6:33:6:67 | process(...) | +| lambda.kt:7:69:7:75 | taint(...) | lambda.kt:7:33:7:76 | process(...) | +| lambda.kt:10:81:10:87 | taint(...) | lambda.kt:10:33:10:88 | processExt(...) | +| lambda.kt:11:66:11:72 | taint(...) | lambda.kt:11:33:11:91 | processExt(...) | +| lambda.kt:14:145:14:151 | taint(...) | lambda.kt:14:33:14:170 | process(...) | +| lambda.kt:15:163:15:169 | taint(...) | lambda.kt:15:33:15:170 | process(...) | +| lambda.kt:28:35:28:41 | taint(...) | lambda.kt:28:21:28:60 | invoke(...) | +| lambda.kt:30:43:30:49 | taint(...) | lambda.kt:30:21:30:69 | invoke(...) | +| lambda.kt:31:61:31:67 | taint(...) | lambda.kt:31:21:31:69 | invoke(...) | | localFunction.kt:3:28:3:34 | taint(...) | localFunction.kt:6:21:6:25 | fn1(...) | | localFunction.kt:7:32:7:38 | taint(...) | localFunction.kt:7:21:7:39 | fn2(...) | -| samConversion.kt:7:37:7:43 | taint(...) | samConversion.kt:10:24:10:29 | go(...) | -| samConversion.kt:7:37:7:43 | taint(...) | samConversion.kt:11:24:11:41 | go(...) | +| localFunction.kt:9:36:9:42 | taint(...) | localFunction.kt:12:21:12:25 | fn3(...) | +| localFunction.kt:13:32:13:38 | taint(...) | localFunction.kt:13:21:13:39 | fn4(...) | +| samConversion.kt:11:37:11:43 | taint(...) | samConversion.kt:14:24:14:29 | go(...) | +| samConversion.kt:15:34:15:40 | taint(...) | samConversion.kt:15:24:15:41 | go(...) | +| samConversion.kt:17:41:17:47 | taint(...) | samConversion.kt:20:24:20:29 | go(...) | +| samConversion.kt:21:34:21:40 | taint(...) | samConversion.kt:21:24:21:41 | go(...) | diff --git a/java/ql/test/kotlin/library-tests/dataflow/func/util.kt b/java/ql/test/kotlin/library-tests/dataflow/func/util.kt index f99a8eb361b..aaf507e8aaf 100644 --- a/java/ql/test/kotlin/library-tests/dataflow/func/util.kt +++ b/java/ql/test/kotlin/library-tests/dataflow/func/util.kt @@ -7,6 +7,10 @@ class Processor { return f(arg) } + suspend fun processSusp(f: suspend (T) -> R2, arg: T) : R2 { + return f(arg) + } + fun process(f: (T0, T1) -> R3, arg0: T0, arg1: T1) : R3 { return f(arg0, arg1) } diff --git a/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected b/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected index 785a79aab08..2a7da9322fc 100644 --- a/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected @@ -4620,6 +4620,382 @@ funcExprs.kt: # 59| 5: [BlockStmt] { ... } # 59| 0: [ReturnStmt] return ... # 59| 0: [IntegerLiteral] 5 +# 82| 16: [Method] fn +# 82| 3: [TypeAccess] Unit +# 82| 5: [BlockStmt] { ... } +# 83| 0: [LocalVariableDeclStmt] var ...; +# 83| 1: [LocalVariableDeclExpr] l1 +# 83| 0: [LambdaExpr] ...->... +# 83| -4: [AnonymousClass] new Function1(...) { ... } +# 83| 1: [Constructor] +# 83| 5: [BlockStmt] { ... } +# 83| 0: [SuperConstructorInvocationStmt] super(...) +# 83| 2: [Method] invoke +# 83| 3: [TypeAccess] String +#-----| 4: (Parameters) +# 83| 0: [Parameter] i +# 83| 0: [TypeAccess] int +# 83| 5: [BlockStmt] { ... } +# 83| 0: [ReturnStmt] return ... +# 83| 0: [MethodAccess] toString(...) +# 83| -1: [VarAccess] i +# 83| -3: [TypeAccess] Function1 +# 83| 0: [TypeAccess] Integer +# 83| 1: [TypeAccess] String +# 84| 1: [ExprStmt] ; +# 84| 0: [ImplicitCoercionToUnitExpr] +# 84| 0: [TypeAccess] Unit +# 84| 1: [MethodAccess] invoke(...) +# 84| -1: [VarAccess] l1 +# 84| 0: [IntegerLiteral] 5 +# 86| 2: [LocalVariableDeclStmt] var ...; +# 86| 1: [LocalVariableDeclExpr] l2 +# 86| 0: [LambdaExpr] ...->... +# 86| -4: [AnonymousClass] new Function1(...) { ... } +# 86| 1: [Constructor] +# 86| 5: [BlockStmt] { ... } +# 86| 0: [SuperConstructorInvocationStmt] super(...) +# 86| 2: [Method] invoke +# 86| 3: [TypeAccess] String +#-----| 4: (Parameters) +# 86| 0: [Parameter] i +# 86| 0: [TypeAccess] int +# 86| 5: [BlockStmt] { ... } +# 86| 0: [ReturnStmt] return ... +# 86| 0: [MethodAccess] toString(...) +# 86| -1: [VarAccess] i +# 86| -3: [TypeAccess] Function1 +# 86| 0: [TypeAccess] Integer +# 86| 1: [TypeAccess] String +# 87| 3: [ExprStmt] ; +# 87| 0: [ImplicitCoercionToUnitExpr] +# 87| 0: [TypeAccess] Unit +# 87| 1: [MethodAccess] invoke(...) +# 87| -1: [VarAccess] l2 +# 87| 0: [IntegerLiteral] 5 +# 89| 4: [LocalVariableDeclStmt] var ...; +# 89| 1: [LocalVariableDeclExpr] l3 +# 90| 0: [LambdaExpr] ...->... +# 90| -4: [AnonymousClass] new FunctionN(...) { ... } +# 90| 1: [Constructor] +# 90| 5: [BlockStmt] { ... } +# 90| 0: [SuperConstructorInvocationStmt] super(...) +# 90| 2: [Method] invoke +# 90| 3: [TypeAccess] String +#-----| 4: (Parameters) +# 90| 0: [Parameter] p0 +# 90| 0: [TypeAccess] int +# 90| 1: [Parameter] p1 +# 90| 0: [TypeAccess] int +# 90| 2: [Parameter] p2 +# 90| 0: [TypeAccess] int +# 90| 3: [Parameter] p3 +# 90| 0: [TypeAccess] int +# 90| 4: [Parameter] p4 +# 90| 0: [TypeAccess] int +# 90| 5: [Parameter] p5 +# 90| 0: [TypeAccess] int +# 90| 6: [Parameter] p6 +# 90| 0: [TypeAccess] int +# 90| 7: [Parameter] p7 +# 90| 0: [TypeAccess] int +# 90| 8: [Parameter] p8 +# 90| 0: [TypeAccess] int +# 90| 9: [Parameter] p9 +# 90| 0: [TypeAccess] int +# 90| 10: [Parameter] p10 +# 90| 0: [TypeAccess] int +# 90| 11: [Parameter] p11 +# 90| 0: [TypeAccess] int +# 90| 12: [Parameter] p12 +# 90| 0: [TypeAccess] int +# 90| 13: [Parameter] p13 +# 90| 0: [TypeAccess] int +# 90| 14: [Parameter] p14 +# 90| 0: [TypeAccess] int +# 90| 15: [Parameter] p15 +# 90| 0: [TypeAccess] int +# 90| 16: [Parameter] p16 +# 90| 0: [TypeAccess] int +# 90| 17: [Parameter] p17 +# 90| 0: [TypeAccess] int +# 90| 18: [Parameter] p18 +# 90| 0: [TypeAccess] int +# 90| 19: [Parameter] p19 +# 90| 0: [TypeAccess] int +# 90| 20: [Parameter] p20 +# 90| 0: [TypeAccess] int +# 90| 21: [Parameter] p21 +# 90| 0: [TypeAccess] int +# 90| 22: [Parameter] p22 +# 90| 0: [TypeAccess] int +# 90| 5: [BlockStmt] { ... } +# 90| 0: [ReturnStmt] return ... +# 90| 0: [StringLiteral] +# 90| 2: [Method] invoke +#-----| 4: (Parameters) +# 90| 0: [Parameter] a0 +# 90| 5: [BlockStmt] { ... } +# 90| 0: [ReturnStmt] return ... +# 90| 0: [MethodAccess] invoke(...) +# 90| -1: [ThisAccess] this +# 90| 0: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 0 +# 90| 1: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 1 +# 90| 2: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 2 +# 90| 3: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 3 +# 90| 4: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 4 +# 90| 5: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 5 +# 90| 6: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 6 +# 90| 7: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 7 +# 90| 8: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 8 +# 90| 9: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 9 +# 90| 10: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 10 +# 90| 11: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 11 +# 90| 12: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 12 +# 90| 13: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 13 +# 90| 14: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 14 +# 90| 15: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 15 +# 90| 16: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 16 +# 90| 17: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 17 +# 90| 18: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 18 +# 90| 19: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 19 +# 90| 20: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 20 +# 90| 21: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 21 +# 90| 22: [CastExpr] (...)... +# 90| 0: [TypeAccess] int +# 90| 1: [ArrayAccess] ...[...] +# 90| 0: [VarAccess] a0 +# 90| 1: [IntegerLiteral] 22 +# 90| -3: [TypeAccess] FunctionN +# 90| 0: [TypeAccess] String +# 91| 5: [ExprStmt] ; +# 91| 0: [ImplicitCoercionToUnitExpr] +# 91| 0: [TypeAccess] Unit +# 91| 1: [MethodAccess] invoke(...) +# 91| -1: [VarAccess] l3 +# 91| 0: [ArrayCreationExpr] new Object[] +# 91| -2: [ArrayInit] {...} +# 91| 0: [IntegerLiteral] 1 +# 91| 1: [IntegerLiteral] 2 +# 91| 2: [IntegerLiteral] 3 +# 91| 3: [IntegerLiteral] 4 +# 91| 4: [IntegerLiteral] 5 +# 91| 5: [IntegerLiteral] 6 +# 91| 6: [IntegerLiteral] 7 +# 91| 7: [IntegerLiteral] 8 +# 91| 8: [IntegerLiteral] 9 +# 91| 9: [IntegerLiteral] 0 +# 91| 10: [IntegerLiteral] 1 +# 91| 11: [IntegerLiteral] 2 +# 91| 12: [IntegerLiteral] 3 +# 91| 13: [IntegerLiteral] 4 +# 91| 14: [IntegerLiteral] 5 +# 91| 15: [IntegerLiteral] 6 +# 91| 16: [IntegerLiteral] 7 +# 91| 17: [IntegerLiteral] 8 +# 91| 18: [IntegerLiteral] 9 +# 91| 19: [IntegerLiteral] 0 +# 91| 20: [IntegerLiteral] 1 +# 91| 21: [IntegerLiteral] 2 +# 91| 22: [IntegerLiteral] 3 +# 91| -1: [TypeAccess] Object +# 91| 0: [IntegerLiteral] 23 +# 93| 6: [LocalVariableDeclStmt] var ...; +# 93| 1: [LocalVariableDeclExpr] l4 +# 94| 0: [LambdaExpr] ...->... +# 94| -4: [AnonymousClass] new Function22(...) { ... } +# 94| 1: [Constructor] +# 94| 5: [BlockStmt] { ... } +# 94| 0: [SuperConstructorInvocationStmt] super(...) +# 94| 2: [Method] invoke +# 94| 3: [TypeAccess] String +#-----| 4: (Parameters) +# 94| 0: [Parameter] p0 +# 94| 0: [TypeAccess] int +# 94| 1: [Parameter] p1 +# 94| 0: [TypeAccess] int +# 94| 2: [Parameter] p2 +# 94| 0: [TypeAccess] int +# 94| 3: [Parameter] p3 +# 94| 0: [TypeAccess] int +# 94| 4: [Parameter] p4 +# 94| 0: [TypeAccess] int +# 94| 5: [Parameter] p5 +# 94| 0: [TypeAccess] int +# 94| 6: [Parameter] p6 +# 94| 0: [TypeAccess] int +# 94| 7: [Parameter] p7 +# 94| 0: [TypeAccess] int +# 94| 8: [Parameter] p8 +# 94| 0: [TypeAccess] int +# 94| 9: [Parameter] p9 +# 94| 0: [TypeAccess] int +# 94| 10: [Parameter] p10 +# 94| 0: [TypeAccess] int +# 94| 11: [Parameter] p11 +# 94| 0: [TypeAccess] int +# 94| 12: [Parameter] p12 +# 94| 0: [TypeAccess] int +# 94| 13: [Parameter] p13 +# 94| 0: [TypeAccess] int +# 94| 14: [Parameter] p14 +# 94| 0: [TypeAccess] int +# 94| 15: [Parameter] p15 +# 94| 0: [TypeAccess] int +# 94| 16: [Parameter] p16 +# 94| 0: [TypeAccess] int +# 94| 17: [Parameter] p17 +# 94| 0: [TypeAccess] int +# 94| 18: [Parameter] p18 +# 94| 0: [TypeAccess] int +# 94| 19: [Parameter] p19 +# 94| 0: [TypeAccess] int +# 94| 20: [Parameter] p20 +# 94| 0: [TypeAccess] int +# 94| 21: [Parameter] p21 +# 94| 0: [TypeAccess] int +# 94| 5: [BlockStmt] { ... } +# 94| 0: [ReturnStmt] return ... +# 94| 0: [StringLiteral] +# 94| -3: [TypeAccess] Function22 +# 94| 0: [TypeAccess] Integer +# 94| 1: [TypeAccess] Integer +# 94| 2: [TypeAccess] Integer +# 94| 3: [TypeAccess] Integer +# 94| 4: [TypeAccess] Integer +# 94| 5: [TypeAccess] Integer +# 94| 6: [TypeAccess] Integer +# 94| 7: [TypeAccess] Integer +# 94| 8: [TypeAccess] Integer +# 94| 9: [TypeAccess] Integer +# 94| 10: [TypeAccess] Integer +# 94| 11: [TypeAccess] Integer +# 94| 12: [TypeAccess] Integer +# 94| 13: [TypeAccess] Integer +# 94| 14: [TypeAccess] Integer +# 94| 15: [TypeAccess] Integer +# 94| 16: [TypeAccess] Integer +# 94| 17: [TypeAccess] Integer +# 94| 18: [TypeAccess] Integer +# 94| 19: [TypeAccess] Integer +# 94| 20: [TypeAccess] Integer +# 94| 21: [TypeAccess] Integer +# 94| 22: [TypeAccess] String +# 95| 7: [ExprStmt] ; +# 95| 0: [ImplicitCoercionToUnitExpr] +# 95| 0: [TypeAccess] Unit +# 95| 1: [MethodAccess] invoke(...) +# 95| -1: [VarAccess] l4 +# 95| 0: [IntegerLiteral] 1 +# 95| 1: [IntegerLiteral] 2 +# 95| 2: [IntegerLiteral] 3 +# 95| 3: [IntegerLiteral] 4 +# 95| 4: [IntegerLiteral] 5 +# 95| 5: [IntegerLiteral] 6 +# 95| 6: [IntegerLiteral] 7 +# 95| 7: [IntegerLiteral] 8 +# 95| 8: [IntegerLiteral] 9 +# 95| 9: [IntegerLiteral] 0 +# 95| 10: [IntegerLiteral] 1 +# 95| 11: [IntegerLiteral] 2 +# 95| 12: [IntegerLiteral] 3 +# 95| 13: [IntegerLiteral] 4 +# 95| 14: [IntegerLiteral] 5 +# 95| 15: [IntegerLiteral] 6 +# 95| 16: [IntegerLiteral] 7 +# 95| 17: [IntegerLiteral] 8 +# 95| 18: [IntegerLiteral] 9 +# 95| 19: [IntegerLiteral] 0 +# 95| 20: [IntegerLiteral] 1 +# 95| 21: [IntegerLiteral] 2 # 54| 2: [Class] MyLambda # 54| 1: [Constructor] MyLambda # 54| 5: [BlockStmt] { ... } @@ -5884,6 +6260,68 @@ samConversion.kt: # 46| -3: [TypeAccess] Function1 # 46| 0: [TypeAccess] Integer # 46| 1: [TypeAccess] Boolean +# 57| 5: [Method] test +# 57| 3: [TypeAccess] Unit +# 57| 5: [BlockStmt] { ... } +# 58| 0: [LocalVariableDeclStmt] var ...; +# 58| 1: [LocalVariableDeclExpr] i0 +# 58| 0: [CastExpr] (...)... +# 58| 0: [TypeAccess] InterfaceFn1Sus +# 58| 1: [ClassInstanceExpr] new (...) +# 58| -4: [AnonymousClass] new InterfaceFn1Sus(...) { ... } +# 58| 1: [Constructor] +#-----| 4: (Parameters) +# 58| 0: [Parameter] +# 58| 5: [BlockStmt] { ... } +# 58| 0: [SuperConstructorInvocationStmt] super(...) +# 58| 1: [ExprStmt] ; +# 58| 0: [AssignExpr] ...=... +# 58| 0: [VarAccess] this. +# 58| -1: [ThisAccess] this +# 58| 1: [VarAccess] +# 58| 2: [FieldDeclaration] Function2 ; +# 58| -1: [TypeAccess] Function2 +# 58| 0: [TypeAccess] Integer +# 58| 1: [TypeAccess] Integer +# 58| 2: [TypeAccess] Unit +# 58| 3: [Method] fn1 +# 58| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 58| 0: [Parameter] i +# 58| 0: [TypeAccess] int +# 58| 1: [Parameter] j +# 58| 0: [TypeAccess] int +# 58| 5: [BlockStmt] { ... } +# 58| 0: [ReturnStmt] return ... +# 58| 0: [MethodAccess] invoke(...) +# 58| -1: [VarAccess] +# 58| 0: [VarAccess] i +# 58| 1: [VarAccess] j +# 58| -3: [TypeAccess] InterfaceFn1Sus +# 58| 0: [LambdaExpr] ...->... +# 58| -4: [AnonymousClass] new Function2(...) { ... } +# 58| 1: [Constructor] +# 58| 5: [BlockStmt] { ... } +# 58| 0: [SuperConstructorInvocationStmt] super(...) +# 58| 2: [Method] invoke +# 58| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 58| 0: [Parameter] a +# 58| 0: [TypeAccess] int +# 58| 1: [Parameter] b +# 58| 0: [TypeAccess] int +# 58| 5: [BlockStmt] { ... } +# 58| 0: [ExprStmt] ; +# 58| 0: [VarAccess] INSTANCE +# 58| -3: [TypeAccess] Function2 +# 58| 0: [TypeAccess] Integer +# 58| 1: [TypeAccess] Integer +# 58| 2: [TypeAccess] Unit +# 59| 1: [ExprStmt] ; +# 59| 0: [MethodAccess] fn1(...) +# 59| -1: [VarAccess] i0 +# 59| 0: [IntegerLiteral] 1 +# 59| 1: [IntegerLiteral] 2 # 16| 2: [Interface] IntPredicate # 17| 1: [Method] accept # 17| 3: [TypeAccess] boolean @@ -5964,6 +6402,14 @@ samConversion.kt: #-----| 4: (Parameters) # 50| 0: [Parameter] i # 50| 0: [TypeAccess] T +# 53| 7: [Interface] InterfaceFn1Sus +# 54| 1: [Method] fn1 +# 54| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 54| 0: [Parameter] i +# 54| 0: [TypeAccess] int +# 54| 1: [Parameter] j +# 54| 0: [TypeAccess] int whenExpr.kt: # 0| [CompilationUnit] whenExpr # 0| 1: [Class] WhenExprKt diff --git a/java/ql/test/kotlin/library-tests/exprs/exprs.expected b/java/ql/test/kotlin/library-tests/exprs/exprs.expected index 06adff46fbf..95edf5abf1b 100644 --- a/java/ql/test/kotlin/library-tests/exprs/exprs.expected +++ b/java/ql/test/kotlin/library-tests/exprs/exprs.expected @@ -2917,6 +2917,288 @@ | funcExprs.kt:77:20:77:55 | Generic | file://:0:0:0:0 | | TypeAccess | | funcExprs.kt:77:20:77:55 | Integer | file://:0:0:0:0 | | TypeAccess | | funcExprs.kt:77:20:77:55 | String | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:82:9:96:1 | Unit | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:83:5:83:51 | l1 | funcExprs.kt:82:9:96:1 | fn | LocalVariableDeclExpr | +| funcExprs.kt:83:31:83:51 | ...->... | funcExprs.kt:82:9:96:1 | fn | LambdaExpr | +| funcExprs.kt:83:31:83:51 | Function1 | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:83:31:83:51 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:83:31:83:51 | String | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:83:31:83:51 | String | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:83:33:83:33 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:83:38:83:38 | i | funcExprs.kt:83:31:83:51 | invoke | VarAccess | +| funcExprs.kt:83:40:83:49 | toString(...) | funcExprs.kt:83:31:83:51 | invoke | MethodAccess | +| funcExprs.kt:84:5:84:6 | l1 | funcExprs.kt:82:9:96:1 | fn | VarAccess | +| funcExprs.kt:84:8:84:16 | | funcExprs.kt:82:9:96:1 | fn | ImplicitCoercionToUnitExpr | +| funcExprs.kt:84:8:84:16 | Unit | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:84:8:84:16 | invoke(...) | funcExprs.kt:82:9:96:1 | fn | MethodAccess | +| funcExprs.kt:84:15:84:15 | 5 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:86:5:86:59 | l2 | funcExprs.kt:82:9:96:1 | fn | LocalVariableDeclExpr | +| funcExprs.kt:86:39:86:59 | ...->... | funcExprs.kt:82:9:96:1 | fn | LambdaExpr | +| funcExprs.kt:86:39:86:59 | Function1 | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:86:39:86:59 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:86:39:86:59 | String | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:86:39:86:59 | String | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:86:41:86:41 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:86:46:86:46 | i | funcExprs.kt:86:39:86:59 | invoke | VarAccess | +| funcExprs.kt:86:48:86:57 | toString(...) | funcExprs.kt:86:39:86:59 | invoke | MethodAccess | +| funcExprs.kt:87:5:87:6 | l2 | funcExprs.kt:82:9:96:1 | fn | VarAccess | +| funcExprs.kt:87:8:87:16 | | funcExprs.kt:82:9:96:1 | fn | ImplicitCoercionToUnitExpr | +| funcExprs.kt:87:8:87:16 | Unit | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:87:8:87:16 | invoke(...) | funcExprs.kt:82:9:96:1 | fn | MethodAccess | +| funcExprs.kt:87:15:87:15 | 5 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:89:5:90:69 | l3 | funcExprs.kt:82:9:96:1 | fn | LocalVariableDeclExpr | +| funcExprs.kt:90:15:90:69 | 0 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 1 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 2 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 3 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 4 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 5 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 6 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 7 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 8 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 9 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 10 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 11 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 12 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 13 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 14 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 15 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 16 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 17 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 18 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 19 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 20 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 21 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | 22 | funcExprs.kt:90:15:90:69 | invoke | IntegerLiteral | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | (...)... | funcExprs.kt:90:15:90:69 | invoke | CastExpr | +| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:82:9:96:1 | fn | LambdaExpr | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | ...[...] | funcExprs.kt:90:15:90:69 | invoke | ArrayAccess | +| funcExprs.kt:90:15:90:69 | FunctionN | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:90:15:90:69 | String | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:15:90:69 | String | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | a0 | funcExprs.kt:90:15:90:69 | invoke | VarAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | int | funcExprs.kt:90:15:90:69 | invoke | TypeAccess | +| funcExprs.kt:90:15:90:69 | invoke(...) | funcExprs.kt:90:15:90:69 | invoke | MethodAccess | +| funcExprs.kt:90:15:90:69 | this | funcExprs.kt:90:15:90:69 | invoke | ThisAccess | +| funcExprs.kt:90:17:90:17 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:19:90:19 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:21:90:21 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:23:90:23 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:25:90:25 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:27:90:27 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:29:90:29 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:31:90:31 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:33:90:33 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:35:90:35 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:37:90:37 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:39:90:39 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:41:90:41 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:43:90:43 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:45:90:45 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:47:90:47 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:49:90:49 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:51:90:51 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:53:90:53 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:55:90:55 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:57:90:57 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:59:90:59 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:61:90:61 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:90:67:90:68 | | funcExprs.kt:90:15:90:69 | invoke | StringLiteral | +| funcExprs.kt:91:5:91:6 | l3 | funcExprs.kt:82:9:96:1 | fn | VarAccess | +| funcExprs.kt:91:8:91:60 | 23 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:8:91:60 | | funcExprs.kt:82:9:96:1 | fn | ImplicitCoercionToUnitExpr | +| funcExprs.kt:91:8:91:60 | Object | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:91:8:91:60 | Unit | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:91:8:91:60 | invoke(...) | funcExprs.kt:82:9:96:1 | fn | MethodAccess | +| funcExprs.kt:91:8:91:60 | new Object[] | funcExprs.kt:82:9:96:1 | fn | ArrayCreationExpr | +| funcExprs.kt:91:8:91:60 | {...} | funcExprs.kt:82:9:96:1 | fn | ArrayInit | +| funcExprs.kt:91:15:91:15 | 1 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:17:91:17 | 2 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:19:91:19 | 3 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:21:91:21 | 4 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:23:91:23 | 5 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:25:91:25 | 6 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:27:91:27 | 7 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:29:91:29 | 8 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:31:91:31 | 9 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:33:91:33 | 0 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:35:91:35 | 1 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:37:91:37 | 2 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:39:91:39 | 3 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:41:91:41 | 4 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:43:91:43 | 5 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:45:91:45 | 6 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:47:91:47 | 7 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:49:91:49 | 8 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:51:91:51 | 9 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:53:91:53 | 0 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:55:91:55 | 1 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:57:91:57 | 2 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:91:59:91:59 | 3 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:93:5:94:67 | l4 | funcExprs.kt:82:9:96:1 | fn | LocalVariableDeclExpr | +| funcExprs.kt:94:15:94:67 | ...->... | funcExprs.kt:82:9:96:1 | fn | LambdaExpr | +| funcExprs.kt:94:15:94:67 | Function22 | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | Integer | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:15:94:67 | String | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:15:94:67 | String | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:94:17:94:17 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:19:94:19 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:21:94:21 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:23:94:23 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:25:94:25 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:27:94:27 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:29:94:29 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:31:94:31 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:33:94:33 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:35:94:35 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:37:94:37 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:39:94:39 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:41:94:41 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:43:94:43 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:45:94:45 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:47:94:47 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:49:94:49 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:51:94:51 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:53:94:53 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:55:94:55 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:57:94:57 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:59:94:59 | int | file://:0:0:0:0 | | TypeAccess | +| funcExprs.kt:94:65:94:66 | | funcExprs.kt:94:15:94:67 | invoke | StringLiteral | +| funcExprs.kt:95:5:95:6 | l4 | funcExprs.kt:82:9:96:1 | fn | VarAccess | +| funcExprs.kt:95:8:95:58 | | funcExprs.kt:82:9:96:1 | fn | ImplicitCoercionToUnitExpr | +| funcExprs.kt:95:8:95:58 | Unit | funcExprs.kt:82:9:96:1 | fn | TypeAccess | +| funcExprs.kt:95:8:95:58 | invoke(...) | funcExprs.kt:82:9:96:1 | fn | MethodAccess | +| funcExprs.kt:95:15:95:15 | 1 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:17:95:17 | 2 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:19:95:19 | 3 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:21:95:21 | 4 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:23:95:23 | 5 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:25:95:25 | 6 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:27:95:27 | 7 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:29:95:29 | 8 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:31:95:31 | 9 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:33:95:33 | 0 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:35:95:35 | 1 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:37:95:37 | 2 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:39:95:39 | 3 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:41:95:41 | 4 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:43:95:43 | 5 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:45:95:45 | 6 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:47:95:47 | 7 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:49:95:49 | 8 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:51:95:51 | 9 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:53:95:53 | 0 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:55:95:55 | 1 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | +| funcExprs.kt:95:57:95:57 | 2 | funcExprs.kt:82:9:96:1 | fn | IntegerLiteral | | kFunctionInvoke.kt:4:5:4:24 | Unit | file://:0:0:0:0 | | TypeAccess | | kFunctionInvoke.kt:4:11:4:19 | String | file://:0:0:0:0 | | TypeAccess | | kFunctionInvoke.kt:7:1:10:1 | Unit | file://:0:0:0:0 | | TypeAccess | @@ -3632,6 +3914,43 @@ | samConversion.kt:46:39:46:42 | true | samConversion.kt:46:32:46:44 | invoke | BooleanLiteral | | samConversion.kt:50:5:50:25 | boolean | file://:0:0:0:0 | | TypeAccess | | samConversion.kt:50:12:50:15 | T | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:54:13:54:35 | Unit | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:54:21:54:26 | int | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:54:29:54:34 | int | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:57:9:60:1 | Unit | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:5:58:45 | i0 | samConversion.kt:57:9:60:1 | test | LocalVariableDeclExpr | +| samConversion.kt:58:14:58:45 | (...)... | samConversion.kt:57:9:60:1 | test | CastExpr | +| samConversion.kt:58:14:58:45 | ...=... | samConversion.kt:58:14:58:45 | | AssignExpr | +| samConversion.kt:58:14:58:45 | | samConversion.kt:58:14:58:45 | | VarAccess | +| samConversion.kt:58:14:58:45 | | samConversion.kt:58:14:58:45 | fn1 | VarAccess | +| samConversion.kt:58:14:58:45 | Function2 | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:14:58:45 | Integer | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:14:58:45 | Integer | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:14:58:45 | InterfaceFn1Sus | samConversion.kt:57:9:60:1 | test | TypeAccess | +| samConversion.kt:58:14:58:45 | InterfaceFn1Sus | samConversion.kt:57:9:60:1 | test | TypeAccess | +| samConversion.kt:58:14:58:45 | Unit | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:14:58:45 | Unit | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:14:58:45 | i | samConversion.kt:58:14:58:45 | fn1 | VarAccess | +| samConversion.kt:58:14:58:45 | int | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:14:58:45 | int | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:14:58:45 | invoke(...) | samConversion.kt:58:14:58:45 | fn1 | MethodAccess | +| samConversion.kt:58:14:58:45 | j | samConversion.kt:58:14:58:45 | fn1 | VarAccess | +| samConversion.kt:58:14:58:45 | new (...) | samConversion.kt:57:9:60:1 | test | ClassInstanceExpr | +| samConversion.kt:58:14:58:45 | this | samConversion.kt:58:14:58:45 | | ThisAccess | +| samConversion.kt:58:14:58:45 | this. | samConversion.kt:58:14:58:45 | | VarAccess | +| samConversion.kt:58:30:58:45 | ...->... | samConversion.kt:57:9:60:1 | test | LambdaExpr | +| samConversion.kt:58:30:58:45 | Function2 | samConversion.kt:57:9:60:1 | test | TypeAccess | +| samConversion.kt:58:30:58:45 | Integer | samConversion.kt:57:9:60:1 | test | TypeAccess | +| samConversion.kt:58:30:58:45 | Integer | samConversion.kt:57:9:60:1 | test | TypeAccess | +| samConversion.kt:58:30:58:45 | Unit | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:30:58:45 | Unit | samConversion.kt:57:9:60:1 | test | TypeAccess | +| samConversion.kt:58:32:58:32 | int | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:35:58:35 | int | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:58:40:58:43 | INSTANCE | samConversion.kt:58:30:58:45 | invoke | VarAccess | +| samConversion.kt:59:5:59:6 | i0 | samConversion.kt:57:9:60:1 | test | VarAccess | +| samConversion.kt:59:8:59:15 | fn1(...) | samConversion.kt:57:9:60:1 | test | MethodAccess | +| samConversion.kt:59:12:59:12 | 1 | samConversion.kt:57:9:60:1 | test | IntegerLiteral | +| samConversion.kt:59:14:59:14 | 2 | samConversion.kt:57:9:60:1 | test | IntegerLiteral | | whenExpr.kt:1:1:9:1 | int | file://:0:0:0:0 | | TypeAccess | | whenExpr.kt:1:14:1:19 | int | file://:0:0:0:0 | | TypeAccess | | whenExpr.kt:2:10:8:3 | | whenExpr.kt:1:1:9:1 | testWhen | StmtExpr | diff --git a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected index 085483b8219..8b4da235ba0 100644 --- a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected +++ b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected @@ -15,6 +15,10 @@ lambdaExpr | funcExprs.kt:35:29:35:112 | ...->... | stmt body | funcExprs.kt:35:29:35:112 | invoke | invoke(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int) | funcExprs.kt:35:29:35:112 | new Function22(...) { ... } | | funcExprs.kt:36:29:36:117 | ...->... | stmt body | funcExprs.kt:36:29:36:117 | invoke | invoke(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int) | funcExprs.kt:36:29:36:117 | new FunctionN(...) { ... } | | funcExprs.kt:75:12:75:22 | ...->... | stmt body | funcExprs.kt:75:12:75:22 | invoke | invoke(Class3.Generic) | funcExprs.kt:75:12:75:22 | new Function1>,String>(...) { ... } | +| funcExprs.kt:83:31:83:51 | ...->... | stmt body | funcExprs.kt:83:31:83:51 | invoke | invoke(int) | funcExprs.kt:83:31:83:51 | new Function1(...) { ... } | +| funcExprs.kt:86:39:86:59 | ...->... | stmt body | funcExprs.kt:86:39:86:59 | invoke | invoke(int) | funcExprs.kt:86:39:86:59 | new Function1(...) { ... } | +| funcExprs.kt:90:15:90:69 | ...->... | stmt body | funcExprs.kt:90:15:90:69 | invoke | invoke(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int) | funcExprs.kt:90:15:90:69 | new FunctionN(...) { ... } | +| funcExprs.kt:94:15:94:67 | ...->... | stmt body | funcExprs.kt:94:15:94:67 | invoke | invoke(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int) | funcExprs.kt:94:15:94:67 | new Function22(...) { ... } | | samConversion.kt:2:31:2:45 | ...->... | stmt body | samConversion.kt:2:31:2:45 | invoke | invoke(int) | samConversion.kt:2:31:2:45 | new Function1(...) { ... } | | samConversion.kt:4:27:4:42 | ...->... | stmt body | samConversion.kt:4:27:4:42 | invoke | invoke(int,int) | samConversion.kt:4:27:4:42 | new Function2(...) { ... } | | samConversion.kt:7:29:7:46 | ...->... | stmt body | samConversion.kt:7:29:7:46 | invoke | invoke(java.lang.String,int) | samConversion.kt:7:29:7:46 | new Function2(...) { ... } | @@ -22,6 +26,7 @@ lambdaExpr | samConversion.kt:11:12:13:5 | ...->... | stmt body | samConversion.kt:11:12:13:5 | invoke | invoke(int) | samConversion.kt:11:12:13:5 | new Function1(...) { ... } | | samConversion.kt:43:31:45:68 | ...->... | stmt body | samConversion.kt:43:31:45:68 | invoke | invoke(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int) | samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | | samConversion.kt:46:32:46:44 | ...->... | stmt body | samConversion.kt:46:32:46:44 | invoke | invoke(int) | samConversion.kt:46:32:46:44 | new Function1(...) { ... } | +| samConversion.kt:58:30:58:45 | ...->... | stmt body | samConversion.kt:58:30:58:45 | invoke | invoke(int,int) | samConversion.kt:58:30:58:45 | new Function2(...) { ... } | memberRefExprs | funcExprs.kt:38:26:38:38 | ...::... | funcExprs.kt:38:26:38:38 | invoke | invoke() | funcExprs.kt:38:26:38:38 | new Function0(...) { ... } | | funcExprs.kt:39:26:39:36 | ...::... | funcExprs.kt:39:26:39:36 | invoke | invoke() | funcExprs.kt:39:26:39:36 | new Function0(...) { ... } | @@ -38,54 +43,38 @@ memberRefExprs | samConversion.kt:5:27:5:31 | ...::... | samConversion.kt:5:27:5:31 | invoke | invoke(int,int) | samConversion.kt:5:27:5:31 | new Function2(...) { ... } | | samConversion.kt:41:13:41:16 | ...::... | samConversion.kt:41:13:41:16 | invoke | invoke(java.lang.Object[]) | samConversion.kt:41:13:41:16 | new FunctionN(...) { ... } | modifiers -| delegatedProperties.kt:6:32:9:9 | ...->... | delegatedProperties.kt:6:32:9:9 | invoke | override | -| delegatedProperties.kt:6:32:9:9 | ...->... | delegatedProperties.kt:6:32:9:9 | invoke | public | -| funcExprs.kt:22:26:22:33 | ...->... | funcExprs.kt:22:26:22:33 | invoke | override | -| funcExprs.kt:22:26:22:33 | ...->... | funcExprs.kt:22:26:22:33 | invoke | public | -| funcExprs.kt:23:26:23:33 | ...->... | funcExprs.kt:23:26:23:33 | invoke | override | -| funcExprs.kt:23:26:23:33 | ...->... | funcExprs.kt:23:26:23:33 | invoke | public | -| funcExprs.kt:24:26:24:33 | ...->... | funcExprs.kt:24:26:24:33 | invoke | override | -| funcExprs.kt:24:26:24:33 | ...->... | funcExprs.kt:24:26:24:33 | invoke | public | -| funcExprs.kt:25:29:25:38 | ...->... | funcExprs.kt:25:29:25:38 | invoke | override | -| funcExprs.kt:25:29:25:38 | ...->... | funcExprs.kt:25:29:25:38 | invoke | public | -| funcExprs.kt:26:29:26:34 | ...->... | funcExprs.kt:26:29:26:34 | invoke | override | -| funcExprs.kt:26:29:26:34 | ...->... | funcExprs.kt:26:29:26:34 | invoke | public | -| funcExprs.kt:27:29:27:42 | ...->... | funcExprs.kt:27:29:27:42 | invoke | override | -| funcExprs.kt:27:29:27:42 | ...->... | funcExprs.kt:27:29:27:42 | invoke | public | -| funcExprs.kt:29:29:29:37 | ...->... | funcExprs.kt:29:29:29:37 | invoke | override | -| funcExprs.kt:29:29:29:37 | ...->... | funcExprs.kt:29:29:29:37 | invoke | public | -| funcExprs.kt:30:28:30:50 | ...->... | funcExprs.kt:30:28:30:50 | invoke | override | -| funcExprs.kt:30:28:30:50 | ...->... | funcExprs.kt:30:28:30:50 | invoke | public | -| funcExprs.kt:31:28:31:40 | ...->... | funcExprs.kt:31:28:31:40 | invoke | override | -| funcExprs.kt:31:28:31:40 | ...->... | funcExprs.kt:31:28:31:40 | invoke | public | -| funcExprs.kt:32:28:32:44 | ...->... | funcExprs.kt:32:28:32:44 | invoke | override | -| funcExprs.kt:32:28:32:44 | ...->... | funcExprs.kt:32:28:32:44 | invoke | public | -| funcExprs.kt:33:28:33:51 | ...->... | funcExprs.kt:33:28:33:51 | invoke | override | -| funcExprs.kt:33:28:33:51 | ...->... | funcExprs.kt:33:28:33:51 | invoke | public | -| funcExprs.kt:33:37:33:47 | ...->... | funcExprs.kt:33:37:33:47 | invoke | override | -| funcExprs.kt:33:37:33:47 | ...->... | funcExprs.kt:33:37:33:47 | invoke | public | -| funcExprs.kt:35:29:35:112 | ...->... | funcExprs.kt:35:29:35:112 | invoke | override | -| funcExprs.kt:35:29:35:112 | ...->... | funcExprs.kt:35:29:35:112 | invoke | public | -| funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | override | +| delegatedProperties.kt:6:32:9:9 | ...->... | delegatedProperties.kt:6:32:9:9 | invoke | override, public | +| funcExprs.kt:22:26:22:33 | ...->... | funcExprs.kt:22:26:22:33 | invoke | override, public | +| funcExprs.kt:23:26:23:33 | ...->... | funcExprs.kt:23:26:23:33 | invoke | override, public | +| funcExprs.kt:24:26:24:33 | ...->... | funcExprs.kt:24:26:24:33 | invoke | override, public | +| funcExprs.kt:25:29:25:38 | ...->... | funcExprs.kt:25:29:25:38 | invoke | override, public | +| funcExprs.kt:26:29:26:34 | ...->... | funcExprs.kt:26:29:26:34 | invoke | override, public | +| funcExprs.kt:27:29:27:42 | ...->... | funcExprs.kt:27:29:27:42 | invoke | override, public | +| funcExprs.kt:29:29:29:37 | ...->... | funcExprs.kt:29:29:29:37 | invoke | override, public | +| funcExprs.kt:30:28:30:50 | ...->... | funcExprs.kt:30:28:30:50 | invoke | override, public | +| funcExprs.kt:31:28:31:40 | ...->... | funcExprs.kt:31:28:31:40 | invoke | override, public | +| funcExprs.kt:32:28:32:44 | ...->... | funcExprs.kt:32:28:32:44 | invoke | override, public | +| funcExprs.kt:33:28:33:51 | ...->... | funcExprs.kt:33:28:33:51 | invoke | override, public | +| funcExprs.kt:33:37:33:47 | ...->... | funcExprs.kt:33:37:33:47 | invoke | override, public | +| funcExprs.kt:35:29:35:112 | ...->... | funcExprs.kt:35:29:35:112 | invoke | override, public | +| funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | override, public | | funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | public | -| funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | public | -| funcExprs.kt:75:12:75:22 | ...->... | funcExprs.kt:75:12:75:22 | invoke | override | -| funcExprs.kt:75:12:75:22 | ...->... | funcExprs.kt:75:12:75:22 | invoke | public | -| samConversion.kt:2:31:2:45 | ...->... | samConversion.kt:2:31:2:45 | invoke | override | -| samConversion.kt:2:31:2:45 | ...->... | samConversion.kt:2:31:2:45 | invoke | public | -| samConversion.kt:4:27:4:42 | ...->... | samConversion.kt:4:27:4:42 | invoke | override | -| samConversion.kt:4:27:4:42 | ...->... | samConversion.kt:4:27:4:42 | invoke | public | -| samConversion.kt:7:29:7:46 | ...->... | samConversion.kt:7:29:7:46 | invoke | override | -| samConversion.kt:7:29:7:46 | ...->... | samConversion.kt:7:29:7:46 | invoke | public | -| samConversion.kt:9:33:11:5 | ...->... | samConversion.kt:9:33:11:5 | invoke | override | -| samConversion.kt:9:33:11:5 | ...->... | samConversion.kt:9:33:11:5 | invoke | public | -| samConversion.kt:11:12:13:5 | ...->... | samConversion.kt:11:12:13:5 | invoke | override | -| samConversion.kt:11:12:13:5 | ...->... | samConversion.kt:11:12:13:5 | invoke | public | -| samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | override | +| funcExprs.kt:75:12:75:22 | ...->... | funcExprs.kt:75:12:75:22 | invoke | override, public | +| funcExprs.kt:83:31:83:51 | ...->... | funcExprs.kt:83:31:83:51 | invoke | override, public | +| funcExprs.kt:86:39:86:59 | ...->... | funcExprs.kt:86:39:86:59 | invoke | override, public, suspend | +| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | override, public | +| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | public | +| funcExprs.kt:94:15:94:67 | ...->... | funcExprs.kt:94:15:94:67 | invoke | override, public, suspend | +| samConversion.kt:2:31:2:45 | ...->... | samConversion.kt:2:31:2:45 | invoke | override, public | +| samConversion.kt:4:27:4:42 | ...->... | samConversion.kt:4:27:4:42 | invoke | override, public | +| samConversion.kt:7:29:7:46 | ...->... | samConversion.kt:7:29:7:46 | invoke | override, public | +| samConversion.kt:9:33:11:5 | ...->... | samConversion.kt:9:33:11:5 | invoke | override, public | +| samConversion.kt:11:12:13:5 | ...->... | samConversion.kt:11:12:13:5 | invoke | override, public | +| samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | override, public | | samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | public | -| samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | public | -| samConversion.kt:46:32:46:44 | ...->... | samConversion.kt:46:32:46:44 | invoke | override | -| samConversion.kt:46:32:46:44 | ...->... | samConversion.kt:46:32:46:44 | invoke | public | +| samConversion.kt:46:32:46:44 | ...->... | samConversion.kt:46:32:46:44 | invoke | override, public | +| samConversion.kt:58:30:58:45 | ...->... | samConversion.kt:58:30:58:45 | invoke | override, public, suspend | nonOverrideInvoke | funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | 23 | +| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | 23 | | samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | 23 | diff --git a/java/ql/test/kotlin/library-tests/exprs/funcExprs.kt b/java/ql/test/kotlin/library-tests/exprs/funcExprs.kt index 06a4f3f3280..ac7e7912072 100644 --- a/java/ql/test/kotlin/library-tests/exprs/funcExprs.kt +++ b/java/ql/test/kotlin/library-tests/exprs/funcExprs.kt @@ -78,3 +78,19 @@ class Class3 { class Generic { } } + +suspend fun fn() { + val l1: (Int) -> String = { i -> i.toString() } + l1.invoke(5) // calls kotlin/jvm/functions/Function1.invoke + + val l2: suspend (Int) -> String = { i -> i.toString() } + l2.invoke(5) // calls kotlin/jvm/functions/Function2.invoke + + val l3: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int) -> String + = { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ -> ""} + l3.invoke(1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3) // 23 args, calls kotlin/jvm/functions/FunctionN.invoke + + val l4: suspend (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int) -> String + = { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ -> ""} + l4.invoke(1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2) // 22 args, calls kotlin/jvm/functions/FunctionN.invoke +} diff --git a/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql b/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql index c1cf7c6f124..fa2b5fda2a2 100644 --- a/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql +++ b/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql @@ -19,9 +19,9 @@ query predicate memberRefExprs(MemberRefExpr e, Method m, string signature, Anon e.getAnonymousClass() = an } -query predicate modifiers(LambdaExpr le, Method m, string modifier) { +query predicate modifiers(LambdaExpr le, Method m, string modifiers) { le.getAnonymousClass().getAMethod() = m and - m.hasModifier(modifier) + modifiers = concat(string s | m.hasModifier(s) | s, ", ") } query predicate nonOverrideInvoke(LambdaExpr le, Method m, int pCount) { diff --git a/java/ql/test/kotlin/library-tests/exprs/samConversion.kt b/java/ql/test/kotlin/library-tests/exprs/samConversion.kt index 167b1f6bc30..2856f839778 100644 --- a/java/ql/test/kotlin/library-tests/exprs/samConversion.kt +++ b/java/ql/test/kotlin/library-tests/exprs/samConversion.kt @@ -49,3 +49,12 @@ fun fn(boo: Boolean) { fun interface SomePredicate { fun fn(i: T): Boolean } + +fun interface InterfaceFn1Sus { + suspend fun fn1(i: Int, j: Int) +} + +suspend fun test() { + val i0 = InterfaceFn1Sus { a, b -> Unit } + i0.fn1(1,2) +} diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin/Continuation.java b/java/ql/test/kotlin/library-tests/java_and_kotlin/Continuation.java new file mode 100644 index 00000000000..1e0bcda4135 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/java_and_kotlin/Continuation.java @@ -0,0 +1,4 @@ +package kotlin.coroutines; + +// This is a stub for the Kotlin Continuation interface. +public interface Continuation { } diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin/Java.java b/java/ql/test/kotlin/library-tests/java_and_kotlin/Java.java index e4ae7eecf19..6240bced9f2 100644 --- a/java/ql/test/kotlin/library-tests/java_and_kotlin/Java.java +++ b/java/ql/test/kotlin/library-tests/java_and_kotlin/Java.java @@ -1,5 +1,19 @@ +import kotlin.coroutines.Continuation; + public class Java { void javaFun() { new Kotlin().kotlinFun(); } + + public class Djava extends Base { + @Override + public String fn0(int x) { + return super.fn0(x); + } + + @Override + public Object fn1(int x, Continuation $completion) { + return super.fn1(x, $completion); + } + } } diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin/Kotlin.kt b/java/ql/test/kotlin/library-tests/java_and_kotlin/Kotlin.kt index b592ebf1c7d..63e5ca99455 100644 --- a/java/ql/test/kotlin/library-tests/java_and_kotlin/Kotlin.kt +++ b/java/ql/test/kotlin/library-tests/java_and_kotlin/Kotlin.kt @@ -3,3 +3,13 @@ public class Kotlin { // TODO: Java().javaFun(); } } + +open class Base { + open fun fn0(x: Int) : String = "" + open suspend fun fn1(x: Int) : String = "" +} + +class Dkotlin : Base() { + override fun fn0(x: Int): String = super.fn0(x) + override suspend fun fn1(x: Int): String = super.fn1(x) +} diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin/methodAccess.expected b/java/ql/test/kotlin/library-tests/java_and_kotlin/methodAccess.expected deleted file mode 100644 index 515457eb54e..00000000000 --- a/java/ql/test/kotlin/library-tests/java_and_kotlin/methodAccess.expected +++ /dev/null @@ -1 +0,0 @@ -| Java.java:3:3:3:26 | kotlinFun(...) | Kotlin.kt:2:2:4:2 | kotlinFun | diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin/methodAccess.ql b/java/ql/test/kotlin/library-tests/java_and_kotlin/methodAccess.ql deleted file mode 100644 index 2162e802e20..00000000000 --- a/java/ql/test/kotlin/library-tests/java_and_kotlin/methodAccess.ql +++ /dev/null @@ -1,5 +0,0 @@ -import java - -from MethodAccess ma, Method m -where m = ma.getMethod() -select ma, m diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin/test.expected b/java/ql/test/kotlin/library-tests/java_and_kotlin/test.expected new file mode 100644 index 00000000000..41d010e4f06 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/java_and_kotlin/test.expected @@ -0,0 +1,23 @@ +methods +| Java.java:4:7:4:13 | javaFun | javaFun() | +| Java.java:10:17:10:19 | fn0 | fn0(int) | +| Java.java:15:17:15:19 | fn1 | fn1(int,kotlin.coroutines.Continuation) | +| Kotlin.kt:2:2:4:2 | kotlinFun | kotlinFun() | +| Kotlin.kt:8:10:8:38 | fn0 | fn0(int) | +| Kotlin.kt:9:18:9:46 | fn1 | fn1(int) | +| Kotlin.kt:13:14:13:51 | fn0 | fn0(int) | +| Kotlin.kt:14:22:14:59 | fn1 | fn1(int) | +overrides +| Java.java:10:17:10:19 | fn0 | Kotlin.kt:8:10:8:38 | fn0 | +| Java.java:15:17:15:19 | fn1 | java_and_kotlin.testproj/test.class.files/Base.class:0:0:0:0 | fn1 | +| Kotlin.kt:13:14:13:51 | fn0 | Kotlin.kt:8:10:8:38 | fn0 | +| Kotlin.kt:14:22:14:59 | fn1 | Kotlin.kt:9:18:9:46 | fn1 | +signature_mismatch +| Kotlin.kt:9:18:9:46 | fn1 | fn1(int) | +| java_and_kotlin.testproj/test.class.files/Base.class:0:0:0:0 | fn1 | fn1(int,kotlin.coroutines.Continuation) | +#select +| Java.java:5:3:5:26 | kotlinFun(...) | Kotlin.kt:2:2:4:2 | kotlinFun | +| Java.java:11:11:11:22 | fn0(...) | Kotlin.kt:8:10:8:38 | fn0 | +| Java.java:16:11:16:35 | fn1(...) | java_and_kotlin.testproj/test.class.files/Base.class:0:0:0:0 | fn1 | +| Kotlin.kt:13:46:13:51 | fn0(...) | Kotlin.kt:8:10:8:38 | fn0 | +| Kotlin.kt:14:54:14:59 | fn1(...) | Kotlin.kt:9:18:9:46 | fn1 | diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin/test.ql b/java/ql/test/kotlin/library-tests/java_and_kotlin/test.ql new file mode 100644 index 00000000000..3b74a66480e --- /dev/null +++ b/java/ql/test/kotlin/library-tests/java_and_kotlin/test.ql @@ -0,0 +1,21 @@ +import java + +from MethodAccess ma, Method m +where m = ma.getMethod() +select ma, m + +query predicate methods(Method m, string sig) { + m.fromSource() and + m.getSignature() = sig +} + +query predicate overrides(Method m1, Method m2) { + m1.fromSource() and + m1.overrides(m2) +} + +query predicate signature_mismatch(Method m, string sig) { + m.getDeclaringType().getQualifiedName() = "Base" and + m.getName() = "fn1" and + m.getSignature() = sig +} diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index b0a7e618de8..1337b43efb8 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.expected +++ b/java/ql/test/kotlin/library-tests/methods/exprs.expected @@ -274,6 +274,7 @@ | methods5.kt:10:13:10:18 | f1(...) | MethodAccess | | methods5.kt:10:13:10:18 | new (...) | ClassInstanceExpr | | methods5.kt:10:16:10:17 | 42 | IntegerLiteral | +| methods6.kt:3:9:4:1 | Unit | TypeAccess | | methods.kt:2:1:3:1 | Unit | TypeAccess | | methods.kt:2:20:2:25 | int | TypeAccess | | methods.kt:2:28:2:33 | int | TypeAccess | diff --git a/java/ql/test/kotlin/library-tests/methods/methods.expected b/java/ql/test/kotlin/library-tests/methods/methods.expected index 8067838d889..e68bc650ce6 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.expected +++ b/java/ql/test/kotlin/library-tests/methods/methods.expected @@ -36,6 +36,7 @@ methods | methods5.kt:0:0:0:0 | Methods5Kt | methods5.kt:3:1:11:1 | x | x() | public, static | | | methods5.kt:5:3:5:27 | | methods5.kt:5:3:5:27 | a | a(int) | public | | | methods5.kt:9:3:9:32 | | methods5.kt:9:3:9:32 | f1 | f1(foo.bar.C1,int) | public | | +| methods6.kt:0:0:0:0 | Methods6Kt | methods6.kt:3:9:4:1 | s | s() | public, static, suspend | | | methods.kt:0:0:0:0 | MethodsKt | methods.kt:2:1:3:1 | topLevelMethod | topLevelMethod(int,int) | public, static | | | methods.kt:5:1:20:1 | Class | methods.kt:6:5:7:5 | classMethod | classMethod(int,int) | public | | | methods.kt:5:1:20:1 | Class | methods.kt:9:5:12:5 | anotherClassMethod | anotherClassMethod(int,int) | public | | diff --git a/java/ql/test/kotlin/library-tests/methods/methods6.kt b/java/ql/test/kotlin/library-tests/methods/methods6.kt new file mode 100644 index 00000000000..6ae5c37d70b --- /dev/null +++ b/java/ql/test/kotlin/library-tests/methods/methods6.kt @@ -0,0 +1,4 @@ +package foo.bar + +suspend fun s() { +} diff --git a/java/ql/test/library-tests/annotation-arrays/test.ql b/java/ql/test/library-tests/annotation-arrays/test.ql index 4c0dfd89b7b..4598687c915 100644 --- a/java/ql/test/library-tests/annotation-arrays/test.ql +++ b/java/ql/test/library-tests/annotation-arrays/test.ql @@ -4,6 +4,6 @@ from Field f, Annotation ann, Expr value, Expr valueChild where f.getDeclaringType().fromSource() and ann = f.getAnAnnotation() and - value = ann.getAValue() and + value = ann.getValue(_) and valueChild.getParent() = value select f, ann, value, valueChild diff --git a/java/ql/test/library-tests/annotations/Annotatable.expected b/java/ql/test/library-tests/annotations/Annotatable.expected new file mode 100644 index 00000000000..7708e78a305 --- /dev/null +++ b/java/ql/test/library-tests/annotations/Annotatable.expected @@ -0,0 +1,101 @@ +declaredAnnotation +| Annotatable.java:8:16:8:40 | CustomInheritedAnnotation | Annotatable.java:7:5:7:14 | Inherited | +| Annotatable.java:14:11:14:22 | WithDeclared | Annotatable.java:12:5:12:21 | CustomAnnotation | +| Annotatable.java:14:11:14:22 | WithDeclared | Annotatable.java:13:5:13:38 | CustomInheritedAnnotation | +| Annotatable.java:17:14:17:31 | methodWithDeclared | Annotatable.java:16:9:16:49 | CustomInheritedAnnotation | +| Annotatable.java:22:14:22:31 | methodWithDeclared | Annotatable.java:21:9:21:17 | Override | +| Annotatable.java:30:11:30:41 | SubclassDeclaringSameAnnotation | Annotatable.java:29:5:29:37 | CustomInheritedAnnotation | +| Annotatable.java:35:15:35:35 | InterfaceWithDeclared | Annotatable.java:34:5:34:38 | CustomInheritedAnnotation | +| Annotatable.java:47:16:47:35 | RepeatableAnnotation | Annotatable.java:46:5:46:42 | Repeatable | +| Annotatable.java:52:16:52:43 | InheritedContainerAnnotation | Annotatable.java:51:5:51:14 | Inherited | +| Annotatable.java:58:16:58:44 | InheritedRepeatableAnnotation | Annotatable.java:56:5:56:14 | Inherited | +| Annotatable.java:58:16:58:44 | InheritedRepeatableAnnotation | Annotatable.java:57:5:57:51 | Repeatable | +| Annotatable.java:63:16:63:44 | InheritedContainerAnnotation2 | Annotatable.java:62:5:62:14 | Inherited | +| Annotatable.java:71:16:71:47 | NonInheritedRepeatableAnnotation | Annotatable.java:70:5:70:52 | Repeatable | +| Annotatable.java:78:11:78:30 | WithAssociatedSingle | Annotatable.java:75:5:75:33 | RepeatableAnnotation | +| Annotatable.java:78:11:78:30 | WithAssociatedSingle | Annotatable.java:76:5:76:42 | InheritedRepeatableAnnotation | +| Annotatable.java:78:11:78:30 | WithAssociatedSingle | Annotatable.java:77:5:77:45 | NonInheritedRepeatableAnnotation | +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | ContainerAnnotation | +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation | +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 | +| Annotatable.java:92:11:92:44 | SubclassOfSingleWithEmptyContainer | Annotatable.java:90:5:90:37 | InheritedContainerAnnotation | +| Annotatable.java:92:11:92:44 | SubclassOfSingleWithEmptyContainer | Annotatable.java:91:5:91:38 | InheritedContainerAnnotation2 | +| Annotatable.java:98:15:98:37 | InterfaceWithAssociated | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation | +| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | ContainerAnnotation | +| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation | +| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 | +| Annotatable.java:116:14:116:39 | methodWithAssociatedSingle | Annotatable.java:115:9:115:53 | InheritedRepeatableAnnotation | +| Annotatable.java:121:14:121:33 | methodWithAssociated | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation | +| Annotatable.java:126:14:126:39 | methodWithAssociatedSingle | Annotatable.java:125:9:125:17 | Override | +| Annotatable.java:129:14:129:33 | methodWithAssociated | Annotatable.java:128:9:128:17 | Override | +| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.java:135:5:135:34 | RepeatableAnnotation | +| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.java:136:5:136:43 | InheritedRepeatableAnnotation | +| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.java:137:5:137:46 | NonInheritedRepeatableAnnotation | +| Annotatable.java:144:11:144:46 | SubclassOfMultipleWithEmptyContainer | Annotatable.java:142:5:142:37 | InheritedContainerAnnotation | +| Annotatable.java:144:11:144:46 | SubclassOfMultipleWithEmptyContainer | Annotatable.java:143:5:143:38 | InheritedContainerAnnotation2 | +| Annotatable.java:150:35:153:5 | {...} | Annotatable.java:151:9:151:53 | InheritedRepeatableAnnotation | +| Annotatable.java:150:35:153:5 | {...} | Annotatable.java:152:9:152:53 | InheritedRepeatableAnnotation | +| Annotatable.java:154:11:154:45 | ExplicitContainerAndSingleContained | Annotatable.java:148:5:148:44 | InheritedRepeatableAnnotation | +| Annotatable.java:154:11:154:45 | ExplicitContainerAndSingleContained | Annotatable.java:150:5:153:6 | InheritedContainerAnnotation | +| Annotatable.java:160:16:160:41 | NestedAnnotationContainer1 | Annotatable.java:159:5:159:14 | Inherited | +| Annotatable.java:166:16:166:32 | NestedAnnotation1 | Annotatable.java:164:5:164:14 | Inherited | +| Annotatable.java:166:16:166:32 | NestedAnnotation1 | Annotatable.java:165:5:165:49 | Repeatable | +| Annotatable.java:172:16:172:32 | NestedAnnotation2 | Annotatable.java:170:5:170:14 | Inherited | +| Annotatable.java:172:16:172:32 | NestedAnnotation2 | Annotatable.java:171:5:171:40 | Repeatable | +| Annotatable.java:182:11:182:30 | WithNestedAssociated | Annotatable.class:0:0:0:0 | NestedAnnotationContainer1 | +| Annotatable.java:182:11:182:30 | WithNestedAssociated | Annotatable.java:177:5:177:27 | NestedAnnotation2 | +| Annotatable.java:189:11:189:48 | WithNestedAssociatedExplicitContainers | Annotatable.class:0:0:0:0 | NestedAnnotationContainer1 | +annotationAdditional +| Annotatable.java:20:11:20:18 | Subclass | Annotatable.java:13:5:13:38 | CustomInheritedAnnotation | +| Annotatable.java:26:11:26:21 | SubSubclass | Annotatable.java:13:5:13:38 | CustomInheritedAnnotation | +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.java:76:5:76:42 | InheritedRepeatableAnnotation | +| Annotatable.java:92:11:92:44 | SubclassOfSingleWithEmptyContainer | Annotatable.java:76:5:76:42 | InheritedRepeatableAnnotation | +| Annotatable.java:124:11:124:32 | WithAssociatedSubclass | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation | +| Annotatable.java:124:11:124:32 | WithAssociatedSubclass | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 | +| Annotatable.java:133:11:133:35 | WithAssociatedSubSubclass | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation | +| Annotatable.java:133:11:133:35 | WithAssociatedSubSubclass | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 | +| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation | +| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 | +| Annotatable.java:156:11:156:35 | ExplicitContainerSubclass | Annotatable.java:148:5:148:44 | InheritedRepeatableAnnotation | +| Annotatable.java:156:11:156:35 | ExplicitContainerSubclass | Annotatable.java:150:5:153:6 | InheritedContainerAnnotation | +| Annotatable.java:184:11:184:38 | WithNestedAssociatedSubclass | Annotatable.class:0:0:0:0 | NestedAnnotationContainer1 | +| Annotatable.java:184:11:184:38 | WithNestedAssociatedSubclass | Annotatable.java:177:5:177:27 | NestedAnnotation2 | +| Annotatable.java:191:11:191:56 | WithNestedAssociatedExplicitContainersSubclass | Annotatable.class:0:0:0:0 | NestedAnnotationContainer1 | +bugAnnotationAdditional +associatedAnnotationAdditional +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | NonInheritedRepeatableAnnotation | +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | NonInheritedRepeatableAnnotation | +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | RepeatableAnnotation | +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | RepeatableAnnotation | +| Annotatable.java:98:15:98:37 | InterfaceWithAssociated | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:98:15:98:37 | InterfaceWithAssociated | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | NonInheritedRepeatableAnnotation | +| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | NonInheritedRepeatableAnnotation | +| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | RepeatableAnnotation | +| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | RepeatableAnnotation | +| Annotatable.java:121:14:121:33 | methodWithAssociated | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:121:14:121:33 | methodWithAssociated | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:124:11:124:32 | WithAssociatedSubclass | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:124:11:124:32 | WithAssociatedSubclass | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:133:11:133:35 | WithAssociatedSubSubclass | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:133:11:133:35 | WithAssociatedSubSubclass | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:144:11:144:46 | SubclassOfMultipleWithEmptyContainer | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:144:11:144:46 | SubclassOfMultipleWithEmptyContainer | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation | +| Annotatable.java:154:11:154:45 | ExplicitContainerAndSingleContained | Annotatable.java:151:9:151:53 | InheritedRepeatableAnnotation | +| Annotatable.java:154:11:154:45 | ExplicitContainerAndSingleContained | Annotatable.java:152:9:152:53 | InheritedRepeatableAnnotation | +| Annotatable.java:156:11:156:35 | ExplicitContainerSubclass | Annotatable.java:151:9:151:53 | InheritedRepeatableAnnotation | +| Annotatable.java:156:11:156:35 | ExplicitContainerSubclass | Annotatable.java:152:9:152:53 | InheritedRepeatableAnnotation | +| Annotatable.java:182:11:182:30 | WithNestedAssociated | Annotatable.class:0:0:0:0 | NestedAnnotation1 | +| Annotatable.java:182:11:182:30 | WithNestedAssociated | Annotatable.class:0:0:0:0 | NestedAnnotation1 | +| Annotatable.java:184:11:184:38 | WithNestedAssociatedSubclass | Annotatable.class:0:0:0:0 | NestedAnnotation1 | +| Annotatable.java:184:11:184:38 | WithNestedAssociatedSubclass | Annotatable.class:0:0:0:0 | NestedAnnotation1 | +| Annotatable.java:189:11:189:48 | WithNestedAssociatedExplicitContainers | Annotatable.class:0:0:0:0 | NestedAnnotation1 | +| Annotatable.java:189:11:189:48 | WithNestedAssociatedExplicitContainers | Annotatable.class:0:0:0:0 | NestedAnnotation1 | +| Annotatable.java:191:11:191:56 | WithNestedAssociatedExplicitContainersSubclass | Annotatable.class:0:0:0:0 | NestedAnnotation1 | +| Annotatable.java:191:11:191:56 | WithNestedAssociatedExplicitContainersSubclass | Annotatable.class:0:0:0:0 | NestedAnnotation1 | +associatedAnnotationNotInherited +| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.java:76:5:76:42 | InheritedRepeatableAnnotation | diff --git a/java/ql/test/library-tests/annotations/Annotatable.java b/java/ql/test/library-tests/annotations/Annotatable.java new file mode 100644 index 00000000000..e73d48bb24d --- /dev/null +++ b/java/ql/test/library-tests/annotations/Annotatable.java @@ -0,0 +1,192 @@ +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; + +class Annotatable { + @interface CustomAnnotation {} + + @Inherited + @interface CustomInheritedAnnotation { + String value(); + } + + @CustomAnnotation + @CustomInheritedAnnotation("base") + class WithDeclared { + // Annotations on methods are not inherited + @CustomInheritedAnnotation("base-method") + void methodWithDeclared() {} + } + + class Subclass extends WithDeclared { + @Override + void methodWithDeclared() {} + } + + // Inheritance from super-superclass + class SubSubclass extends Subclass {} + + // Prevents inheriting annotation of same type + @CustomInheritedAnnotation("sub") + class SubclassDeclaringSameAnnotation extends WithDeclared {} + + + // Annotations on interfaces are not inherited + @CustomInheritedAnnotation("base") + interface InterfaceWithDeclared {} + + interface ExtendingInterface extends InterfaceWithDeclared {} + + class ImplementingInterface implements InterfaceWithDeclared {} + + + @interface ContainerAnnotation { + RepeatableAnnotation[] value(); + } + + @Repeatable(ContainerAnnotation.class) + @interface RepeatableAnnotation { + String value(); + } + + @Inherited + @interface InheritedContainerAnnotation { + InheritedRepeatableAnnotation[] value(); + } + + @Inherited + @Repeatable(InheritedContainerAnnotation.class) + @interface InheritedRepeatableAnnotation { + String value(); + } + + @Inherited + @interface InheritedContainerAnnotation2 { + NonInheritedRepeatableAnnotation[] value(); + } + + // Container is marked as @Inherited, but this annotation type is not + // This is allowed, but means that associated annotations will not be inherited, + // see java.lang.reflect.AnnotatedElement documentation + @Repeatable(InheritedContainerAnnotation2.class) + @interface NonInheritedRepeatableAnnotation { + String value(); + } + + @RepeatableAnnotation("base") + @InheritedRepeatableAnnotation("base") + @NonInheritedRepeatableAnnotation("base") + class WithAssociatedSingle {} + + @RepeatableAnnotation("sub-1") + @RepeatableAnnotation("sub-2") + @InheritedRepeatableAnnotation("sub-1") + @InheritedRepeatableAnnotation("sub-2") + @NonInheritedRepeatableAnnotation("sub-1") + @NonInheritedRepeatableAnnotation("sub-2") + class SubclassWithMultiple extends WithAssociatedSingle {} + + + // Empty container annotations have no effect; annotations are inherited from superclass + @InheritedContainerAnnotation({}) + @InheritedContainerAnnotation2({}) + class SubclassOfSingleWithEmptyContainer extends WithAssociatedSingle {} + + + // Annotations on interfaces are not inherited + @InheritedRepeatableAnnotation("base-1") + @InheritedRepeatableAnnotation("base-2") + interface InterfaceWithAssociated {} + + interface ExtendingInterfaceWithAssociated extends InterfaceWithAssociated {} + + class ImplementingInterfaceWithAssociated implements InterfaceWithAssociated {} + + + @RepeatableAnnotation("base-1") + @RepeatableAnnotation("base-2") + @InheritedRepeatableAnnotation("base-1") + @InheritedRepeatableAnnotation("base-2") + // These annotations are not inherited, but their (implicit) container annotation + // is inherited + @NonInheritedRepeatableAnnotation("base-1") + @NonInheritedRepeatableAnnotation("base-2") + class WithAssociatedMultiple { + // Annotations on methods are not inherited + @InheritedRepeatableAnnotation("base-method") + void methodWithAssociatedSingle() {} + + // Annotations on methods are not inherited + @InheritedRepeatableAnnotation("base-method-1") + @InheritedRepeatableAnnotation("base-method-2") + void methodWithAssociated() {} + } + + class WithAssociatedSubclass extends WithAssociatedMultiple { + @Override + void methodWithAssociatedSingle() {} + + @Override + void methodWithAssociated() {} + } + + // Inheritance from super-superclass + class WithAssociatedSubSubclass extends WithAssociatedSubclass {} + + @RepeatableAnnotation("sub-1") + @InheritedRepeatableAnnotation("sub-1") + @NonInheritedRepeatableAnnotation("sub-1") + class SubclassWithSingle extends WithAssociatedMultiple {} + + + // Empty container annotations have no effect; associated annotations are inherited from superclass + @InheritedContainerAnnotation({}) + @InheritedContainerAnnotation2({}) + class SubclassOfMultipleWithEmptyContainer extends WithAssociatedMultiple {} + + + // This annotation exists on its own without a container + @InheritedRepeatableAnnotation("single") + // TODO: Has currently spurious results for ArrayInit due to https://github.com/github/codeql/issues/8647 + @InheritedContainerAnnotation({ + @InheritedRepeatableAnnotation("container-1"), + @InheritedRepeatableAnnotation("container-2") + }) + class ExplicitContainerAndSingleContained {} + + class ExplicitContainerSubclass extends ExplicitContainerAndSingleContained {} + + + @Inherited + @interface NestedAnnotationContainer1 { + NestedAnnotation1[] value(); + } + + @Inherited + @Repeatable(NestedAnnotationContainer1.class) + @interface NestedAnnotation1 { + NestedAnnotation2[] value(); + } + + @Inherited + @Repeatable(NestedAnnotation1.class) + @interface NestedAnnotation2 { + String value(); + } + + // This annotation exists on its own without a container + @NestedAnnotation2("1") + // But these are nested inside an implicit @NestedAnnotationContainer1 + // Nested repeated annotations (@NestedAnnotation2) are not considered associated + @NestedAnnotation1({@NestedAnnotation2("1-1"), @NestedAnnotation2("1-2")}) + @NestedAnnotation1({@NestedAnnotation2("2-1"), @NestedAnnotation2("2-2")}) + class WithNestedAssociated {} + + class WithNestedAssociatedSubclass extends WithNestedAssociated {} + + // Nested repeated annotations (@NestedAnnotation2) are not considered associated + @NestedAnnotation1({@NestedAnnotation2("1-1"), @NestedAnnotation2("1-2")}) + @NestedAnnotation1({@NestedAnnotation2("2-1"), @NestedAnnotation2("2-2")}) + class WithNestedAssociatedExplicitContainers {} + + class WithNestedAssociatedExplicitContainersSubclass extends WithNestedAssociatedExplicitContainers {} +} diff --git a/java/ql/test/library-tests/annotations/Annotatable.ql b/java/ql/test/library-tests/annotations/Annotatable.ql new file mode 100644 index 00000000000..12745eb42fc --- /dev/null +++ b/java/ql/test/library-tests/annotations/Annotatable.ql @@ -0,0 +1,34 @@ +import java + +class RelevantAnnotatable extends Annotatable { + RelevantAnnotatable() { + getCompilationUnit().hasName("Annotatable") and getCompilationUnit().fromSource() + } +} + +query Annotation declaredAnnotation(RelevantAnnotatable a) { result = a.getADeclaredAnnotation() } + +/** Note: Only has the annotations as result which are not also considered _declared_. */ +query Annotation annotationAdditional(RelevantAnnotatable a) { + result = a.getAnAnnotation() and not result = a.getADeclaredAnnotation() +} + +/** Sanity check to verify that `getADeclaredAnnotation()` is a subset of `getAnAnnotation()` */ +query Annotation bugAnnotationAdditional(RelevantAnnotatable a) { + result = a.getADeclaredAnnotation() and not result = a.getAnAnnotation() +} + +/** Note: Only has the annotations as result which are not part of `getAnAnnotation()`. */ +query Annotation associatedAnnotationAdditional(RelevantAnnotatable a) { + result = a.getAnAssociatedAnnotation() and not result = a.getAnAnnotation() +} + +/** + * Covers all results of `getAnAssociatedAnnotation()` which are not also a result of `getAnAnnotation()`. + * This should only be the case for a base class using an inheritable annotation `A` and a subclass which + * has an annotation `CA` of the container type of `A`. In that case `A` is not considered _associated_ + * and the _indirect_ annotations from `CA` are considered instead. + */ +query Annotation associatedAnnotationNotInherited(RelevantAnnotatable a) { + result = a.getAnAnnotation() and not result = a.getAnAssociatedAnnotation() +} diff --git a/java/ql/test/library-tests/annotations/Annotation-values.expected b/java/ql/test/library-tests/annotations/Annotation-values.expected new file mode 100644 index 00000000000..55c86f3a124 --- /dev/null +++ b/java/ql/test/library-tests/annotations/Annotation-values.expected @@ -0,0 +1,215 @@ +value +| AnnotationValues.java:39:5:39:17 | SingleValues | annotationValue | AnnotationValues.class:0:0:0:0 | CustomAnnotation | +| AnnotationValues.java:39:5:39:17 | SingleValues | booleanValue | AnnotationValues.class:0:0:0:0 | false | +| AnnotationValues.java:39:5:39:17 | SingleValues | byteValue | AnnotationValues.class:0:0:0:0 | -1 | +| AnnotationValues.java:39:5:39:17 | SingleValues | charValue | AnnotationValues.class:0:0:0:0 | \uffff | +| AnnotationValues.java:39:5:39:17 | SingleValues | classValue | AnnotationValues.class:0:0:0:0 | AnnotationValues.class | +| AnnotationValues.java:39:5:39:17 | SingleValues | doubleValue | AnnotationValues.class:0:0:0:0 | -1.0 | +| AnnotationValues.java:39:5:39:17 | SingleValues | enumValue | AnnotationValues.class:0:0:0:0 | DEFAULT | +| AnnotationValues.java:39:5:39:17 | SingleValues | floatValue | AnnotationValues.class:0:0:0:0 | -1.0 | +| AnnotationValues.java:39:5:39:17 | SingleValues | intValue | AnnotationValues.class:0:0:0:0 | -1 | +| AnnotationValues.java:39:5:39:17 | SingleValues | longValue | AnnotationValues.class:0:0:0:0 | -1 | +| AnnotationValues.java:39:5:39:17 | SingleValues | shortValue | AnnotationValues.class:0:0:0:0 | -1 | +| AnnotationValues.java:39:5:39:17 | SingleValues | stringValue | AnnotationValues.class:0:0:0:0 | "\u0000" | +| AnnotationValues.java:42:5:55:5 | SingleValues | annotationValue | AnnotationValues.java:54:27:54:53 | CustomAnnotation | +| AnnotationValues.java:42:5:55:5 | SingleValues | booleanValue | AnnotationValues.java:49:24:49:27 | true | +| AnnotationValues.java:42:5:55:5 | SingleValues | byteValue | AnnotationValues.java:43:21:43:21 | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | charValue | AnnotationValues.java:50:21:50:21 | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | classValue | AnnotationValues.java:52:22:52:39 | SingleValues.class | +| AnnotationValues.java:42:5:55:5 | SingleValues | doubleValue | AnnotationValues.java:48:23:48:23 | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | enumValue | AnnotationValues.java:53:21:53:32 | CustomEnum.A | +| AnnotationValues.java:42:5:55:5 | SingleValues | floatValue | AnnotationValues.java:47:22:47:22 | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | intValue | AnnotationValues.java:45:20:45:20 | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | longValue | AnnotationValues.java:46:21:46:21 | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | shortValue | AnnotationValues.java:44:22:44:22 | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | stringValue | AnnotationValues.java:51:23:51:25 | "a" | +| AnnotationValues.java:54:27:54:53 | CustomAnnotation | value | AnnotationValues.java:54:45:54:52 | "single" | +| AnnotationValues.java:58:5:71:5 | SingleValues | annotationValue | AnnotationValues.java:70:27:70:53 | CustomAnnotation | +| AnnotationValues.java:58:5:71:5 | SingleValues | booleanValue | AnnotationValues.java:65:24:65:30 | BOOLEAN | +| AnnotationValues.java:58:5:71:5 | SingleValues | byteValue | AnnotationValues.java:59:21:59:24 | BYTE | +| AnnotationValues.java:58:5:71:5 | SingleValues | charValue | AnnotationValues.java:66:21:66:24 | CHAR | +| AnnotationValues.java:58:5:71:5 | SingleValues | classValue | AnnotationValues.java:68:22:68:39 | SingleValues.class | +| AnnotationValues.java:58:5:71:5 | SingleValues | doubleValue | AnnotationValues.java:64:23:64:28 | DOUBLE | +| AnnotationValues.java:58:5:71:5 | SingleValues | enumValue | AnnotationValues.java:69:21:69:32 | CustomEnum.A | +| AnnotationValues.java:58:5:71:5 | SingleValues | floatValue | AnnotationValues.java:63:22:63:26 | FLOAT | +| AnnotationValues.java:58:5:71:5 | SingleValues | intValue | AnnotationValues.java:61:20:61:22 | INT | +| AnnotationValues.java:58:5:71:5 | SingleValues | longValue | AnnotationValues.java:62:21:62:24 | LONG | +| AnnotationValues.java:58:5:71:5 | SingleValues | shortValue | AnnotationValues.java:60:22:60:26 | SHORT | +| AnnotationValues.java:58:5:71:5 | SingleValues | stringValue | AnnotationValues.java:67:23:67:28 | STRING | +| AnnotationValues.java:70:27:70:53 | CustomAnnotation | value | AnnotationValues.java:70:45:70:52 | "single" | +| AnnotationValues.java:90:5:90:16 | ArrayValues | annotationValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | booleanValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | byteValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | charValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | classValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | doubleValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | enumValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | floatValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | intValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | longValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | shortValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:90:5:90:16 | ArrayValues | stringValues | AnnotationValues.class:0:0:0:0 | {...} | +| AnnotationValues.java:93:5:106:5 | ArrayValues | annotationValues | AnnotationValues.java:105:28:105:54 | {...} | +| AnnotationValues.java:93:5:106:5 | ArrayValues | booleanValues | AnnotationValues.java:100:25:100:28 | true | +| AnnotationValues.java:93:5:106:5 | ArrayValues | byteValues | AnnotationValues.java:94:22:94:22 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | charValues | AnnotationValues.java:101:22:101:24 | 'a' | +| AnnotationValues.java:93:5:106:5 | ArrayValues | classValues | AnnotationValues.java:103:23:103:39 | ArrayValues.class | +| AnnotationValues.java:93:5:106:5 | ArrayValues | doubleValues | AnnotationValues.java:99:24:99:24 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | enumValues | AnnotationValues.java:104:22:104:33 | CustomEnum.A | +| AnnotationValues.java:93:5:106:5 | ArrayValues | floatValues | AnnotationValues.java:98:23:98:23 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | intValues | AnnotationValues.java:96:21:96:21 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | longValues | AnnotationValues.java:97:22:97:22 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | shortValues | AnnotationValues.java:95:23:95:23 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | stringValues | AnnotationValues.java:102:24:102:26 | "a" | +| AnnotationValues.java:105:28:105:54 | CustomAnnotation | value | AnnotationValues.java:105:46:105:53 | "single" | +| AnnotationValues.java:109:5:122:5 | ArrayValues | annotationValues | AnnotationValues.java:121:28:121:84 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | AnnotationValues.java:116:25:116:40 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | AnnotationValues.java:110:22:110:30 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | AnnotationValues.java:117:22:117:32 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | AnnotationValues.java:119:23:119:61 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | AnnotationValues.java:115:24:115:34 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | AnnotationValues.java:120:22:120:49 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | AnnotationValues.java:114:23:114:32 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | AnnotationValues.java:112:21:112:28 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | AnnotationValues.java:113:22:113:30 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | AnnotationValues.java:111:23:111:32 | {...} | +| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | AnnotationValues.java:118:24:118:33 | {...} | +| AnnotationValues.java:121:29:121:54 | CustomAnnotation | value | AnnotationValues.java:121:47:121:53 | "first" | +| AnnotationValues.java:121:57:121:83 | CustomAnnotation | value | AnnotationValues.java:121:75:121:82 | "second" | +enumConstantValue +| AnnotationValues.java:39:5:39:17 | SingleValues | enumValue | AnnotationValues.java:14:9:14:15 | DEFAULT | +| AnnotationValues.java:42:5:55:5 | SingleValues | enumValue | AnnotationValues.java:15:9:15:9 | A | +| AnnotationValues.java:58:5:71:5 | SingleValues | enumValue | AnnotationValues.java:15:9:15:9 | A | +stringValue +| AnnotationValues.java:39:5:39:17 | SingleValues | stringValue | \u0000 | +| AnnotationValues.java:42:5:55:5 | SingleValues | stringValue | a | +| AnnotationValues.java:54:27:54:53 | CustomAnnotation | value | single | +| AnnotationValues.java:58:5:71:5 | SingleValues | stringValue | b | +| AnnotationValues.java:70:27:70:53 | CustomAnnotation | value | single | +| AnnotationValues.java:105:28:105:54 | CustomAnnotation | value | single | +| AnnotationValues.java:121:29:121:54 | CustomAnnotation | value | first | +| AnnotationValues.java:121:57:121:83 | CustomAnnotation | value | second | +intValue +| AnnotationValues.java:39:5:39:17 | SingleValues | byteValue | -1 | +| AnnotationValues.java:39:5:39:17 | SingleValues | charValue | 65535 | +| AnnotationValues.java:39:5:39:17 | SingleValues | intValue | -1 | +| AnnotationValues.java:39:5:39:17 | SingleValues | shortValue | -1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | byteValue | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | charValue | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | intValue | 1 | +| AnnotationValues.java:42:5:55:5 | SingleValues | shortValue | 1 | +| AnnotationValues.java:58:5:71:5 | SingleValues | byteValue | 2 | +| AnnotationValues.java:58:5:71:5 | SingleValues | charValue | 98 | +| AnnotationValues.java:58:5:71:5 | SingleValues | intValue | 2 | +| AnnotationValues.java:58:5:71:5 | SingleValues | shortValue | 2 | +booleanValue +| AnnotationValues.java:39:5:39:17 | SingleValues | booleanValue | false | +| AnnotationValues.java:42:5:55:5 | SingleValues | booleanValue | true | +| AnnotationValues.java:58:5:71:5 | SingleValues | booleanValue | true | +typeValue +| AnnotationValues.java:39:5:39:17 | SingleValues | classValue | AnnotationValues.java:1:7:1:22 | AnnotationValues | +| AnnotationValues.java:42:5:55:5 | SingleValues | classValue | AnnotationValues.java:23:16:23:27 | SingleValues | +| AnnotationValues.java:58:5:71:5 | SingleValues | classValue | AnnotationValues.java:23:16:23:27 | SingleValues | +arrayValue +| AnnotationValues.java:90:5:90:16 | ArrayValues | annotationValues | 0 | AnnotationValues.class:0:0:0:0 | CustomAnnotation | +| AnnotationValues.java:90:5:90:16 | ArrayValues | booleanValues | 0 | AnnotationValues.class:0:0:0:0 | false | +| AnnotationValues.java:90:5:90:16 | ArrayValues | byteValues | 0 | AnnotationValues.class:0:0:0:0 | -1 | +| AnnotationValues.java:90:5:90:16 | ArrayValues | charValues | 0 | AnnotationValues.class:0:0:0:0 | \uffff | +| AnnotationValues.java:90:5:90:16 | ArrayValues | classValues | 0 | AnnotationValues.class:0:0:0:0 | AnnotationValues.class | +| AnnotationValues.java:90:5:90:16 | ArrayValues | doubleValues | 0 | AnnotationValues.class:0:0:0:0 | -1.0 | +| AnnotationValues.java:90:5:90:16 | ArrayValues | enumValues | 0 | AnnotationValues.class:0:0:0:0 | DEFAULT | +| AnnotationValues.java:90:5:90:16 | ArrayValues | floatValues | 0 | AnnotationValues.class:0:0:0:0 | -1.0 | +| AnnotationValues.java:90:5:90:16 | ArrayValues | intValues | 0 | AnnotationValues.class:0:0:0:0 | -1 | +| AnnotationValues.java:90:5:90:16 | ArrayValues | longValues | 0 | AnnotationValues.class:0:0:0:0 | -1 | +| AnnotationValues.java:90:5:90:16 | ArrayValues | shortValues | 0 | AnnotationValues.class:0:0:0:0 | -1 | +| AnnotationValues.java:90:5:90:16 | ArrayValues | stringValues | 0 | AnnotationValues.class:0:0:0:0 | "\u0000" | +| AnnotationValues.java:93:5:106:5 | ArrayValues | annotationValues | 0 | AnnotationValues.java:105:28:105:54 | CustomAnnotation | +| AnnotationValues.java:93:5:106:5 | ArrayValues | booleanValues | 0 | AnnotationValues.java:100:25:100:28 | true | +| AnnotationValues.java:93:5:106:5 | ArrayValues | byteValues | 0 | AnnotationValues.java:94:22:94:22 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | charValues | 0 | AnnotationValues.java:101:22:101:24 | 'a' | +| AnnotationValues.java:93:5:106:5 | ArrayValues | classValues | 0 | AnnotationValues.java:103:23:103:39 | ArrayValues.class | +| AnnotationValues.java:93:5:106:5 | ArrayValues | doubleValues | 0 | AnnotationValues.java:99:24:99:24 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | enumValues | 0 | AnnotationValues.java:104:22:104:33 | CustomEnum.A | +| AnnotationValues.java:93:5:106:5 | ArrayValues | floatValues | 0 | AnnotationValues.java:98:23:98:23 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | intValues | 0 | AnnotationValues.java:96:21:96:21 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | longValues | 0 | AnnotationValues.java:97:22:97:22 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | shortValues | 0 | AnnotationValues.java:95:23:95:23 | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | stringValues | 0 | AnnotationValues.java:102:24:102:26 | "a" | +| AnnotationValues.java:109:5:122:5 | ArrayValues | annotationValues | 0 | AnnotationValues.java:121:29:121:54 | CustomAnnotation | +| AnnotationValues.java:109:5:122:5 | ArrayValues | annotationValues | 1 | AnnotationValues.java:121:57:121:83 | CustomAnnotation | +| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | 0 | AnnotationValues.class:0:0:0:0 | false | +| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | 1 | AnnotationValues.class:0:0:0:0 | true | +| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | -1 | AnnotationValues.java:116:26:116:30 | false | +| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | -2 | AnnotationValues.java:116:33:116:39 | BOOLEAN | +| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | 0 | AnnotationValues.class:0:0:0:0 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | 1 | AnnotationValues.class:0:0:0:0 | 2 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | -1 | AnnotationValues.java:110:23:110:23 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | -2 | AnnotationValues.java:110:26:110:29 | BYTE | +| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | 0 | AnnotationValues.class:0:0:0:0 | a | +| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | 1 | AnnotationValues.class:0:0:0:0 | b | +| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | -1 | AnnotationValues.java:117:23:117:25 | 'a' | +| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | -2 | AnnotationValues.java:117:28:117:31 | CHAR | +| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | 0 | AnnotationValues.class:0:0:0:0 | SingleValues.class | +| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | 1 | AnnotationValues.class:0:0:0:0 | ArrayValues.class | +| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | -1 | AnnotationValues.java:119:24:119:41 | SingleValues.class | +| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | -2 | AnnotationValues.java:119:44:119:60 | ArrayValues.class | +| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | 0 | AnnotationValues.class:0:0:0:0 | 1.0 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | 1 | AnnotationValues.class:0:0:0:0 | 2.0 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | -1 | AnnotationValues.java:115:25:115:25 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | -2 | AnnotationValues.java:115:28:115:33 | DOUBLE | +| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | 0 | AnnotationValues.class:0:0:0:0 | A | +| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | 1 | AnnotationValues.class:0:0:0:0 | B | +| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | -1 | AnnotationValues.java:120:23:120:34 | CustomEnum.A | +| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | -2 | AnnotationValues.java:120:37:120:48 | CustomEnum.B | +| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | 0 | AnnotationValues.class:0:0:0:0 | 1.0 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | 1 | AnnotationValues.class:0:0:0:0 | 2.0 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | -1 | AnnotationValues.java:114:24:114:24 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | -2 | AnnotationValues.java:114:27:114:31 | FLOAT | +| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | 0 | AnnotationValues.class:0:0:0:0 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | 1 | AnnotationValues.class:0:0:0:0 | 2 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | -1 | AnnotationValues.java:112:22:112:22 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | -2 | AnnotationValues.java:112:25:112:27 | INT | +| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | 0 | AnnotationValues.class:0:0:0:0 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | 1 | AnnotationValues.class:0:0:0:0 | 2 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | -1 | AnnotationValues.java:113:23:113:23 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | -2 | AnnotationValues.java:113:26:113:29 | LONG | +| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | 0 | AnnotationValues.class:0:0:0:0 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | 1 | AnnotationValues.class:0:0:0:0 | 2 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | -1 | AnnotationValues.java:111:24:111:24 | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | -2 | AnnotationValues.java:111:27:111:31 | SHORT | +| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | 0 | AnnotationValues.class:0:0:0:0 | "a" | +| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | 1 | AnnotationValues.class:0:0:0:0 | "b" | +| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | -1 | AnnotationValues.java:118:25:118:27 | "a" | +| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | -2 | AnnotationValues.java:118:30:118:32 | "b" | +enumConstantArrayValue +| AnnotationValues.java:90:5:90:16 | ArrayValues | enumValues | AnnotationValues.java:14:9:14:15 | DEFAULT | +| AnnotationValues.java:93:5:106:5 | ArrayValues | enumValues | AnnotationValues.java:15:9:15:9 | A | +| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | AnnotationValues.java:15:9:15:9 | A | +| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | AnnotationValues.java:16:9:16:9 | B | +stringArrayValue +| AnnotationValues.java:90:5:90:16 | ArrayValues | stringValues | \u0000 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | stringValues | a | +| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | a | +| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | b | +intArrayValue +| AnnotationValues.java:90:5:90:16 | ArrayValues | byteValues | -1 | +| AnnotationValues.java:90:5:90:16 | ArrayValues | charValues | 65535 | +| AnnotationValues.java:90:5:90:16 | ArrayValues | intValues | -1 | +| AnnotationValues.java:90:5:90:16 | ArrayValues | shortValues | -1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | byteValues | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | charValues | 97 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | intValues | 1 | +| AnnotationValues.java:93:5:106:5 | ArrayValues | shortValues | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | 2 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | 97 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | 98 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | 2 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | 1 | +| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | 2 | +typeArrayValue +| AnnotationValues.java:90:5:90:16 | ArrayValues | classValues | AnnotationValues.java:1:7:1:22 | AnnotationValues | +| AnnotationValues.java:93:5:106:5 | ArrayValues | classValues | AnnotationValues.java:74:16:74:26 | ArrayValues | +| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | AnnotationValues.java:23:16:23:27 | SingleValues | +| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | AnnotationValues.java:74:16:74:26 | ArrayValues | diff --git a/java/ql/test/library-tests/annotations/Annotation-values.ql b/java/ql/test/library-tests/annotations/Annotation-values.ql new file mode 100644 index 00000000000..65e7be6650c --- /dev/null +++ b/java/ql/test/library-tests/annotations/Annotation-values.ql @@ -0,0 +1,37 @@ +import java + +class RelevantAnnotation extends Annotation { + RelevantAnnotation() { + getCompilationUnit().hasName("AnnotationValues") and getCompilationUnit().fromSource() + } +} + +query Expr value(RelevantAnnotation a, string name) { result = a.getValue(name) } + +query EnumConstant enumConstantValue(RelevantAnnotation a, string name) { + result = a.getEnumConstantValue(name) +} + +query string stringValue(RelevantAnnotation a, string name) { result = a.getStringValue(name) } + +query int intValue(RelevantAnnotation a, string name) { result = a.getIntValue(name) } + +query boolean booleanValue(RelevantAnnotation a, string name) { result = a.getBooleanValue(name) } + +query Type typeValue(RelevantAnnotation a, string name) { result = a.getTypeValue(name) } + +query Expr arrayValue(RelevantAnnotation a, string name, int index) { + result = a.getArrayValue(name, index) +} + +query EnumConstant enumConstantArrayValue(RelevantAnnotation a, string name) { + result = a.getAnEnumConstantArrayValue(name) +} + +query string stringArrayValue(RelevantAnnotation a, string name) { + result = a.getAStringArrayValue(name) +} + +query int intArrayValue(RelevantAnnotation a, string name) { result = a.getAnIntArrayValue(name) } + +query Type typeArrayValue(RelevantAnnotation a, string name) { result = a.getATypeArrayValue(name) } diff --git a/java/ql/test/library-tests/annotations/AnnotationType.expected b/java/ql/test/library-tests/annotations/AnnotationType.expected new file mode 100644 index 00000000000..77d9abf5016 --- /dev/null +++ b/java/ql/test/library-tests/annotations/AnnotationType.expected @@ -0,0 +1,13 @@ +annotationType +| AnnotationType.java:11:16:11:34 | InheritedAnnotation | inherited | | CLASS | +| AnnotationType.java:14:16:14:35 | DocumentedAnnotation | documented | | CLASS | +| AnnotationType.java:16:16:16:34 | ContainerAnnotation | | | CLASS | +| AnnotationType.java:21:16:21:35 | RepeatableAnnotation | repeatable | | CLASS | +| AnnotationType.java:25:16:25:26 | EmptyTarget | | | CLASS | +| AnnotationType.java:28:16:28:27 | SingleTarget | | ANNOTATION_TYPE | CLASS | +| AnnotationType.java:43:16:43:25 | AllTargets | | ANNOTATION_TYPE,CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,MODULE,PACKAGE,PARAMETER,RECORD_COMPONENT,TYPE_PARAMETER,TYPE_USE | CLASS | +| AnnotationType.java:47:16:47:29 | ClassRetention | | | CLASS | +| AnnotationType.java:50:16:50:31 | RuntimeRetention | | | RUNTIME | +| AnnotationType.java:53:16:53:30 | SourceRetention | | | SOURCE | +containingAnnotationType +| AnnotationType.java:21:16:21:35 | RepeatableAnnotation | AnnotationType.java:16:16:16:34 | ContainerAnnotation | diff --git a/java/ql/test/library-tests/annotations/AnnotationType.java b/java/ql/test/library-tests/annotations/AnnotationType.java new file mode 100644 index 00000000000..94498ce36f2 --- /dev/null +++ b/java/ql/test/library-tests/annotations/AnnotationType.java @@ -0,0 +1,54 @@ +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +class AnnotationType { + @Inherited + @interface InheritedAnnotation {} + + @Documented + @interface DocumentedAnnotation {} + + @interface ContainerAnnotation { + RepeatableAnnotation[] value(); + } + + @Repeatable(ContainerAnnotation.class) + @interface RepeatableAnnotation {} + + + @Target({}) + @interface EmptyTarget {} + + @Target(ElementType.ANNOTATION_TYPE) + @interface SingleTarget {} + + @Target({ + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.FIELD, + ElementType.LOCAL_VARIABLE, + ElementType.METHOD, + ElementType.MODULE, + ElementType.PACKAGE, + ElementType.PARAMETER, + ElementType.RECORD_COMPONENT, + ElementType.TYPE_PARAMETER, + ElementType.TYPE_USE + }) + @interface AllTargets {} + + + @Retention(RetentionPolicy.CLASS) + @interface ClassRetention {} + + @Retention(RetentionPolicy.RUNTIME) + @interface RuntimeRetention {} + + @Retention(RetentionPolicy.SOURCE) + @interface SourceRetention {} +} diff --git a/java/ql/test/library-tests/annotations/AnnotationType.ql b/java/ql/test/library-tests/annotations/AnnotationType.ql new file mode 100644 index 00000000000..268bc876448 --- /dev/null +++ b/java/ql/test/library-tests/annotations/AnnotationType.ql @@ -0,0 +1,46 @@ +import java + +class RelevantAnnotationType extends AnnotationType { + RelevantAnnotationType() { getCompilationUnit().hasName("AnnotationType") } +} + +query predicate annotationType( + RelevantAnnotationType t, string flagsString, string targets, string retentionPolicy +) { + flagsString = + concat(string s | + t.isInherited() and s = "inherited" + or + t.isDocumented() and s = "documented" + or + t.isRepeatable() and s = "repeatable" + | + s, "," order by s + ) and + ( + // Workaround to test if no explicit @Target is specified; in that case any string except + // TYPE_USE, which represents type contexts, is considered a target because it might be + // added to ElementType in a future JDK version + if t.isATargetType("") + then + if t.isATargetType("TYPE_USE") + then targets = "BUG: Includes TYPE_USE" + else targets = "" + else + targets = + concat(string s | + exists(EnumConstant elementType | + elementType.getDeclaringType().hasQualifiedName("java.lang.annotation", "ElementType") and + s = elementType.getName() and + t.isATargetType(s) + ) + | + s, "," order by s + ) + ) and + retentionPolicy = t.getRetentionPolicy() +} + +query AnnotationType containingAnnotationType(RelevantAnnotationType t) { + result = t.getContainingAnnotationType() +} diff --git a/java/ql/test/library-tests/annotations/AnnotationValues.java b/java/ql/test/library-tests/annotations/AnnotationValues.java new file mode 100644 index 00000000000..a40085fe015 --- /dev/null +++ b/java/ql/test/library-tests/annotations/AnnotationValues.java @@ -0,0 +1,124 @@ +class AnnotationValues { + private static final byte BYTE = 2; + private static final short SHORT = 2; + private static final int INT = 2; + private static final long LONG = 2; + private static final float FLOAT = 2; + private static final double DOUBLE = 2; + private static final boolean BOOLEAN = true; + private static final char CHAR = 'b'; + + private static final String STRING = "b"; + + enum CustomEnum { + DEFAULT, + A, + B + } + + @interface CustomAnnotation { + String value(); + } + + @interface SingleValues { + byte byteValue() default -1; + short shortValue() default -1; + int intValue() default -1; + long longValue() default -1; + float floatValue() default -1; + double doubleValue() default -1; + boolean booleanValue() default false; + char charValue() default '\uFFFF'; + + String stringValue() default "\0"; + Class classValue() default AnnotationValues.class; + CustomEnum enumValue() default CustomEnum.DEFAULT; + CustomAnnotation annotationValue() default @CustomAnnotation("default"); + } + + @SingleValues + private int singleValuesDefault; + + @SingleValues( + byteValue = 1, + shortValue = 1, + intValue = 1, + longValue = 1, + floatValue = 1, + doubleValue = 1, + booleanValue = true, + charValue = 1, + stringValue = "a", + classValue = SingleValues.class, + enumValue = CustomEnum.A, + annotationValue = @CustomAnnotation("single") + ) + private int singleValues; + + @SingleValues( + byteValue = BYTE, + shortValue = SHORT, + intValue = INT, + longValue = LONG, + floatValue = FLOAT, + doubleValue = DOUBLE, + booleanValue = BOOLEAN, + charValue = CHAR, + stringValue = STRING, + classValue = SingleValues.class, + enumValue = CustomEnum.A, + annotationValue = @CustomAnnotation("single") + ) + private int singleValuesConstants; + + @interface ArrayValues { + byte[] byteValues() default -1; + short[] shortValues() default -1; + int[] intValues() default -1; + long[] longValues() default -1; + float[] floatValues() default -1; + double[] doubleValues() default -1; + boolean[] booleanValues() default false; + char[] charValues() default '\uFFFF'; + + String[] stringValues() default "\0"; + Class[] classValues() default AnnotationValues.class; + CustomEnum[] enumValues() default CustomEnum.DEFAULT; + CustomAnnotation[] annotationValues() default @CustomAnnotation("default"); + } + + @ArrayValues + private int arrayValuesDefault; + + @ArrayValues( + byteValues = 1, + shortValues = 1, + intValues = 1, + longValues = 1, + floatValues = 1, + doubleValues = 1, + booleanValues = true, + charValues = 'a', + stringValues = "a", + classValues = ArrayValues.class, + enumValues = CustomEnum.A, + annotationValues = @CustomAnnotation("single") + ) + private int arrayValuesSingleExpr; + + @ArrayValues( + byteValues = {1, BYTE}, + shortValues = {1, SHORT}, + intValues = {1, INT}, + longValues = {1, LONG}, + floatValues = {1, FLOAT}, + doubleValues = {1, DOUBLE}, + booleanValues = {false, BOOLEAN}, + charValues = {'a', CHAR}, + stringValues = {"a", "b"}, + classValues = {SingleValues.class, ArrayValues.class}, + enumValues = {CustomEnum.A, CustomEnum.B}, + annotationValues = {@CustomAnnotation("first"), @CustomAnnotation("second")} + ) + private int arrayValues; +} diff --git a/java/ql/test/library-tests/annotations/options b/java/ql/test/library-tests/annotations/options new file mode 100644 index 00000000000..fc57fe025b9 --- /dev/null +++ b/java/ql/test/library-tests/annotations/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -source 16 -target 16 diff --git a/java/ql/test/library-tests/frameworks/thymeleaf/Test.java b/java/ql/test/library-tests/frameworks/thymeleaf/Test.java new file mode 100644 index 00000000000..7d0d193715f --- /dev/null +++ b/java/ql/test/library-tests/frameworks/thymeleaf/Test.java @@ -0,0 +1,61 @@ +package generatedtest; + +import java.util.Map; +import java.util.Set; +import org.thymeleaf.TemplateSpec; +import org.thymeleaf.templatemode.TemplateMode; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object source() { return null; } + void sink(Object o) { } + + public void test() throws Exception { + + { + // "org.thymeleaf;TemplateSpec;false;TemplateSpec;;;Argument[0];Argument[-1];taint;manual" + TemplateSpec out = null; + String in = (String)source(); + out = new TemplateSpec(in, (Map)null); + sink(out); // $ hasTaintFlow + } + { + // "org.thymeleaf;TemplateSpec;false;TemplateSpec;;;Argument[0];Argument[-1];taint;manual" + TemplateSpec out = null; + String in = (String)source(); + out = new TemplateSpec(in, (Set)null, (String)null, (Map)null); + sink(out); // $ hasTaintFlow + } + { + // "org.thymeleaf;TemplateSpec;false;TemplateSpec;;;Argument[0];Argument[-1];taint;manual" + TemplateSpec out = null; + String in = (String)source(); + out = new TemplateSpec(in, (Set)null, (TemplateMode)null, (Map)null); + sink(out); // $ hasTaintFlow + } + { + // "org.thymeleaf;TemplateSpec;false;TemplateSpec;;;Argument[0];Argument[-1];taint;manual" + TemplateSpec out = null; + String in = (String)source(); + out = new TemplateSpec(in, (String)null); + sink(out); // $ hasTaintFlow + } + { + // "org.thymeleaf;TemplateSpec;false;TemplateSpec;;;Argument[0];Argument[-1];taint;manual" + TemplateSpec out = null; + String in = (String)source(); + out = new TemplateSpec(in, (TemplateMode)null); + sink(out); // $ hasTaintFlow + } + { + // "org.thymeleaf;TemplateSpec;false;getTemplate;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + TemplateSpec in = (TemplateSpec)source(); + out = in.getTemplate(); + sink(out); // $ hasTaintFlow + } + + } + +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/thymeleaf/options b/java/ql/test/library-tests/frameworks/thymeleaf/options new file mode 100644 index 00000000000..061e53d9ece --- /dev/null +++ b/java/ql/test/library-tests/frameworks/thymeleaf/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/thymeleaf-3.0.14 \ No newline at end of file diff --git a/swift/ql/test/extractor-tests/generated/expr/UnresolvedDeclRefExpr/UnresolvedDeclRefExpr_getType.expected b/java/ql/test/library-tests/frameworks/thymeleaf/test.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/UnresolvedDeclRefExpr/UnresolvedDeclRefExpr_getType.expected rename to java/ql/test/library-tests/frameworks/thymeleaf/test.expected diff --git a/java/ql/test/library-tests/frameworks/thymeleaf/test.ql b/java/ql/test/library-tests/frameworks/thymeleaf/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/thymeleaf/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/FreemarkerSSTI.java b/java/ql/test/query-tests/security/CWE-094/FreemarkerSSTI.java similarity index 61% rename from java/ql/test/experimental/query-tests/security/CWE-094/FreemarkerSSTI.java rename to java/ql/test/query-tests/security/CWE-094/FreemarkerSSTI.java index 3ac93749616..31eb634a5fe 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-094/FreemarkerSSTI.java +++ b/java/ql/test/query-tests/security/CWE-094/FreemarkerSSTI.java @@ -11,7 +11,7 @@ import java.util.HashMap; import freemarker.template.Template; import freemarker.template.Configuration; import freemarker.cache.StringTemplateLoader; -import freemarker.template.ParserConfiguration; +import freemarker.core.ParserConfiguration; @Controller public class FreemarkerSSTI { @@ -23,8 +23,7 @@ public class FreemarkerSSTI { String code = request.getParameter("code"); Reader reader = new StringReader(code); - // Template(java.lang.String name, java.io.Reader reader) - Template t = new Template(name, reader); + Template t = new Template(name, reader); // $hasTemplateInjection } @GetMapping(value = "bad2") @@ -33,9 +32,8 @@ public class FreemarkerSSTI { String code = request.getParameter("code"); Reader reader = new StringReader(code); Configuration cfg = new Configuration(); - - // Template(java.lang.String name, java.io.Reader reader, Configuration cfg) - Template t = new Template(name, reader, cfg); + + Template t = new Template(name, reader, cfg); // $hasTemplateInjection } @GetMapping(value = "bad3") @@ -45,9 +43,7 @@ public class FreemarkerSSTI { Reader reader = new StringReader(code); Configuration cfg = new Configuration(); - // Template(java.lang.String name, java.io.Reader reader, Configuration cfg, - // java.lang.String encoding) - Template t = new Template(name, reader, cfg, "UTF-8"); + Template t = new Template(name, reader, cfg, "UTF-8"); // $hasTemplateInjection } @GetMapping(value = "bad4") @@ -56,9 +52,7 @@ public class FreemarkerSSTI { String sourceCode = request.getParameter("sourceCode"); Configuration cfg = new Configuration(); - // Template(java.lang.String name, java.lang.String sourceCode, Configuration - // cfg) - Template t = new Template(name, sourceCode, cfg); + Template t = new Template(name, sourceCode, cfg); // $hasTemplateInjection } @GetMapping(value = "bad5") @@ -68,9 +62,7 @@ public class FreemarkerSSTI { Configuration cfg = new Configuration(); Reader reader = new StringReader(code); - // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader - // reader, Configuration cfg) - Template t = new Template(name, sourceName, reader, cfg); + Template t = new Template(name, sourceName, reader, cfg); // $hasTemplateInjection } @GetMapping(value = "bad6") @@ -81,10 +73,8 @@ public class FreemarkerSSTI { ParserConfiguration customParserConfiguration = new Configuration(); Reader reader = new StringReader(code); - // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader - // reader, Configuration cfg, ParserConfiguration customParserConfiguration, - // java.lang.String encoding) - Template t = new Template(name, sourceName, reader, cfg, customParserConfiguration, "UTF-8"); + Template t = + new Template(name, sourceName, reader, cfg, customParserConfiguration, "UTF-8"); // $hasTemplateInjection } @GetMapping(value = "bad7") @@ -95,9 +85,7 @@ public class FreemarkerSSTI { ParserConfiguration customParserConfiguration = new Configuration(); Reader reader = new StringReader(code); - // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader - // reader, Configuration cfg, java.lang.String encoding) - Template t = new Template(name, sourceName, reader, cfg, "UTF-8"); + Template t = new Template(name, sourceName, reader, cfg, "UTF-8"); // $hasTemplateInjection } @GetMapping(value = "bad8") @@ -105,28 +93,25 @@ public class FreemarkerSSTI { String code = request.getParameter("code"); StringTemplateLoader stringLoader = new StringTemplateLoader(); - // void putTemplate(java.lang.String name, java.lang.String templateContent) - stringLoader.putTemplate("myTemplate", code); + stringLoader.putTemplate("myTemplate", code); // $hasTemplateInjection } @GetMapping(value = "bad9") public void bad9(HttpServletRequest request) { String code = request.getParameter("code"); StringTemplateLoader stringLoader = new StringTemplateLoader(); - - // void putTemplate(java.lang.String name, java.lang.String templateContent, - // long lastModified) - stringLoader.putTemplate("myTemplate", code, 0); + + stringLoader.putTemplate("myTemplate", code, 0); // $hasTemplateInjection } - @GetMapping(value = "bad10") - public void bad10(HttpServletRequest request) { - HashMap root = new HashMap(); + @GetMapping(value = "good1") + public void good1(HttpServletRequest request) { + HashMap root = new HashMap(); String code = request.getParameter("code"); - root.put("code", code); + root.put("code", code); Configuration cfg = new Configuration(); - Template temp = cfg.getTemplate("test.ftlh"); - OutputStreamWriter out = new OutputStreamWriter(System.out); - temp.process(root, out); + Template temp = cfg.getTemplate("test.ftlh"); + OutputStreamWriter out = new OutputStreamWriter(System.out); + temp.process(root, out); // Safe } } diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java b/java/ql/test/query-tests/security/CWE-094/JinJavaSSTI.java similarity index 79% rename from java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java rename to java/ql/test/query-tests/security/CWE-094/JinJavaSSTI.java index a5791ae1d57..4341a44f192 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java +++ b/java/ql/test/query-tests/security/CWE-094/JinJavaSSTI.java @@ -21,8 +21,7 @@ public class JinJavaSSTI { String template = request.getParameter("template"); Jinjava jinjava = new Jinjava(); Map context = new HashMap<>(); - // String render(String template, Map bindings) - String renderedTemplate = jinjava.render(template, context); + String renderedTemplate = jinjava.render(template, context); // $hasTemplateInjection } @GetMapping(value = "bad2") @@ -30,8 +29,7 @@ public class JinJavaSSTI { String template = request.getParameter("template"); Jinjava jinjava = new Jinjava(); Map bindings = new HashMap<>(); - // RenderResult renderForResult (String template, Map bindings) - RenderResult renderResult = jinjava.renderForResult(template, bindings); + RenderResult renderResult = jinjava.renderForResult(template, bindings); // $hasTemplateInjection } @GetMapping(value = "bad3") @@ -41,8 +39,6 @@ public class JinJavaSSTI { Map bindings = new HashMap<>(); JinjavaConfig renderConfig = new JinjavaConfig(); - // RenderResult renderForResult (String template, Map bindings, - // JinjavaConfig renderConfig) - RenderResult renderResult = jinjava.renderForResult(template, bindings, renderConfig); + RenderResult renderResult = jinjava.renderForResult(template, bindings, renderConfig); // $hasTemplateInjection } } diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/PebbleSSTI.java b/java/ql/test/query-tests/security/CWE-094/PebbleSSTI.java similarity index 66% rename from java/ql/test/experimental/query-tests/security/CWE-094/PebbleSSTI.java rename to java/ql/test/query-tests/security/CWE-094/PebbleSSTI.java index 13ed42a9b26..c026f98645b 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-094/PebbleSSTI.java +++ b/java/ql/test/query-tests/security/CWE-094/PebbleSSTI.java @@ -15,16 +15,15 @@ public class PebbleSSTI { @GetMapping(value = "bad1") public void bad1(HttpServletRequest request) { - String code = request.getParameter("code"); + String templateName = request.getParameter("templateName"); PebbleEngine engine = new PebbleEngine.Builder().build(); - // public PebbleTemplate getTemplate(String templateName) - PebbleTemplate compiledTemplate = engine.getTemplate(code); + PebbleTemplate compiledTemplate = engine.getTemplate(templateName); // $hasTemplateInjection } + @GetMapping(value = "bad2") public void bad2(HttpServletRequest request) { - String code = request.getParameter("code"); + String templateName = request.getParameter("templateName"); PebbleEngine engine = new PebbleEngine.Builder().build(); - // public PebbleTemplate getLiteralTemplate(String templateName) - PebbleTemplate compiledTemplate = engine.getLiteralTemplate(code); + PebbleTemplate compiledTemplate = engine.getLiteralTemplate(templateName); // $hasTemplateInjection } } diff --git a/swift/ql/test/extractor-tests/generated/expr/UnresolvedPatternExpr/UnresolvedPatternExpr_getType.expected b/java/ql/test/query-tests/security/CWE-094/TemplateInjectionTest.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/UnresolvedPatternExpr/UnresolvedPatternExpr_getType.expected rename to java/ql/test/query-tests/security/CWE-094/TemplateInjectionTest.expected diff --git a/java/ql/test/query-tests/security/CWE-094/TemplateInjectionTest.ql b/java/ql/test/query-tests/security/CWE-094/TemplateInjectionTest.ql new file mode 100644 index 00000000000..b8bb1080f3f --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-094/TemplateInjectionTest.ql @@ -0,0 +1,20 @@ +import java +import semmle.code.java.security.TemplateInjectionQuery +import TestUtilities.InlineExpectationsTest + +class TemplateInjectionTest extends InlineExpectationsTest { + TemplateInjectionTest() { this = "TemplateInjectionTest" } + + override string getARelevantTag() { result = "hasTemplateInjection" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasTemplateInjection" and + exists(DataFlow::Node src, DataFlow::Node sink, TemplateInjectionFlowConfig conf | + conf.hasFlow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} diff --git a/java/ql/test/query-tests/security/CWE-094/ThymeleafSSTI.java b/java/ql/test/query-tests/security/CWE-094/ThymeleafSSTI.java new file mode 100644 index 00000000000..4b390668948 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-094/ThymeleafSSTI.java @@ -0,0 +1,38 @@ +import javax.imageio.stream.FileImageInputStream; +import javax.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +import java.lang.String; +import java.io.File; +import java.io.FileWriter; +import java.io.Reader; +import java.io.StringReader; +import java.io.Writer; +import java.util.Set; + +import org.thymeleaf.*; +import org.thymeleaf.context.Context; + +@Controller +public class ThymeleafSSTI { + @GetMapping(value = "bad1") + public void bad1(HttpServletRequest request) { + String code = request.getParameter("code"); + try { + TemplateEngine templateEngine = new TemplateEngine(); + templateEngine.process(code, (Set) null, (Context) null); // $hasTemplateInjection + templateEngine.process(code, (Set) null, (Context) null, (Writer) null); // $hasTemplateInjection + templateEngine.process(code, (Context) null); // $hasTemplateInjection + templateEngine.process(code, (Context) null, (Writer) null); // $hasTemplateInjection + templateEngine.processThrottled(code, (Set) null, (Context) null); // $hasTemplateInjection + templateEngine.processThrottled(code, (Context) null); // $hasTemplateInjection + + TemplateSpec spec = new TemplateSpec(code, ""); + templateEngine.process(spec, (Context) null); // $hasTemplateInjection + templateEngine.process(spec, (Context) null, (Writer) null); // $hasTemplateInjection + templateEngine.processThrottled(spec, (Context) null); // $hasTemplateInjection + } catch (Exception e) { + } + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/VelocitySSTI.java b/java/ql/test/query-tests/security/CWE-094/VelocitySSTI.java similarity index 71% rename from java/ql/test/experimental/query-tests/security/CWE-094/VelocitySSTI.java rename to java/ql/test/query-tests/security/CWE-094/VelocitySSTI.java index c35dd9b0aae..09c7a07058f 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-094/VelocitySSTI.java +++ b/java/ql/test/query-tests/security/CWE-094/VelocitySSTI.java @@ -34,8 +34,7 @@ public class VelocitySSTI { String s = "We are using $project $name to render this."; StringWriter w = new StringWriter(); - // evaluate( Context context, Writer out, String logTag, String instring ) - Velocity.evaluate(context, w, "mystring", code); + Velocity.evaluate(context, w, "mystring", code); // $hasTemplateInjection } @GetMapping(value = "bad2") @@ -49,8 +48,7 @@ public class VelocitySSTI { StringWriter w = new StringWriter(); StringReader reader = new StringReader(code); - // evaluate(Context context, Writer writer, String logTag, Reader reader) - Velocity.evaluate(context, w, "mystring", reader); + Velocity.evaluate(context, w, "mystring", reader); // $hasTemplateInjection } @GetMapping(value = "bad3") @@ -58,13 +56,13 @@ public class VelocitySSTI { String name = "ttemplate"; String code = request.getParameter("code"); - RuntimeServices runtimeServices = new RuntimeServices(); + RuntimeServices runtimeServices = null; StringReader reader = new StringReader(code); - runtimeServices.parse(reader, new Template()); + runtimeServices.parse(reader, new Template()); // $hasTemplateInjection } - @GetMapping(value = "bad4") - public void bad4(HttpServletRequest request) { + @GetMapping(value = "good1") + public void good1(HttpServletRequest request) { String name = "ttemplate"; String code = request.getParameter("code"); @@ -74,7 +72,7 @@ public class VelocitySSTI { StringWriter w = new StringWriter(); StringReader reader = new StringReader("test"); - Velocity.evaluate(context, w, "mystring", reader); + Velocity.evaluate(context, w, "mystring", reader); // Safe } @GetMapping(value = "bad5") @@ -86,41 +84,37 @@ public class VelocitySSTI { context.put("code", code); StringWriter w = new StringWriter(); - VelocityEngine.mergeTemplate("testtemplate.vm", "UTF-8", context, w); + VelocityEngine engine = null; + engine.mergeTemplate("testtemplate.vm", "UTF-8", context, w); // Safe + AbstractContext ctx = null; + ctx.put("key", code); + engine.evaluate(ctx, null, null, (String) null); // Safe + engine.evaluate(ctx, null, null, (Reader) null); // Safe + engine.evaluate(null, null, null, code); // $hasTemplateInjection + engine.evaluate(null, null, null, new StringReader(code)); // $hasTemplateInjection + } + + @GetMapping(value = "good2") + public void good2(HttpServletRequest request) { + String name = "ttemplate"; + String code = request.getParameter("code"); + + VelocityContext context = new VelocityContext(); + context.put("code", code); + + StringWriter w = new StringWriter(); + Template t = new Template(); + t.merge(context, w); // Safe + t.merge(context, w, new LinkedList()); // Safe + } @GetMapping(value = "bad6") public void bad6(HttpServletRequest request) { - String name = "ttemplate"; - String code = request.getParameter("code"); - - VelocityContext context = new VelocityContext(); - context.put("code", code); - - StringWriter w = new StringWriter(); - Template t = new Template(); - t.merge(context, w); - } - - @GetMapping(value = "bad7") - public void bad7(HttpServletRequest request) { - String name = "ttemplate"; - String code = request.getParameter("code"); - - VelocityContext context = new VelocityContext(); - context.put("code", code); - - StringWriter w = new StringWriter(); - Template t = new Template(); - t.merge(context, w, new LinkedList()); - } - - @GetMapping(value = "bad8") - public void bad8(HttpServletRequest request) { String code = request.getParameter("code"); StringResourceRepository repo = new StringResourceRepositoryImpl(); - repo.putStringResource("woogie2", code); + repo.putStringResource("woogie2", code); // $hasTemplateInjection } } diff --git a/java/ql/test/query-tests/security/CWE-094/options b/java/ql/test/query-tests/security/CWE-094/options index 1b4bd12d17f..72dc22e6bd3 100644 --- a/java/ql/test/query-tests/security/CWE-094/options +++ b/java/ql/test/query-tests/security/CWE-094/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/validation-api-2.0.1.Final:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../stubs/apache-commons-logging-1.2:${testdir}/../../../stubs/mvel2-2.4.7:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/scriptengine:${testdir}/../../../stubs/jsr223-api +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/validation-api-2.0.1.Final:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../stubs/apache-commons-logging-1.2:${testdir}/../../../stubs/mvel2-2.4.7:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/scriptengine:${testdir}/../../../stubs/jsr223-api:${testdir}/../../../stubs/apache-freemarker-2.3.31:${testdir}/../../../stubs/jinjava-2.6.0:${testdir}/../../../stubs/pebble-3.1.5:${testdir}/../../../stubs/thymeleaf-3.0.14:${testdir}/../../../stubs/apache-velocity-2.3 diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/CacheStorage.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/CacheStorage.java new file mode 100644 index 00000000000..b654a411c48 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/CacheStorage.java @@ -0,0 +1,12 @@ +// Generated automatically from freemarker.cache.CacheStorage for testing purposes + +package freemarker.cache; + + +public interface CacheStorage +{ + Object get(Object p0); + void clear(); + void put(Object p0, Object p1); + void remove(Object p0); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/StringTemplateLoader.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/StringTemplateLoader.java new file mode 100644 index 00000000000..524b2d07621 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/StringTemplateLoader.java @@ -0,0 +1,19 @@ +// Generated automatically from freemarker.cache.StringTemplateLoader for testing purposes + +package freemarker.cache; + +import freemarker.cache.TemplateLoader; +import java.io.Reader; + +public class StringTemplateLoader implements TemplateLoader +{ + public Object findTemplateSource(String p0){ return null; } + public Reader getReader(Object p0, String p1){ return null; } + public String toString(){ return null; } + public StringTemplateLoader(){} + public boolean removeTemplate(String p0){ return false; } + public long getLastModified(Object p0){ return 0; } + public void closeTemplateSource(Object p0){} + public void putTemplate(String p0, String p1){} + public void putTemplate(String p0, String p1, long p2){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateConfigurationFactory.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateConfigurationFactory.java new file mode 100644 index 00000000000..c61f916b8f1 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateConfigurationFactory.java @@ -0,0 +1,15 @@ +// Generated automatically from freemarker.cache.TemplateConfigurationFactory for testing purposes + +package freemarker.cache; + +import freemarker.core.TemplateConfiguration; +import freemarker.template.Configuration; + +abstract public class TemplateConfigurationFactory +{ + protected abstract void setConfigurationOfChildren(Configuration p0); + public Configuration getConfiguration(){ return null; } + public TemplateConfigurationFactory(){} + public abstract TemplateConfiguration get(String p0, Object p1); + public final void setConfiguration(Configuration p0){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLoader.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLoader.java new file mode 100644 index 00000000000..a301fa50a89 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLoader.java @@ -0,0 +1,13 @@ +// Generated automatically from freemarker.cache.TemplateLoader for testing purposes + +package freemarker.cache; + +import java.io.Reader; + +public interface TemplateLoader +{ + Object findTemplateSource(String p0); + Reader getReader(Object p0, String p1); + long getLastModified(Object p0); + void closeTemplateSource(Object p0); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLookupContext.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLookupContext.java new file mode 100644 index 00000000000..42e29d77cf2 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLookupContext.java @@ -0,0 +1,17 @@ +// Generated automatically from freemarker.cache.TemplateLookupContext for testing purposes + +package freemarker.cache; + +import freemarker.cache.TemplateLookupResult; +import java.util.Locale; + +abstract public class TemplateLookupContext +{ + protected TemplateLookupContext() {} + public Locale getTemplateLocale(){ return null; } + public Object getCustomLookupCondition(){ return null; } + public String getTemplateName(){ return null; } + public TemplateLookupResult createNegativeLookupResult(){ return null; } + public abstract TemplateLookupResult lookupWithAcquisitionStrategy(String p0); + public abstract TemplateLookupResult lookupWithLocalizedThenAcquisitionStrategy(String p0, Locale p1); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLookupResult.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLookupResult.java new file mode 100644 index 00000000000..1ed7bd94dbe --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLookupResult.java @@ -0,0 +1,11 @@ +// Generated automatically from freemarker.cache.TemplateLookupResult for testing purposes + +package freemarker.cache; + + +abstract public class TemplateLookupResult +{ + protected TemplateLookupResult() {} + public abstract String getTemplateSourceName(); + public abstract boolean isPositive(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLookupStrategy.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLookupStrategy.java new file mode 100644 index 00000000000..ef365997e57 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateLookupStrategy.java @@ -0,0 +1,13 @@ +// Generated automatically from freemarker.cache.TemplateLookupStrategy for testing purposes + +package freemarker.cache; + +import freemarker.cache.TemplateLookupContext; +import freemarker.cache.TemplateLookupResult; + +abstract public class TemplateLookupStrategy +{ + public TemplateLookupStrategy(){} + public abstract TemplateLookupResult lookup(TemplateLookupContext p0); + public static TemplateLookupStrategy DEFAULT_2_3_0 = null; +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateNameFormat.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateNameFormat.java new file mode 100644 index 00000000000..78682aee7ec --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/cache/TemplateNameFormat.java @@ -0,0 +1,11 @@ +// Generated automatically from freemarker.cache.TemplateNameFormat for testing purposes + +package freemarker.cache; + + +abstract public class TemplateNameFormat +{ + protected TemplateNameFormat() {} + public static TemplateNameFormat DEFAULT_2_3_0 = null; + public static TemplateNameFormat DEFAULT_2_4_0 = null; +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/ArithmeticEngine.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/ArithmeticEngine.java new file mode 100644 index 00000000000..34f0d04115e --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/ArithmeticEngine.java @@ -0,0 +1,46 @@ +// Generated automatically from freemarker.core.ArithmeticEngine for testing purposes + +package freemarker.core; + + +abstract public class ArithmeticEngine +{ + protected int maxScale = 0; + protected int minScale = 0; + protected int roundingPolicy = 0; + public ArithmeticEngine(){} + public abstract Number add(Number p0, Number p1); + public abstract Number divide(Number p0, Number p1); + public abstract Number modulus(Number p0, Number p1); + public abstract Number multiply(Number p0, Number p1); + public abstract Number subtract(Number p0, Number p1); + public abstract Number toNumber(String p0); + public abstract int compareNumbers(Number p0, Number p1); + public static ArithmeticEngine.BigDecimalEngine BIGDECIMAL_ENGINE = null; + public static ArithmeticEngine.ConservativeEngine CONSERVATIVE_ENGINE = null; + public void setMaxScale(int p0){} + public void setMinScale(int p0){} + public void setRoundingPolicy(int p0){} + static public class BigDecimalEngine extends ArithmeticEngine + { + public BigDecimalEngine(){} + public Number add(Number p0, Number p1){ return null; } + public Number divide(Number p0, Number p1){ return null; } + public Number modulus(Number p0, Number p1){ return null; } + public Number multiply(Number p0, Number p1){ return null; } + public Number subtract(Number p0, Number p1){ return null; } + public Number toNumber(String p0){ return null; } + public int compareNumbers(Number p0, Number p1){ return 0; } + } + static public class ConservativeEngine extends ArithmeticEngine + { + public ConservativeEngine(){} + public Number add(Number p0, Number p1){ return null; } + public Number divide(Number p0, Number p1){ return null; } + public Number modulus(Number p0, Number p1){ return null; } + public Number multiply(Number p0, Number p1){ return null; } + public Number subtract(Number p0, Number p1){ return null; } + public Number toNumber(String p0){ return null; } + public int compareNumbers(Number p0, Number p1){ return 0; } + } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Configurable.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Configurable.java new file mode 100644 index 00000000000..f92fd4bd038 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Configurable.java @@ -0,0 +1,238 @@ +// Generated automatically from freemarker.core.Configurable for testing purposes + +package freemarker.core; + +import freemarker.core.ArithmeticEngine; +import freemarker.core.Environment; +import freemarker.core.TemplateClassResolver; +import freemarker.core.TemplateDateFormatFactory; +import freemarker.core.TemplateNumberFormatFactory; +import freemarker.core.TruncateBuiltinAlgorithm; +import freemarker.template.AttemptExceptionReporter; +import freemarker.template.ObjectWrapper; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; +import freemarker.template.Version; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TimeZone; + +public class Configurable +{ + protected ArrayList parseAsList(String p0){ return null; } + protected ArrayList parseAsSegmentedList(String p0){ return null; } + protected Configurable(Version p0){} + protected Environment getEnvironment(){ return null; } + protected HashMap parseAsImportList(String p0){ return null; } + protected Object clone(){ return null; } + protected String getCorrectedNameForUnknownSetting(String p0){ return null; } + protected TemplateException invalidSettingValueException(String p0, String p1){ return null; } + protected TemplateException settingValueAssignmentException(String p0, String p1, Throwable p2){ return null; } + protected TemplateException unknownSettingException(String p0){ return null; } + protected void doAutoImportsAndIncludes(Environment p0){} + public ArithmeticEngine getArithmeticEngine(){ return null; } + public AttemptExceptionReporter getAttemptExceptionReporter(){ return null; } + public Boolean getLazyAutoImports(){ return null; } + public Configurable(){} + public Configurable(Configurable p0){} + public List getAutoIncludes(){ return null; } + public List getAutoIncludesWithoutFallback(){ return null; } + public Locale getLocale(){ return null; } + public Map getSettings(){ return null; } + public Map getCustomDateFormats(){ return null; } + public Map getCustomDateFormatsWithoutFallback(){ return null; } + public Map getCustomNumberFormats(){ return null; } + public Map getCustomNumberFormatsWithoutFallback(){ return null; } + public Map getAutoImports(){ return null; } + public Map getAutoImportsWithoutFallback(){ return null; } + public Object getCustomAttribute(String p0){ return null; } + public ObjectWrapper getObjectWrapper(){ return null; } + public Set getSettingNames(boolean p0){ return null; } + public String getBooleanFormat(){ return null; } + public String getDateFormat(){ return null; } + public String getDateTimeFormat(){ return null; } + public String getNumberFormat(){ return null; } + public String getOutputEncoding(){ return null; } + public String getSetting(String p0){ return null; } + public String getTimeFormat(){ return null; } + public String getURLEscapingCharset(){ return null; } + public String[] getCustomAttributeNames(){ return null; } + public TemplateClassResolver getNewBuiltinClassResolver(){ return null; } + public TemplateDateFormatFactory getCustomDateFormat(String p0){ return null; } + public TemplateExceptionHandler getTemplateExceptionHandler(){ return null; } + public TemplateNumberFormatFactory getCustomNumberFormat(String p0){ return null; } + public TimeZone getSQLDateAndTimeTimeZone(){ return null; } + public TimeZone getTimeZone(){ return null; } + public TruncateBuiltinAlgorithm getTruncateBuiltinAlgorithm(){ return null; } + public boolean getAutoFlush(){ return false; } + public boolean getLazyImports(){ return false; } + public boolean getLogTemplateExceptions(){ return false; } + public boolean getShowErrorTips(){ return false; } + public boolean getWrapUncheckedExceptions(){ return false; } + public boolean hasCustomFormats(){ return false; } + public boolean isAPIBuiltinEnabled(){ return false; } + public boolean isAPIBuiltinEnabledSet(){ return false; } + public boolean isArithmeticEngineSet(){ return false; } + public boolean isAttemptExceptionReporterSet(){ return false; } + public boolean isAutoFlushSet(){ return false; } + public boolean isAutoImportsSet(){ return false; } + public boolean isAutoIncludesSet(){ return false; } + public boolean isBooleanFormatSet(){ return false; } + public boolean isClassicCompatible(){ return false; } + public boolean isClassicCompatibleSet(){ return false; } + public boolean isCustomDateFormatsSet(){ return false; } + public boolean isCustomNumberFormatsSet(){ return false; } + public boolean isDateFormatSet(){ return false; } + public boolean isDateTimeFormatSet(){ return false; } + public boolean isLazyAutoImportsSet(){ return false; } + public boolean isLazyImportsSet(){ return false; } + public boolean isLocaleSet(){ return false; } + public boolean isLogTemplateExceptionsSet(){ return false; } + public boolean isNewBuiltinClassResolverSet(){ return false; } + public boolean isNumberFormatSet(){ return false; } + public boolean isObjectWrapperSet(){ return false; } + public boolean isOutputEncodingSet(){ return false; } + public boolean isSQLDateAndTimeTimeZoneSet(){ return false; } + public boolean isShowErrorTipsSet(){ return false; } + public boolean isTemplateExceptionHandlerSet(){ return false; } + public boolean isTimeFormatSet(){ return false; } + public boolean isTimeZoneSet(){ return false; } + public boolean isTruncateBuiltinAlgorithmSet(){ return false; } + public boolean isURLEscapingCharsetSet(){ return false; } + public boolean isWrapUncheckedExceptionsSet(){ return false; } + public final Configurable getParent(){ return null; } + public int getClassicCompatibleAsInt(){ return 0; } + public static String API_BUILTIN_ENABLED_KEY = null; + public static String API_BUILTIN_ENABLED_KEY_CAMEL_CASE = null; + public static String API_BUILTIN_ENABLED_KEY_SNAKE_CASE = null; + public static String ARITHMETIC_ENGINE_KEY = null; + public static String ARITHMETIC_ENGINE_KEY_CAMEL_CASE = null; + public static String ARITHMETIC_ENGINE_KEY_SNAKE_CASE = null; + public static String ATTEMPT_EXCEPTION_REPORTER_KEY = null; + public static String ATTEMPT_EXCEPTION_REPORTER_KEY_CAMEL_CASE = null; + public static String ATTEMPT_EXCEPTION_REPORTER_KEY_SNAKE_CASE = null; + public static String AUTO_FLUSH_KEY = null; + public static String AUTO_FLUSH_KEY_CAMEL_CASE = null; + public static String AUTO_FLUSH_KEY_SNAKE_CASE = null; + public static String AUTO_IMPORT_KEY = null; + public static String AUTO_IMPORT_KEY_CAMEL_CASE = null; + public static String AUTO_IMPORT_KEY_SNAKE_CASE = null; + public static String AUTO_INCLUDE_KEY = null; + public static String AUTO_INCLUDE_KEY_CAMEL_CASE = null; + public static String AUTO_INCLUDE_KEY_SNAKE_CASE = null; + public static String BOOLEAN_FORMAT_KEY = null; + public static String BOOLEAN_FORMAT_KEY_CAMEL_CASE = null; + public static String BOOLEAN_FORMAT_KEY_SNAKE_CASE = null; + public static String CLASSIC_COMPATIBLE_KEY = null; + public static String CLASSIC_COMPATIBLE_KEY_CAMEL_CASE = null; + public static String CLASSIC_COMPATIBLE_KEY_SNAKE_CASE = null; + public static String CUSTOM_DATE_FORMATS_KEY = null; + public static String CUSTOM_DATE_FORMATS_KEY_CAMEL_CASE = null; + public static String CUSTOM_DATE_FORMATS_KEY_SNAKE_CASE = null; + public static String CUSTOM_NUMBER_FORMATS_KEY = null; + public static String CUSTOM_NUMBER_FORMATS_KEY_CAMEL_CASE = null; + public static String CUSTOM_NUMBER_FORMATS_KEY_SNAKE_CASE = null; + public static String DATETIME_FORMAT_KEY = null; + public static String DATETIME_FORMAT_KEY_CAMEL_CASE = null; + public static String DATETIME_FORMAT_KEY_SNAKE_CASE = null; + public static String DATE_FORMAT_KEY = null; + public static String DATE_FORMAT_KEY_CAMEL_CASE = null; + public static String DATE_FORMAT_KEY_SNAKE_CASE = null; + public static String LAZY_AUTO_IMPORTS_KEY = null; + public static String LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE = null; + public static String LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE = null; + public static String LAZY_IMPORTS_KEY = null; + public static String LAZY_IMPORTS_KEY_CAMEL_CASE = null; + public static String LAZY_IMPORTS_KEY_SNAKE_CASE = null; + public static String LOCALE_KEY = null; + public static String LOCALE_KEY_CAMEL_CASE = null; + public static String LOCALE_KEY_SNAKE_CASE = null; + public static String LOG_TEMPLATE_EXCEPTIONS_KEY = null; + public static String LOG_TEMPLATE_EXCEPTIONS_KEY_CAMEL_CASE = null; + public static String LOG_TEMPLATE_EXCEPTIONS_KEY_SNAKE_CASE = null; + public static String NEW_BUILTIN_CLASS_RESOLVER_KEY = null; + public static String NEW_BUILTIN_CLASS_RESOLVER_KEY_CAMEL_CASE = null; + public static String NEW_BUILTIN_CLASS_RESOLVER_KEY_SNAKE_CASE = null; + public static String NUMBER_FORMAT_KEY = null; + public static String NUMBER_FORMAT_KEY_CAMEL_CASE = null; + public static String NUMBER_FORMAT_KEY_SNAKE_CASE = null; + public static String OBJECT_WRAPPER_KEY = null; + public static String OBJECT_WRAPPER_KEY_CAMEL_CASE = null; + public static String OBJECT_WRAPPER_KEY_SNAKE_CASE = null; + public static String OUTPUT_ENCODING_KEY = null; + public static String OUTPUT_ENCODING_KEY_CAMEL_CASE = null; + public static String OUTPUT_ENCODING_KEY_SNAKE_CASE = null; + public static String SHOW_ERROR_TIPS_KEY = null; + public static String SHOW_ERROR_TIPS_KEY_CAMEL_CASE = null; + public static String SHOW_ERROR_TIPS_KEY_SNAKE_CASE = null; + public static String SQL_DATE_AND_TIME_TIME_ZONE_KEY = null; + public static String SQL_DATE_AND_TIME_TIME_ZONE_KEY_CAMEL_CASE = null; + public static String SQL_DATE_AND_TIME_TIME_ZONE_KEY_SNAKE_CASE = null; + public static String STRICT_BEAN_MODELS = null; + public static String STRICT_BEAN_MODELS_KEY = null; + public static String STRICT_BEAN_MODELS_KEY_CAMEL_CASE = null; + public static String STRICT_BEAN_MODELS_KEY_SNAKE_CASE = null; + public static String TEMPLATE_EXCEPTION_HANDLER_KEY = null; + public static String TEMPLATE_EXCEPTION_HANDLER_KEY_CAMEL_CASE = null; + public static String TEMPLATE_EXCEPTION_HANDLER_KEY_SNAKE_CASE = null; + public static String TIME_FORMAT_KEY = null; + public static String TIME_FORMAT_KEY_CAMEL_CASE = null; + public static String TIME_FORMAT_KEY_SNAKE_CASE = null; + public static String TIME_ZONE_KEY = null; + public static String TIME_ZONE_KEY_CAMEL_CASE = null; + public static String TIME_ZONE_KEY_SNAKE_CASE = null; + public static String TRUNCATE_BUILTIN_ALGORITHM_KEY = null; + public static String TRUNCATE_BUILTIN_ALGORITHM_KEY_CAMEL_CASE = null; + public static String TRUNCATE_BUILTIN_ALGORITHM_KEY_SNAKE_CASE = null; + public static String URL_ESCAPING_CHARSET_KEY = null; + public static String URL_ESCAPING_CHARSET_KEY_CAMEL_CASE = null; + public static String URL_ESCAPING_CHARSET_KEY_SNAKE_CASE = null; + public static String WRAP_UNCHECKED_EXCEPTIONS_KEY = null; + public static String WRAP_UNCHECKED_EXCEPTIONS_KEY_CAMEL_CASE = null; + public static String WRAP_UNCHECKED_EXCEPTIONS_KEY_SNAKE_CASE = null; + public void addAutoImport(String p0, String p1){} + public void addAutoInclude(String p0){} + public void removeAutoImport(String p0){} + public void removeAutoInclude(String p0){} + public void removeCustomAttribute(String p0){} + public void setAPIBuiltinEnabled(boolean p0){} + public void setArithmeticEngine(ArithmeticEngine p0){} + public void setAttemptExceptionReporter(AttemptExceptionReporter p0){} + public void setAutoFlush(boolean p0){} + public void setAutoImports(Map p0){} + public void setAutoIncludes(List p0){} + public void setBooleanFormat(String p0){} + public void setClassicCompatible(boolean p0){} + public void setClassicCompatibleAsInt(int p0){} + public void setCustomAttribute(String p0, Object p1){} + public void setCustomDateFormats(Map p0){} + public void setCustomNumberFormats(Map p0){} + public void setDateFormat(String p0){} + public void setDateTimeFormat(String p0){} + public void setLazyAutoImports(Boolean p0){} + public void setLazyImports(boolean p0){} + public void setLocale(Locale p0){} + public void setLogTemplateExceptions(boolean p0){} + public void setNewBuiltinClassResolver(TemplateClassResolver p0){} + public void setNumberFormat(String p0){} + public void setObjectWrapper(ObjectWrapper p0){} + public void setOutputEncoding(String p0){} + public void setSQLDateAndTimeTimeZone(TimeZone p0){} + public void setSetting(String p0, String p1){} + public void setSettings(InputStream p0){} + public void setSettings(Properties p0){} + public void setShowErrorTips(boolean p0){} + public void setStrictBeanModels(boolean p0){} + public void setTemplateExceptionHandler(TemplateExceptionHandler p0){} + public void setTimeFormat(String p0){} + public void setTimeZone(TimeZone p0){} + public void setTruncateBuiltinAlgorithm(TruncateBuiltinAlgorithm p0){} + public void setURLEscapingCharset(String p0){} + public void setWrapUncheckedExceptions(boolean p0){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/DirectiveCallPlace.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/DirectiveCallPlace.java new file mode 100644 index 00000000000..12546f43f7b --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/DirectiveCallPlace.java @@ -0,0 +1,17 @@ +// Generated automatically from freemarker.core.DirectiveCallPlace for testing purposes + +package freemarker.core; + +import freemarker.template.Template; +import freemarker.template.utility.ObjectFactory; + +public interface DirectiveCallPlace +{ + Object getOrCreateCustomData(Object p0, ObjectFactory p1); + Template getTemplate(); + boolean isNestedOutputCacheable(); + int getBeginColumn(); + int getBeginLine(); + int getEndColumn(); + int getEndLine(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Environment.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Environment.java new file mode 100644 index 00000000000..0ba487d9484 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Environment.java @@ -0,0 +1,106 @@ +// Generated automatically from freemarker.core.Environment for testing purposes + +package freemarker.core; + +import freemarker.core.Configurable; +import freemarker.core.DirectiveCallPlace; +import freemarker.core.TemplateDateFormat; +import freemarker.core.TemplateElement; +import freemarker.core.TemplateNumberFormat; +import freemarker.template.Configuration; +import freemarker.template.SimpleHash; +import freemarker.template.Template; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateExceptionHandler; +import freemarker.template.TemplateHashModel; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateNodeModel; +import java.io.PrintWriter; +import java.io.Writer; +import java.text.NumberFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; + +public class Environment extends Configurable +{ + protected Environment() {} + public Configuration getConfiguration(){ return null; } + public DirectiveCallPlace getCurrentDirectiveCallPlace(){ return null; } + public Environment(Template p0, TemplateHashModel p1, Writer p2){} + public Environment.Namespace getCurrentNamespace(){ return null; } + public Environment.Namespace getGlobalNamespace(){ return null; } + public Environment.Namespace getMainNamespace(){ return null; } + public Environment.Namespace getNamespace(String p0){ return null; } + public Environment.Namespace importLib(String p0, String p1){ return null; } + public Environment.Namespace importLib(String p0, String p1, boolean p2){ return null; } + public Environment.Namespace importLib(Template p0, String p1){ return null; } + public NumberFormat getCNumberFormat(){ return null; } + public Object __getitem__(String p0){ return null; } + public Object getCustomState(Object p0){ return null; } + public Object setCustomState(Object p0, Object p1){ return null; } + public Set getKnownVariableNames(){ return null; } + public String getDefaultNS(){ return null; } + public String getNamespaceForPrefix(String p0){ return null; } + public String getPrefixForNamespace(String p0){ return null; } + public String rootBasedToAbsoluteTemplateName(String p0){ return null; } + public String toFullTemplateName(String p0, String p1){ return null; } + public Template getCurrentTemplate(){ return null; } + public Template getMainTemplate(){ return null; } + public Template getTemplate(){ return null; } + public Template getTemplateForImporting(String p0){ return null; } + public Template getTemplateForInclusion(String p0, String p1, boolean p2){ return null; } + public Template getTemplateForInclusion(String p0, String p1, boolean p2, boolean p3){ return null; } + public TemplateDateFormat getTemplateDateFormat(String p0, int p1, Class p2){ return null; } + public TemplateDateFormat getTemplateDateFormat(String p0, int p1, Class p2, Locale p3){ return null; } + public TemplateDateFormat getTemplateDateFormat(String p0, int p1, Class p2, Locale p3, TimeZone p4, TimeZone p5){ return null; } + public TemplateDateFormat getTemplateDateFormat(String p0, int p1, Locale p2, TimeZone p3, boolean p4){ return null; } + public TemplateDateFormat getTemplateDateFormat(int p0, Class p1){ return null; } + public TemplateHashModel getDataModel(){ return null; } + public TemplateHashModel getGlobalVariables(){ return null; } + public TemplateModel getDataModelOrSharedVariable(String p0){ return null; } + public TemplateModel getGlobalVariable(String p0){ return null; } + public TemplateModel getLocalVariable(String p0){ return null; } + public TemplateModel getVariable(String p0){ return null; } + public TemplateNodeModel getCurrentVisitorNode(){ return null; } + public TemplateNumberFormat getTemplateNumberFormat(){ return null; } + public TemplateNumberFormat getTemplateNumberFormat(String p0){ return null; } + public TemplateNumberFormat getTemplateNumberFormat(String p0, Locale p1){ return null; } + public Writer getOut(){ return null; } + public boolean applyEqualsOperator(TemplateModel p0, TemplateModel p1){ return false; } + public boolean applyEqualsOperatorLenient(TemplateModel p0, TemplateModel p1){ return false; } + public boolean applyGreaterThanOperator(TemplateModel p0, TemplateModel p1){ return false; } + public boolean applyLessThanOperator(TemplateModel p0, TemplateModel p1){ return false; } + public boolean applyLessThanOrEqualsOperator(TemplateModel p0, TemplateModel p1){ return false; } + public boolean applyWithGreaterThanOrEqualsOperator(TemplateModel p0, TemplateModel p1){ return false; } + public boolean isInAttemptBlock(){ return false; } + public class Namespace extends SimpleHash + { + public Template getTemplate(){ return null; } + } + public static Environment getCurrentEnvironment(){ return null; } + public void __setitem__(String p0, Object p1){} + public void include(String p0, String p1, boolean p2){} + public void include(Template p0){} + public void outputInstructionStack(PrintWriter p0){} + public void process(){} + public void setCurrentVisitorNode(TemplateNodeModel p0){} + public void setDateFormat(String p0){} + public void setDateTimeFormat(String p0){} + public void setGlobalVariable(String p0, TemplateModel p1){} + public void setLocalVariable(String p0, TemplateModel p1){} + public void setLocale(Locale p0){} + public void setNumberFormat(String p0){} + public void setOut(Writer p0){} + public void setOutputEncoding(String p0){} + public void setSQLDateAndTimeTimeZone(TimeZone p0){} + public void setTemplateExceptionHandler(TemplateExceptionHandler p0){} + public void setTimeFormat(String p0){} + public void setTimeZone(TimeZone p0){} + public void setURLEscapingCharset(String p0){} + public void setVariable(String p0, TemplateModel p1){} + public void visit(TemplateElement p0, TemplateDirectiveModel p1, Map p2, List p3){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Expression.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Expression.java new file mode 100644 index 00000000000..7ed1c62835a --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Expression.java @@ -0,0 +1,21 @@ +// Generated automatically from freemarker.core.Expression for testing purposes + +package freemarker.core; + +import freemarker.core.Environment; +import freemarker.core.TemplateObject; +import freemarker.template.TemplateModel; + +abstract public class Expression extends TemplateObject { + protected abstract Expression deepCloneWithIdentifierReplaced_inner(String p0, Expression p1, + Expression.ReplacemenetState p2); + + public Expression() {} + + public final TemplateModel getAsTemplateModel(Environment p0) { + return null; + } + + class ReplacemenetState { + } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/LibraryLoad.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/LibraryLoad.java new file mode 100644 index 00000000000..abc530760d3 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/LibraryLoad.java @@ -0,0 +1,12 @@ +// Generated automatically from freemarker.core.LibraryLoad for testing purposes + +package freemarker.core; + +import freemarker.core.TemplateElement; + +public class LibraryLoad extends TemplateElement +{ + protected LibraryLoad() {} + protected String dump(boolean p0){ return null; } + public String getTemplateName(){ return null; } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/LocalContext.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/LocalContext.java new file mode 100644 index 00000000000..4bd991a6275 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/LocalContext.java @@ -0,0 +1,12 @@ +// Generated automatically from freemarker.core.LocalContext for testing purposes + +package freemarker.core; + +import freemarker.template.TemplateModel; +import java.util.Collection; + +public interface LocalContext +{ + Collection getLocalVariableNames(); + TemplateModel getLocalVariable(String p0); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Macro.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Macro.java new file mode 100644 index 00000000000..6be750b4e26 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/Macro.java @@ -0,0 +1,49 @@ +// Generated automatically from freemarker.core.Macro for testing purposes + +package freemarker.core; + +import freemarker.core.LocalContext; +import freemarker.core.TemplateElement; +import freemarker.template.TemplateHashModelEx; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateSequenceModel; +import java.util.Collection; + +public class Macro extends TemplateElement implements TemplateModel { + protected Macro() {} + + protected String dump(boolean p0) { + return null; + } + + public Macro.WithArgs getWithArgs() { + return null; + } + + public Object getNamespaceLookupKey() { + return null; + } + + public String getCatchAll() { + return null; + } + + public String getName() { + return null; + } + + public String[] getArgumentNames() { + return null; + } + + public boolean hasArgNamed(String p0) { + return false; + } + + public boolean isFunction() { + return false; + } + + class WithArgs { + } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/OutputFormat.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/OutputFormat.java new file mode 100644 index 00000000000..f6fd1f37982 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/OutputFormat.java @@ -0,0 +1,14 @@ +// Generated automatically from freemarker.core.OutputFormat for testing purposes + +package freemarker.core; + + +abstract public class OutputFormat +{ + protected String toStringExtraProperties(){ return null; } + public OutputFormat(){} + public abstract String getMimeType(); + public abstract String getName(); + public abstract boolean isOutputFormatMixingAllowed(); + public final String toString(){ return null; } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/ParserConfiguration.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/ParserConfiguration.java new file mode 100644 index 00000000000..8a1fd56afc1 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/ParserConfiguration.java @@ -0,0 +1,22 @@ +// Generated automatically from freemarker.core.ParserConfiguration for testing purposes + +package freemarker.core; + +import freemarker.core.ArithmeticEngine; +import freemarker.core.OutputFormat; +import freemarker.template.Version; + +public interface ParserConfiguration +{ + ArithmeticEngine getArithmeticEngine(); + OutputFormat getOutputFormat(); + Version getIncompatibleImprovements(); + boolean getRecognizeStandardFileExtensions(); + boolean getStrictSyntaxMode(); + boolean getWhitespaceStripping(); + int getAutoEscapingPolicy(); + int getInterpolationSyntax(); + int getNamingConvention(); + int getTabSize(); + int getTagSyntax(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateClassResolver.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateClassResolver.java new file mode 100644 index 00000000000..9ad07af08e7 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateClassResolver.java @@ -0,0 +1,14 @@ +// Generated automatically from freemarker.core.TemplateClassResolver for testing purposes + +package freemarker.core; + +import freemarker.core.Environment; +import freemarker.template.Template; + +public interface TemplateClassResolver +{ + Class resolve(String p0, Environment p1, Template p2); + static TemplateClassResolver ALLOWS_NOTHING_RESOLVER = null; + static TemplateClassResolver SAFER_RESOLVER = null; + static TemplateClassResolver UNRESTRICTED_RESOLVER = null; +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateConfiguration.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateConfiguration.java new file mode 100644 index 00000000000..7715cfb1636 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateConfiguration.java @@ -0,0 +1,51 @@ +// Generated automatically from freemarker.core.TemplateConfiguration for testing purposes + +package freemarker.core; + +import freemarker.core.Configurable; +import freemarker.core.OutputFormat; +import freemarker.core.ParserConfiguration; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.Version; + +public class TemplateConfiguration extends Configurable implements ParserConfiguration +{ + public Configuration getParentConfiguration(){ return null; } + public OutputFormat getOutputFormat(){ return null; } + public String getEncoding(){ return null; } + public TemplateConfiguration(){} + public Version getIncompatibleImprovements(){ return null; } + public boolean getRecognizeStandardFileExtensions(){ return false; } + public boolean getStrictSyntaxMode(){ return false; } + public boolean getWhitespaceStripping(){ return false; } + public boolean isAutoEscapingPolicySet(){ return false; } + public boolean isEncodingSet(){ return false; } + public boolean isInterpolationSyntaxSet(){ return false; } + public boolean isNamingConventionSet(){ return false; } + public boolean isOutputFormatSet(){ return false; } + public boolean isRecognizeStandardFileExtensionsSet(){ return false; } + public boolean isStrictSyntaxModeSet(){ return false; } + public boolean isTabSizeSet(){ return false; } + public boolean isTagSyntaxSet(){ return false; } + public boolean isWhitespaceStrippingSet(){ return false; } + public int getAutoEscapingPolicy(){ return 0; } + public int getInterpolationSyntax(){ return 0; } + public int getNamingConvention(){ return 0; } + public int getTabSize(){ return 0; } + public int getTagSyntax(){ return 0; } + public void apply(Template p0){} + public void merge(TemplateConfiguration p0){} + public void setAutoEscapingPolicy(int p0){} + public void setEncoding(String p0){} + public void setInterpolationSyntax(int p0){} + public void setNamingConvention(int p0){} + public void setOutputFormat(OutputFormat p0){} + public void setParentConfiguration(Configuration p0){} + public void setRecognizeStandardFileExtensions(boolean p0){} + public void setStrictBeanModels(boolean p0){} + public void setStrictSyntaxMode(boolean p0){} + public void setTabSize(int p0){} + public void setTagSyntax(int p0){} + public void setWhitespaceStripping(boolean p0){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateDateFormat.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateDateFormat.java new file mode 100644 index 00000000000..6598080616f --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateDateFormat.java @@ -0,0 +1,16 @@ +// Generated automatically from freemarker.core.TemplateDateFormat for testing purposes + +package freemarker.core; + +import freemarker.core.TemplateValueFormat; +import freemarker.template.TemplateDateModel; + +abstract public class TemplateDateFormat extends TemplateValueFormat +{ + public Object format(TemplateDateModel p0){ return null; } + public TemplateDateFormat(){} + public abstract Object parse(String p0, int p1); + public abstract String formatToPlainText(TemplateDateModel p0); + public abstract boolean isLocaleBound(); + public abstract boolean isTimeZoneBound(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateDateFormatFactory.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateDateFormatFactory.java new file mode 100644 index 00000000000..f251e28d0b6 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateDateFormatFactory.java @@ -0,0 +1,15 @@ +// Generated automatically from freemarker.core.TemplateDateFormatFactory for testing purposes + +package freemarker.core; + +import freemarker.core.Environment; +import freemarker.core.TemplateDateFormat; +import freemarker.core.TemplateValueFormatFactory; +import java.util.Locale; +import java.util.TimeZone; + +abstract public class TemplateDateFormatFactory extends TemplateValueFormatFactory +{ + public TemplateDateFormatFactory(){} + public abstract TemplateDateFormat get(String p0, int p1, Locale p2, TimeZone p3, boolean p4, Environment p5); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateElement.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateElement.java new file mode 100644 index 00000000000..ff025939234 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateElement.java @@ -0,0 +1,30 @@ +// Generated automatically from freemarker.core.TemplateElement for testing purposes + +package freemarker.core; + +import freemarker.core.TemplateObject; +import freemarker.template.TemplateNodeModel; +import freemarker.template.TemplateSequenceModel; +import java.util.Enumeration; +import javax.swing.tree.TreeNode; + +abstract public class TemplateElement extends TemplateObject implements TreeNode +{ + protected abstract String dump(boolean p0); + public Enumeration children(){ return null; } + public String getNodeName(){ return null; } + public String getNodeNamespace(){ return null; } + public String getNodeType(){ return null; } + public TemplateElement(){} + public TemplateNodeModel getParentNode(){ return null; } + public TemplateSequenceModel getChildNodes(){ return null; } + public TreeNode getChildAt(int p0){ return null; } + public TreeNode getParent(){ return null; } + public boolean getAllowsChildren(){ return false; } + public boolean isLeaf(){ return false; } + public final String getCanonicalForm(){ return null; } + public final String getDescription(){ return null; } + public int getChildCount(){ return 0; } + public int getIndex(TreeNode p0){ return 0; } + public void setChildAt(int p0, TemplateElement p1){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateNumberFormat.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateNumberFormat.java new file mode 100644 index 00000000000..3ed83f5fcd3 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateNumberFormat.java @@ -0,0 +1,15 @@ +// Generated automatically from freemarker.core.TemplateNumberFormat for testing purposes + +package freemarker.core; + +import freemarker.core.TemplateValueFormat; +import freemarker.template.TemplateNumberModel; + +abstract public class TemplateNumberFormat extends TemplateValueFormat +{ + public Object format(TemplateNumberModel p0){ return null; } + public TemplateNumberFormat(){} + public abstract String formatToPlainText(TemplateNumberModel p0); + public abstract boolean isLocaleBound(); + public final Object parse(String p0){ return null; } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateNumberFormatFactory.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateNumberFormatFactory.java new file mode 100644 index 00000000000..6ccd1ebd428 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateNumberFormatFactory.java @@ -0,0 +1,14 @@ +// Generated automatically from freemarker.core.TemplateNumberFormatFactory for testing purposes + +package freemarker.core; + +import freemarker.core.Environment; +import freemarker.core.TemplateNumberFormat; +import freemarker.core.TemplateValueFormatFactory; +import java.util.Locale; + +abstract public class TemplateNumberFormatFactory extends TemplateValueFormatFactory +{ + public TemplateNumberFormatFactory(){} + public abstract TemplateNumberFormat get(String p0, Locale p1, Environment p2); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateObject.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateObject.java new file mode 100644 index 00000000000..66a30450d02 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateObject.java @@ -0,0 +1,23 @@ +// Generated automatically from freemarker.core.TemplateObject for testing purposes + +package freemarker.core; + +import freemarker.template.Template; + +abstract public class TemplateObject +{ + public String getEndLocation(){ return null; } + public String getEndLocationQuoted(){ return null; } + public String getStartLocation(){ return null; } + public String getStartLocationQuoted(){ return null; } + public String toString(){ return null; } + public Template getTemplate(){ return null; } + public TemplateObject(){} + public abstract String getCanonicalForm(); + public boolean contains(int p0, int p1){ return false; } + public final String getSource(){ return null; } + public final int getBeginColumn(){ return 0; } + public final int getBeginLine(){ return 0; } + public final int getEndColumn(){ return 0; } + public final int getEndLine(){ return 0; } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateValueFormat.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateValueFormat.java new file mode 100644 index 00000000000..84f787a7468 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateValueFormat.java @@ -0,0 +1,10 @@ +// Generated automatically from freemarker.core.TemplateValueFormat for testing purposes + +package freemarker.core; + + +abstract public class TemplateValueFormat +{ + public TemplateValueFormat(){} + public abstract String getDescription(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateValueFormatFactory.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateValueFormatFactory.java new file mode 100644 index 00000000000..f43a63c9a11 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TemplateValueFormatFactory.java @@ -0,0 +1,9 @@ +// Generated automatically from freemarker.core.TemplateValueFormatFactory for testing purposes + +package freemarker.core; + + +abstract public class TemplateValueFormatFactory +{ + public TemplateValueFormatFactory(){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TruncateBuiltinAlgorithm.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TruncateBuiltinAlgorithm.java new file mode 100644 index 00000000000..36a20f26806 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/TruncateBuiltinAlgorithm.java @@ -0,0 +1,18 @@ +// Generated automatically from freemarker.core.TruncateBuiltinAlgorithm for testing purposes + +package freemarker.core; + +import freemarker.core.Environment; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateScalarModel; + +abstract public class TruncateBuiltinAlgorithm +{ + public TruncateBuiltinAlgorithm(){} + public abstract TemplateModel truncateCM(String p0, int p1, TemplateModel p2, Integer p3, Environment p4); + public abstract TemplateModel truncateM(String p0, int p1, TemplateModel p2, Integer p3, Environment p4); + public abstract TemplateModel truncateWM(String p0, int p1, TemplateModel p2, Integer p3, Environment p4); + public abstract TemplateScalarModel truncate(String p0, int p1, TemplateScalarModel p2, Integer p3, Environment p4); + public abstract TemplateScalarModel truncateC(String p0, int p1, TemplateScalarModel p2, Integer p3, Environment p4); + public abstract TemplateScalarModel truncateW(String p0, int p1, TemplateScalarModel p2, Integer p3, Environment p4); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/_ErrorDescriptionBuilder.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/_ErrorDescriptionBuilder.java new file mode 100644 index 00000000000..ab90808ab3e --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/core/_ErrorDescriptionBuilder.java @@ -0,0 +1,24 @@ +// Generated automatically from freemarker.core._ErrorDescriptionBuilder for testing purposes + +package freemarker.core; + +import freemarker.core.Expression; +import freemarker.core.TemplateElement; +import freemarker.template.Template; + +public class _ErrorDescriptionBuilder +{ + protected _ErrorDescriptionBuilder() {} + public String toString(){ return null; } + public String toString(TemplateElement p0, boolean p1){ return null; } + public _ErrorDescriptionBuilder blame(Expression p0){ return null; } + public _ErrorDescriptionBuilder showBlamer(boolean p0){ return null; } + public _ErrorDescriptionBuilder template(Template p0){ return null; } + public _ErrorDescriptionBuilder tip(Object... p0){ return null; } + public _ErrorDescriptionBuilder tip(String p0){ return null; } + public _ErrorDescriptionBuilder tips(Object... p0){ return null; } + public _ErrorDescriptionBuilder(Object... p0){} + public _ErrorDescriptionBuilder(String p0){} + public static String toString(Object p0){ return null; } + public static String tryToString(Object p0){ return null; } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/AttemptExceptionReporter.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/AttemptExceptionReporter.java new file mode 100644 index 00000000000..a870a2d0d82 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/AttemptExceptionReporter.java @@ -0,0 +1,13 @@ +// Generated automatically from freemarker.template.AttemptExceptionReporter for testing purposes + +package freemarker.template; + +import freemarker.core.Environment; +import freemarker.template.TemplateException; + +public interface AttemptExceptionReporter +{ + static AttemptExceptionReporter LOG_ERROR_REPORTER = null; + static AttemptExceptionReporter LOG_WARN_REPORTER = null; + void report(TemplateException p0, Environment p1); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/Configuration.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/Configuration.java new file mode 100644 index 00000000000..4c8c4cd5a84 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/Configuration.java @@ -0,0 +1,253 @@ +// Generated automatically from freemarker.template.Configuration for testing purposes + +package freemarker.template; + +import freemarker.cache.CacheStorage; +import freemarker.cache.TemplateConfigurationFactory; +import freemarker.cache.TemplateLoader; +import freemarker.cache.TemplateLookupStrategy; +import freemarker.cache.TemplateNameFormat; +import freemarker.core.Configurable; +import freemarker.core.Environment; +import freemarker.core.OutputFormat; +import freemarker.core.ParserConfiguration; +import freemarker.template.AttemptExceptionReporter; +import freemarker.template.ObjectWrapper; +import freemarker.template.Template; +import freemarker.template.TemplateExceptionHandler; +import freemarker.template.TemplateHashModelEx; +import freemarker.template.TemplateModel; +import freemarker.template.Version; +import java.io.File; +import java.util.Collection; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; + +public class Configuration extends Configurable implements Cloneable, ParserConfiguration +{ + protected String getCorrectedNameForUnknownSetting(String p0){ return null; } + protected void doAutoImportsAndIncludes(Environment p0){} + public CacheStorage getCacheStorage(){ return null; } + public Collection getRegisteredCustomOutputFormats(){ return null; } + public Configuration(){} + public Configuration(Version p0){} + public Object clone(){ return null; } + public OutputFormat getOutputFormat(){ return null; } + public OutputFormat getOutputFormat(String p0){ return null; } + public Set getSharedVariableNames(){ return null; } + public Set getSupportedBuiltInDirectiveNames(){ return null; } + public Set getSupportedBuiltInNames(){ return null; } + public Set getSettingNames(boolean p0){ return null; } + public Set getSupportedBuiltInDirectiveNames(int p0){ return null; } + public Set getSupportedBuiltInNames(int p0){ return null; } + public String getDefaultEncoding(){ return null; } + public String getEncoding(Locale p0){ return null; } + public String getIncompatibleEnhancements(){ return null; } + public Template getTemplate(String p0){ return null; } + public Template getTemplate(String p0, Locale p1){ return null; } + public Template getTemplate(String p0, Locale p1, Object p2, String p3, boolean p4, boolean p5){ return null; } + public Template getTemplate(String p0, Locale p1, String p2){ return null; } + public Template getTemplate(String p0, Locale p1, String p2, boolean p3){ return null; } + public Template getTemplate(String p0, Locale p1, String p2, boolean p3, boolean p4){ return null; } + public Template getTemplate(String p0, String p1){ return null; } + public TemplateConfigurationFactory getTemplateConfigurations(){ return null; } + public TemplateLoader getTemplateLoader(){ return null; } + public TemplateLookupStrategy getTemplateLookupStrategy(){ return null; } + public TemplateModel getSharedVariable(String p0){ return null; } + public TemplateNameFormat getTemplateNameFormat(){ return null; } + public Version getIncompatibleImprovements(){ return null; } + public boolean getFallbackOnNullLoopVariable(){ return false; } + public boolean getLocalizedLookup(){ return false; } + public boolean getRecognizeStandardFileExtensions(){ return false; } + public boolean getStrictSyntaxMode(){ return false; } + public boolean getWhitespaceStripping(){ return false; } + public boolean isAttemptExceptionReporterExplicitlySet(){ return false; } + public boolean isCacheStorageExplicitlySet(){ return false; } + public boolean isDefaultEncodingExplicitlySet(){ return false; } + public boolean isLocaleExplicitlySet(){ return false; } + public boolean isLogTemplateExceptionsExplicitlySet(){ return false; } + public boolean isObjectWrapperExplicitlySet(){ return false; } + public boolean isOutputFormatExplicitlySet(){ return false; } + public boolean isRecognizeStandardFileExtensionsExplicitlySet(){ return false; } + public boolean isTemplateExceptionHandlerExplicitlySet(){ return false; } + public boolean isTemplateLoaderExplicitlySet(){ return false; } + public boolean isTemplateLookupStrategyExplicitlySet(){ return false; } + public boolean isTemplateNameFormatExplicitlySet(){ return false; } + public boolean isTimeZoneExplicitlySet(){ return false; } + public boolean isWrapUncheckedExceptionsExplicitlySet(){ return false; } + public int getAutoEscapingPolicy(){ return 0; } + public int getInterpolationSyntax(){ return 0; } + public int getNamingConvention(){ return 0; } + public int getParsedIncompatibleEnhancements(){ return 0; } + public int getTabSize(){ return 0; } + public int getTagSyntax(){ return 0; } + public long getTemplateUpdateDelayMilliseconds(){ return 0; } + public static Configuration getDefaultConfiguration(){ return null; } + public static ObjectWrapper getDefaultObjectWrapper(Version p0){ return null; } + public static String AUTO_ESCAPING_POLICY_KEY = null; + public static String AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE = null; + public static String AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE = null; + public static String AUTO_IMPORT_KEY = null; + public static String AUTO_IMPORT_KEY_CAMEL_CASE = null; + public static String AUTO_IMPORT_KEY_SNAKE_CASE = null; + public static String AUTO_INCLUDE_KEY = null; + public static String AUTO_INCLUDE_KEY_CAMEL_CASE = null; + public static String AUTO_INCLUDE_KEY_SNAKE_CASE = null; + public static String CACHE_STORAGE_KEY = null; + public static String CACHE_STORAGE_KEY_CAMEL_CASE = null; + public static String CACHE_STORAGE_KEY_SNAKE_CASE = null; + public static String DEFAULT_ENCODING_KEY = null; + public static String DEFAULT_ENCODING_KEY_CAMEL_CASE = null; + public static String DEFAULT_ENCODING_KEY_SNAKE_CASE = null; + public static String DEFAULT_INCOMPATIBLE_ENHANCEMENTS = null; + public static String FALLBACK_ON_NULL_LOOP_VARIABLE_KEY = null; + public static String FALLBACK_ON_NULL_LOOP_VARIABLE_KEY_CAMEL_CASE = null; + public static String FALLBACK_ON_NULL_LOOP_VARIABLE_KEY_SNAKE_CASE = null; + public static String INCOMPATIBLE_ENHANCEMENTS = null; + public static String INCOMPATIBLE_IMPROVEMENTS = null; + public static String INCOMPATIBLE_IMPROVEMENTS_KEY = null; + public static String INCOMPATIBLE_IMPROVEMENTS_KEY_CAMEL_CASE = null; + public static String INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE = null; + public static String INTERPOLATION_SYNTAX_KEY = null; + public static String INTERPOLATION_SYNTAX_KEY_CAMEL_CASE = null; + public static String INTERPOLATION_SYNTAX_KEY_SNAKE_CASE = null; + public static String LOCALIZED_LOOKUP_KEY = null; + public static String LOCALIZED_LOOKUP_KEY_CAMEL_CASE = null; + public static String LOCALIZED_LOOKUP_KEY_SNAKE_CASE = null; + public static String NAMING_CONVENTION_KEY = null; + public static String NAMING_CONVENTION_KEY_CAMEL_CASE = null; + public static String NAMING_CONVENTION_KEY_SNAKE_CASE = null; + public static String OUTPUT_FORMAT_KEY = null; + public static String OUTPUT_FORMAT_KEY_CAMEL_CASE = null; + public static String OUTPUT_FORMAT_KEY_SNAKE_CASE = null; + public static String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY = null; + public static String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE = null; + public static String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE = null; + public static String REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY = null; + public static String REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_CAMEL_CASE = null; + public static String REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE = null; + public static String STRICT_SYNTAX_KEY = null; + public static String STRICT_SYNTAX_KEY_CAMEL_CASE = null; + public static String STRICT_SYNTAX_KEY_SNAKE_CASE = null; + public static String TAB_SIZE_KEY = null; + public static String TAB_SIZE_KEY_CAMEL_CASE = null; + public static String TAB_SIZE_KEY_SNAKE_CASE = null; + public static String TAG_SYNTAX_KEY = null; + public static String TAG_SYNTAX_KEY_CAMEL_CASE = null; + public static String TAG_SYNTAX_KEY_SNAKE_CASE = null; + public static String TEMPLATE_CONFIGURATIONS_KEY = null; + public static String TEMPLATE_CONFIGURATIONS_KEY_CAMEL_CASE = null; + public static String TEMPLATE_CONFIGURATIONS_KEY_SNAKE_CASE = null; + public static String TEMPLATE_LOADER_KEY = null; + public static String TEMPLATE_LOADER_KEY_CAMEL_CASE = null; + public static String TEMPLATE_LOADER_KEY_SNAKE_CASE = null; + public static String TEMPLATE_LOOKUP_STRATEGY_KEY = null; + public static String TEMPLATE_LOOKUP_STRATEGY_KEY_CAMEL_CASE = null; + public static String TEMPLATE_LOOKUP_STRATEGY_KEY_SNAKE_CASE = null; + public static String TEMPLATE_NAME_FORMAT_KEY = null; + public static String TEMPLATE_NAME_FORMAT_KEY_CAMEL_CASE = null; + public static String TEMPLATE_NAME_FORMAT_KEY_SNAKE_CASE = null; + public static String TEMPLATE_UPDATE_DELAY_KEY = null; + public static String TEMPLATE_UPDATE_DELAY_KEY_CAMEL_CASE = null; + public static String TEMPLATE_UPDATE_DELAY_KEY_SNAKE_CASE = null; + public static String WHITESPACE_STRIPPING_KEY = null; + public static String WHITESPACE_STRIPPING_KEY_CAMEL_CASE = null; + public static String WHITESPACE_STRIPPING_KEY_SNAKE_CASE = null; + public static String getVersionNumber(){ return null; } + public static Version DEFAULT_INCOMPATIBLE_IMPROVEMENTS = null; + public static Version VERSION_2_3_0 = null; + public static Version VERSION_2_3_19 = null; + public static Version VERSION_2_3_20 = null; + public static Version VERSION_2_3_21 = null; + public static Version VERSION_2_3_22 = null; + public static Version VERSION_2_3_23 = null; + public static Version VERSION_2_3_24 = null; + public static Version VERSION_2_3_25 = null; + public static Version VERSION_2_3_26 = null; + public static Version VERSION_2_3_27 = null; + public static Version VERSION_2_3_28 = null; + public static Version VERSION_2_3_29 = null; + public static Version VERSION_2_3_30 = null; + public static Version VERSION_2_3_31 = null; + public static Version getVersion(){ return null; } + public static int ANGLE_BRACKET_TAG_SYNTAX = 0; + public static int AUTO_DETECT_NAMING_CONVENTION = 0; + public static int AUTO_DETECT_TAG_SYNTAX = 0; + public static int CAMEL_CASE_NAMING_CONVENTION = 0; + public static int DISABLE_AUTO_ESCAPING_POLICY = 0; + public static int DOLLAR_INTERPOLATION_SYNTAX = 0; + public static int ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY = 0; + public static int ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY = 0; + public static int LEGACY_INTERPOLATION_SYNTAX = 0; + public static int LEGACY_NAMING_CONVENTION = 0; + public static int PARSED_DEFAULT_INCOMPATIBLE_ENHANCEMENTS = 0; + public static int SQUARE_BRACKET_INTERPOLATION_SYNTAX = 0; + public static int SQUARE_BRACKET_TAG_SYNTAX = 0; + public static void setDefaultConfiguration(Configuration p0){} + public void clearEncodingMap(){} + public void clearSharedVariables(){} + public void clearTemplateCache(){} + public void loadBuiltInEncodingMap(){} + public void removeTemplateFromCache(String p0){} + public void removeTemplateFromCache(String p0, Locale p1){} + public void removeTemplateFromCache(String p0, Locale p1, Object p2, String p3, boolean p4){} + public void removeTemplateFromCache(String p0, Locale p1, String p2){} + public void removeTemplateFromCache(String p0, Locale p1, String p2, boolean p3){} + public void removeTemplateFromCache(String p0, String p1){} + public void setAllSharedVariables(TemplateHashModelEx p0){} + public void setAttemptExceptionReporter(AttemptExceptionReporter p0){} + public void setAutoEscapingPolicy(int p0){} + public void setCacheStorage(CacheStorage p0){} + public void setClassForTemplateLoading(Class p0, String p1){} + public void setClassLoaderForTemplateLoading(ClassLoader p0, String p1){} + public void setDefaultEncoding(String p0){} + public void setDirectoryForTemplateLoading(File p0){} + public void setEncoding(Locale p0, String p1){} + public void setFallbackOnNullLoopVariable(boolean p0){} + public void setIncompatibleEnhancements(String p0){} + public void setIncompatibleImprovements(Version p0){} + public void setInterpolationSyntax(int p0){} + public void setLocale(Locale p0){} + public void setLocalizedLookup(boolean p0){} + public void setLogTemplateExceptions(boolean p0){} + public void setNamingConvention(int p0){} + public void setObjectWrapper(ObjectWrapper p0){} + public void setOutputFormat(OutputFormat p0){} + public void setRecognizeStandardFileExtensions(boolean p0){} + public void setRegisteredCustomOutputFormats(Collection p0){} + public void setServletContextForTemplateLoading(Object p0, String p1){} + public void setSetting(String p0, String p1){} + public void setSharedVariable(String p0, Object p1){} + public void setSharedVariable(String p0, TemplateModel p1){} + public void setSharedVariables(Map p0){} + public void setSharedVaribles(Map p0){} + public void setStrictSyntaxMode(boolean p0){} + public void setTabSize(int p0){} + public void setTagSyntax(int p0){} + public void setTemplateConfigurations(TemplateConfigurationFactory p0){} + public void setTemplateExceptionHandler(TemplateExceptionHandler p0){} + public void setTemplateLoader(TemplateLoader p0){} + public void setTemplateLookupStrategy(TemplateLookupStrategy p0){} + public void setTemplateNameFormat(TemplateNameFormat p0){} + public void setTemplateUpdateDelay(int p0){} + public void setTemplateUpdateDelayMilliseconds(long p0){} + public void setTimeZone(TimeZone p0){} + public void setWhitespaceStripping(boolean p0){} + public void setWrapUncheckedExceptions(boolean p0){} + public void unsetAttemptExceptionReporter(){} + public void unsetCacheStorage(){} + public void unsetDefaultEncoding(){} + public void unsetLocale(){} + public void unsetLogTemplateExceptions(){} + public void unsetObjectWrapper(){} + public void unsetOutputFormat(){} + public void unsetRecognizeStandardFileExtensions(){} + public void unsetTemplateExceptionHandler(){} + public void unsetTemplateLoader(){} + public void unsetTemplateLookupStrategy(){} + public void unsetTemplateNameFormat(){} + public void unsetTimeZone(){} + public void unsetWrapUncheckedExceptions(){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/ObjectWrapper.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/ObjectWrapper.java new file mode 100644 index 00000000000..c34a96ece19 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/ObjectWrapper.java @@ -0,0 +1,13 @@ +// Generated automatically from freemarker.template.ObjectWrapper for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateModel; + +public interface ObjectWrapper +{ + TemplateModel wrap(Object p0); + static ObjectWrapper BEANS_WRAPPER = null; + static ObjectWrapper DEFAULT_WRAPPER = null; + static ObjectWrapper SIMPLE_WRAPPER = null; +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/SimpleHash.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/SimpleHash.java new file mode 100644 index 00000000000..3e7095ab34a --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/SimpleHash.java @@ -0,0 +1,35 @@ +// Generated automatically from freemarker.template.SimpleHash for testing purposes + +package freemarker.template; + +import freemarker.template.ObjectWrapper; +import freemarker.template.TemplateCollectionModel; +import freemarker.template.TemplateHashModelEx2; +import freemarker.template.TemplateModel; +import freemarker.template.WrappingTemplateModel; +import java.io.Serializable; +import java.util.Map; + +public class SimpleHash extends WrappingTemplateModel implements Serializable, TemplateHashModelEx2 +{ + protected Map copyMap(Map p0){ return null; } + public Map toMap(){ return null; } + public SimpleHash synchronizedWrapper(){ return null; } + public SimpleHash(){} + public SimpleHash(Map p0){} + public SimpleHash(Map p0, ObjectWrapper p1){} + public SimpleHash(Map p0, ObjectWrapper p1, int p2){} + public SimpleHash(ObjectWrapper p0){} + public String toString(){ return null; } + public TemplateCollectionModel keys(){ return null; } + public TemplateCollectionModel values(){ return null; } + public TemplateHashModelEx2.KeyValuePairIterator keyValuePairIterator(){ return null; } + public TemplateModel get(String p0){ return null; } + public boolean containsKey(String p0){ return false; } + public boolean isEmpty(){ return false; } + public int size(){ return 0; } + public void put(String p0, Object p1){} + public void put(String p0, boolean p1){} + public void putAll(Map p0){} + public void remove(String p0){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/Template.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/Template.java new file mode 100644 index 00000000000..0a80e52cb1d --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/Template.java @@ -0,0 +1,69 @@ +// Generated automatically from freemarker.template.Template for testing purposes + +package freemarker.template; + +import freemarker.core.Configurable; +import freemarker.core.Environment; +import freemarker.core.LibraryLoad; +import freemarker.core.Macro; +import freemarker.core.OutputFormat; +import freemarker.core.ParserConfiguration; +import freemarker.core.TemplateElement; +import freemarker.template.Configuration; +import freemarker.template.ObjectWrapper; +import freemarker.template.TemplateNodeModel; +import java.io.PrintStream; +import java.io.Reader; +import java.io.Writer; +import java.util.List; +import java.util.Map; +import javax.swing.tree.TreePath; + +public class Template extends Configurable +{ + protected Template() {} + public Configuration getConfiguration(){ return null; } + public Environment createProcessingEnvironment(Object p0, Writer p1){ return null; } + public Environment createProcessingEnvironment(Object p0, Writer p1, ObjectWrapper p2){ return null; } + public List getImports(){ return null; } + public Map getMacros(){ return null; } + public Object getCustomLookupCondition(){ return null; } + public OutputFormat getOutputFormat(){ return null; } + public ParserConfiguration getParserConfiguration(){ return null; } + public String getDefaultNS(){ return null; } + public String getEncoding(){ return null; } + public String getName(){ return null; } + public String getNamespaceForPrefix(String p0){ return null; } + public String getPrefixForNamespace(String p0){ return null; } + public String getPrefixedName(String p0, String p1){ return null; } + public String getSource(int p0, int p1, int p2, int p3){ return null; } + public String getSourceName(){ return null; } + public String toString(){ return null; } + public Template(String p0, Reader p1){} + public Template(String p0, Reader p1, Configuration p2){} + public Template(String p0, Reader p1, Configuration p2, String p3){} + public Template(String p0, String p1, Configuration p2){} + public Template(String p0, String p1, Reader p2, Configuration p3){} + public Template(String p0, String p1, Reader p2, Configuration p3, ParserConfiguration p4, String p5){} + public Template(String p0, String p1, Reader p2, Configuration p3, String p4){} + public TemplateElement getRootTreeNode(){ return null; } + public TreePath containingElements(int p0, int p1){ return null; } + public boolean getAutoEscaping(){ return false; } + public int getActualNamingConvention(){ return 0; } + public int getActualTagSyntax(){ return 0; } + public int getInterpolationSyntax(){ return 0; } + public static String DEFAULT_NAMESPACE_PREFIX = null; + public static String NO_NS_PREFIX = null; + public static Template getPlainTextTemplate(String p0, String p1, Configuration p2){ return null; } + public static Template getPlainTextTemplate(String p0, String p1, String p2, Configuration p3){ return null; } + public void addImport(LibraryLoad p0){} + public void addMacro(Macro p0){} + public void addPrefixNSMapping(String p0, String p1){} + public void dump(PrintStream p0){} + public void dump(Writer p0){} + public void process(Object p0, Writer p1){} + public void process(Object p0, Writer p1, ObjectWrapper p2){} + public void process(Object p0, Writer p1, ObjectWrapper p2, TemplateNodeModel p3){} + public void setCustomLookupCondition(Object p0){} + public void setEncoding(String p0){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateCollectionModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateCollectionModel.java new file mode 100644 index 00000000000..c56cd42301c --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateCollectionModel.java @@ -0,0 +1,11 @@ +// Generated automatically from freemarker.template.TemplateCollectionModel for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelIterator; + +public interface TemplateCollectionModel extends TemplateModel +{ + TemplateModelIterator iterator(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateDateModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateDateModel.java new file mode 100644 index 00000000000..59c32cc5e6d --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateDateModel.java @@ -0,0 +1,18 @@ +// Generated automatically from freemarker.template.TemplateDateModel for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateModel; +import java.util.Date; +import java.util.List; + +public interface TemplateDateModel extends TemplateModel +{ + Date getAsDate(); + int getDateType(); + static List TYPE_NAMES = null; + static int DATE = 0; + static int DATETIME = 0; + static int TIME = 0; + static int UNKNOWN = 0; +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateDirectiveBody.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateDirectiveBody.java new file mode 100644 index 00000000000..d3d74da7c66 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateDirectiveBody.java @@ -0,0 +1,10 @@ +// Generated automatically from freemarker.template.TemplateDirectiveBody for testing purposes + +package freemarker.template; + +import java.io.Writer; + +public interface TemplateDirectiveBody +{ + void render(Writer p0); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateDirectiveModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateDirectiveModel.java new file mode 100644 index 00000000000..15f800d52c7 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateDirectiveModel.java @@ -0,0 +1,13 @@ +// Generated automatically from freemarker.template.TemplateDirectiveModel for testing purposes + +package freemarker.template; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateModel; +import java.util.Map; + +public interface TemplateDirectiveModel extends TemplateModel +{ + void execute(Environment p0, Map p1, TemplateModel[] p2, TemplateDirectiveBody p3); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateException.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateException.java new file mode 100644 index 00000000000..930eb2167a8 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateException.java @@ -0,0 +1,39 @@ +// Generated automatically from freemarker.template.TemplateException for testing purposes + +package freemarker.template; + +import freemarker.core.Environment; +import freemarker.core.Expression; +import freemarker.core._ErrorDescriptionBuilder; +import java.io.PrintStream; +import java.io.PrintWriter; + +public class TemplateException extends Exception +{ + protected TemplateException() {} + protected TemplateException(Throwable p0, Environment p1, Expression p2, _ErrorDescriptionBuilder p3){} + public Environment getEnvironment(){ return null; } + public Exception getCauseException(){ return null; } + public Integer getColumnNumber(){ return null; } + public Integer getEndColumnNumber(){ return null; } + public Integer getEndLineNumber(){ return null; } + public Integer getLineNumber(){ return null; } + public String getBlamedExpressionString(){ return null; } + public String getFTLInstructionStack(){ return null; } + public String getMessage(){ return null; } + public String getMessageWithoutStackTop(){ return null; } + public String getTemplateName(){ return null; } + public String getTemplateSourceName(){ return null; } + public TemplateException(Environment p0){} + public TemplateException(Exception p0, Environment p1){} + public TemplateException(String p0, Environment p1){} + public TemplateException(String p0, Exception p1, Environment p2){} + public TemplateException(String p0, Throwable p1, Environment p2){} + public TemplateException(Throwable p0, Environment p1){} + public void printStackTrace(PrintStream p0){} + public void printStackTrace(PrintStream p0, boolean p1, boolean p2, boolean p3){} + public void printStackTrace(PrintWriter p0){} + public void printStackTrace(PrintWriter p0, boolean p1, boolean p2, boolean p3){} + public void printStandardStackTrace(PrintStream p0){} + public void printStandardStackTrace(PrintWriter p0){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateExceptionHandler.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateExceptionHandler.java new file mode 100644 index 00000000000..940f0be053d --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateExceptionHandler.java @@ -0,0 +1,16 @@ +// Generated automatically from freemarker.template.TemplateExceptionHandler for testing purposes + +package freemarker.template; + +import freemarker.core.Environment; +import freemarker.template.TemplateException; +import java.io.Writer; + +public interface TemplateExceptionHandler +{ + static TemplateExceptionHandler DEBUG_HANDLER = null; + static TemplateExceptionHandler HTML_DEBUG_HANDLER = null; + static TemplateExceptionHandler IGNORE_HANDLER = null; + static TemplateExceptionHandler RETHROW_HANDLER = null; + void handleTemplateException(TemplateException p0, Environment p1, Writer p2); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateHashModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateHashModel.java new file mode 100644 index 00000000000..9c05dc3e98e --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateHashModel.java @@ -0,0 +1,11 @@ +// Generated automatically from freemarker.template.TemplateHashModel for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateModel; + +public interface TemplateHashModel extends TemplateModel +{ + TemplateModel get(String p0); + boolean isEmpty(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateHashModelEx.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateHashModelEx.java new file mode 100644 index 00000000000..ad2d690fb20 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateHashModelEx.java @@ -0,0 +1,13 @@ +// Generated automatically from freemarker.template.TemplateHashModelEx for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateCollectionModel; +import freemarker.template.TemplateHashModel; + +public interface TemplateHashModelEx extends TemplateHashModel +{ + TemplateCollectionModel keys(); + TemplateCollectionModel values(); + int size(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateHashModelEx2.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateHashModelEx2.java new file mode 100644 index 00000000000..abcc7345891 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateHashModelEx2.java @@ -0,0 +1,21 @@ +// Generated automatically from freemarker.template.TemplateHashModelEx2 for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateHashModelEx; +import freemarker.template.TemplateModel; + +public interface TemplateHashModelEx2 extends TemplateHashModelEx +{ + TemplateHashModelEx2.KeyValuePairIterator keyValuePairIterator(); + static public interface KeyValuePair + { + TemplateModel getKey(); + TemplateModel getValue(); + } + static public interface KeyValuePairIterator + { + TemplateHashModelEx2.KeyValuePair next(); + boolean hasNext(); + } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateModel.java new file mode 100644 index 00000000000..e56340a1ea0 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateModel.java @@ -0,0 +1,9 @@ +// Generated automatically from freemarker.template.TemplateModel for testing purposes + +package freemarker.template; + + +public interface TemplateModel +{ + static TemplateModel NOTHING = null; +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateModelIterator.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateModelIterator.java new file mode 100644 index 00000000000..439160b654a --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateModelIterator.java @@ -0,0 +1,11 @@ +// Generated automatically from freemarker.template.TemplateModelIterator for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateModel; + +public interface TemplateModelIterator +{ + TemplateModel next(); + boolean hasNext(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNodeModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNodeModel.java new file mode 100644 index 00000000000..7fa5e8d47b1 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNodeModel.java @@ -0,0 +1,15 @@ +// Generated automatically from freemarker.template.TemplateNodeModel for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateModel; +import freemarker.template.TemplateSequenceModel; + +public interface TemplateNodeModel extends TemplateModel +{ + String getNodeName(); + String getNodeNamespace(); + String getNodeType(); + TemplateNodeModel getParentNode(); + TemplateSequenceModel getChildNodes(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNumberModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNumberModel.java new file mode 100644 index 00000000000..4dc02739565 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNumberModel.java @@ -0,0 +1,10 @@ +// Generated automatically from freemarker.template.TemplateNumberModel for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateModel; + +public interface TemplateNumberModel extends TemplateModel +{ + Number getAsNumber(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateScalarModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateScalarModel.java new file mode 100644 index 00000000000..e1bc2596503 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateScalarModel.java @@ -0,0 +1,11 @@ +// Generated automatically from freemarker.template.TemplateScalarModel for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateModel; + +public interface TemplateScalarModel extends TemplateModel +{ + String getAsString(); + static TemplateModel EMPTY_STRING = null; +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateSequenceModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateSequenceModel.java new file mode 100644 index 00000000000..1caa1b019a2 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateSequenceModel.java @@ -0,0 +1,11 @@ +// Generated automatically from freemarker.template.TemplateSequenceModel for testing purposes + +package freemarker.template; + +import freemarker.template.TemplateModel; + +public interface TemplateSequenceModel extends TemplateModel +{ + TemplateModel get(int p0); + int size(); +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/Version.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/Version.java new file mode 100644 index 00000000000..9ec313b634c --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/Version.java @@ -0,0 +1,27 @@ +// Generated automatically from freemarker.template.Version for testing purposes + +package freemarker.template; + +import java.io.Serializable; +import java.util.Date; + +public class Version implements Serializable +{ + protected Version() {} + public Boolean isGAECompliant(){ return null; } + public Date getBuildDate(){ return null; } + public String getExtraInfo(){ return null; } + public String toString(){ return null; } + public Version(String p0){} + public Version(String p0, Boolean p1, Date p2){} + public Version(int p0){} + public Version(int p0, int p1, int p2){} + public Version(int p0, int p1, int p2, String p3, Boolean p4, Date p5){} + public boolean equals(Object p0){ return false; } + public int getMajor(){ return 0; } + public int getMicro(){ return 0; } + public int getMinor(){ return 0; } + public int hashCode(){ return 0; } + public int intValue(){ return 0; } + public static int intValueFor(int p0, int p1, int p2){ return 0; } +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/WrappingTemplateModel.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/WrappingTemplateModel.java new file mode 100644 index 00000000000..a300f9aec05 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/WrappingTemplateModel.java @@ -0,0 +1,17 @@ +// Generated automatically from freemarker.template.WrappingTemplateModel for testing purposes + +package freemarker.template; + +import freemarker.template.ObjectWrapper; +import freemarker.template.TemplateModel; + +abstract public class WrappingTemplateModel +{ + protected WrappingTemplateModel(){} + protected WrappingTemplateModel(ObjectWrapper p0){} + protected final TemplateModel wrap(Object p0){ return null; } + public ObjectWrapper getObjectWrapper(){ return null; } + public static ObjectWrapper getDefaultObjectWrapper(){ return null; } + public static void setDefaultObjectWrapper(ObjectWrapper p0){} + public void setObjectWrapper(ObjectWrapper p0){} +} diff --git a/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/utility/ObjectFactory.java b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/utility/ObjectFactory.java new file mode 100644 index 00000000000..43fa80d72f1 --- /dev/null +++ b/java/ql/test/stubs/apache-freemarker-2.3.31/freemarker/template/utility/ObjectFactory.java @@ -0,0 +1,9 @@ +// Generated automatically from freemarker.template.utility.ObjectFactory for testing purposes + +package freemarker.template.utility; + + +public interface ObjectFactory +{ + T createObject(); +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/Template.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/Template.java new file mode 100644 index 00000000000..e9c1ee00f41 --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/Template.java @@ -0,0 +1,19 @@ +// Generated automatically from org.apache.velocity.Template for testing purposes + +package org.apache.velocity; + +import java.io.Writer; +import java.util.List; +import java.util.Map; +import org.apache.velocity.context.Context; +import org.apache.velocity.runtime.resource.Resource; + +public class Template extends Resource +{ + public Map getMacros(){ return null; } + public Template(){} + public boolean process(){ return false; } + public void initDocument(){} + public void merge(Context p0, Writer p1){} + public void merge(Context p0, Writer p1, List p2){} +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/VelocityContext.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/VelocityContext.java new file mode 100644 index 00000000000..05ab45a2f8d --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/VelocityContext.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.velocity.VelocityContext for testing purposes + +package org.apache.velocity; + +import java.io.Serializable; +import java.util.Map; +import org.apache.velocity.context.AbstractContext; +import org.apache.velocity.context.Context; + +public class VelocityContext extends AbstractContext implements Cloneable, Serializable +{ + public Object clone(){ return null; } + public Object internalGet(String p0){ return null; } + public Object internalPut(String p0, Object p1){ return null; } + public Object internalRemove(String p0){ return null; } + public String[] internalGetKeys(){ return null; } + public VelocityContext(){} + public VelocityContext(Context p0){} + public VelocityContext(Map p0){} + public VelocityContext(Map p0, Context p1){} + public boolean internalContainsKey(String p0){ return false; } +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/Velocity.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/Velocity.java new file mode 100644 index 00000000000..0e388794c61 --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/Velocity.java @@ -0,0 +1,36 @@ +// Generated automatically from org.apache.velocity.app.Velocity for testing purposes + +package org.apache.velocity.app; + +import java.io.Reader; +import java.io.Writer; +import java.util.Properties; +import org.apache.velocity.Template; +import org.apache.velocity.context.Context; +import org.apache.velocity.runtime.RuntimeConstants; +import org.slf4j.Logger; + +public class Velocity implements RuntimeConstants +{ + public Velocity(){} + public static Logger getLog(){ return null; } + public static Object getProperty(String p0){ return null; } + public static Template getTemplate(String p0){ return null; } + public static Template getTemplate(String p0, String p1){ return null; } + public static boolean evaluate(Context p0, Writer p1, String p2, Reader p3){ return false; } + public static boolean evaluate(Context p0, Writer p1, String p2, String p3){ return false; } + public static boolean invokeVelocimacro(String p0, String p1, String[] p2, Context p3, Writer p4){ return false; } + public static boolean mergeTemplate(String p0, String p1, Context p2, Writer p3){ return false; } + public static boolean resourceExists(String p0){ return false; } + public static void addProperty(String p0, Object p1){} + public static void clearProperty(String p0){} + public static void init(){} + public static void init(Properties p0){} + public static void init(String p0){} + public static void reset(){} + public static void setApplicationAttribute(Object p0, Object p1){} + public static void setProperties(Properties p0){} + public static void setProperty(String p0, Object p1){} + public void loadDirective(String p0){} + public void removeDirective(String p0){} +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/VelocityEngine.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/VelocityEngine.java new file mode 100644 index 00000000000..d692a1d7c34 --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/VelocityEngine.java @@ -0,0 +1,40 @@ +// Generated automatically from org.apache.velocity.app.VelocityEngine for testing purposes + +package org.apache.velocity.app; + +import java.io.Reader; +import java.io.Writer; +import java.util.Properties; +import org.apache.velocity.Template; +import org.apache.velocity.context.Context; +import org.apache.velocity.runtime.RuntimeConstants; +import org.slf4j.Logger; + +public class VelocityEngine implements RuntimeConstants +{ + public Logger getLog(){ return null; } + public Object getApplicationAttribute(Object p0){ return null; } + public Object getProperty(String p0){ return null; } + public Template getTemplate(String p0){ return null; } + public Template getTemplate(String p0, String p1){ return null; } + public VelocityEngine(){} + public VelocityEngine(Properties p0){} + public VelocityEngine(String p0){} + public boolean evaluate(Context p0, Writer p1, String p2, Reader p3){ return false; } + public boolean evaluate(Context p0, Writer p1, String p2, String p3){ return false; } + public boolean invokeVelocimacro(String p0, String p1, String[] p2, Context p3, Writer p4){ return false; } + public boolean mergeTemplate(String p0, String p1, Context p2, Writer p3){ return false; } + public boolean resourceExists(String p0){ return false; } + public void addProperty(String p0, Object p1){} + public void clearProperty(String p0){} + public void init(){} + public void init(Properties p0){} + public void init(String p0){} + public void loadDirective(String p0){} + public void removeDirective(String p0){} + public void reset(){} + public void setApplicationAttribute(Object p0, Object p1){} + public void setProperties(Properties p0){} + public void setProperties(String p0){} + public void setProperty(String p0, Object p1){} +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/EventCartridge.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/EventCartridge.java new file mode 100644 index 00000000000..9a3cc037501 --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/EventCartridge.java @@ -0,0 +1,35 @@ +// Generated automatically from org.apache.velocity.app.event.EventCartridge for testing purposes + +package org.apache.velocity.app.event; + +import org.apache.velocity.app.event.EventHandler; +import org.apache.velocity.app.event.IncludeEventHandler; +import org.apache.velocity.app.event.InvalidReferenceEventHandler; +import org.apache.velocity.app.event.MethodExceptionEventHandler; +import org.apache.velocity.app.event.ReferenceInsertionEventHandler; +import org.apache.velocity.context.Context; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.RuntimeServices; +import org.apache.velocity.util.introspection.Info; +import org.slf4j.Logger; + +public class EventCartridge +{ + protected Logger getLog(){ return null; } + protected RuntimeServices rsvc = null; + public EventCartridge(){} + public Object invalidGetMethod(Context p0, String p1, Object p2, String p3, Info p4){ return null; } + public Object invalidMethod(Context p0, String p1, Object p2, String p3, Info p4){ return null; } + public Object methodException(Context p0, Class p1, String p2, Exception p3, Info p4){ return null; } + public Object referenceInsert(InternalContextAdapter p0, String p1, Object p2){ return null; } + public String includeEvent(Context p0, String p1, String p2, String p3){ return null; } + public boolean addEventHandler(EventHandler p0){ return false; } + public boolean invalidSetMethod(Context p0, String p1, String p2, Info p3){ return false; } + public boolean removeEventHandler(EventHandler p0){ return false; } + public final boolean attachToContext(Context p0){ return false; } + public void addIncludeEventHandler(IncludeEventHandler p0){} + public void addInvalidReferenceEventHandler(InvalidReferenceEventHandler p0){} + public void addMethodExceptionHandler(MethodExceptionEventHandler p0){} + public void addReferenceInsertionEventHandler(ReferenceInsertionEventHandler p0){} + public void setRuntimeServices(RuntimeServices p0){} +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/EventHandler.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/EventHandler.java new file mode 100644 index 00000000000..d1cbae049ce --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/EventHandler.java @@ -0,0 +1,8 @@ +// Generated automatically from org.apache.velocity.app.event.EventHandler for testing purposes + +package org.apache.velocity.app.event; + + +public interface EventHandler +{ +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/IncludeEventHandler.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/IncludeEventHandler.java new file mode 100644 index 00000000000..2b7cf756d2f --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/IncludeEventHandler.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.velocity.app.event.IncludeEventHandler for testing purposes + +package org.apache.velocity.app.event; + +import org.apache.velocity.app.event.EventHandler; +import org.apache.velocity.context.Context; + +public interface IncludeEventHandler extends EventHandler +{ + String includeEvent(Context p0, String p1, String p2, String p3); +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/InvalidReferenceEventHandler.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/InvalidReferenceEventHandler.java new file mode 100644 index 00000000000..224785a2183 --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/InvalidReferenceEventHandler.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.velocity.app.event.InvalidReferenceEventHandler for testing purposes + +package org.apache.velocity.app.event; + +import org.apache.velocity.app.event.EventHandler; +import org.apache.velocity.context.Context; +import org.apache.velocity.util.introspection.Info; + +public interface InvalidReferenceEventHandler extends EventHandler +{ + Object invalidGetMethod(Context p0, String p1, Object p2, String p3, Info p4); + Object invalidMethod(Context p0, String p1, Object p2, String p3, Info p4); + boolean invalidSetMethod(Context p0, String p1, String p2, Info p3); +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/MethodExceptionEventHandler.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/MethodExceptionEventHandler.java new file mode 100644 index 00000000000..8d4d1b87a6b --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/MethodExceptionEventHandler.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.velocity.app.event.MethodExceptionEventHandler for testing purposes + +package org.apache.velocity.app.event; + +import org.apache.velocity.app.event.EventHandler; +import org.apache.velocity.context.Context; +import org.apache.velocity.util.introspection.Info; + +public interface MethodExceptionEventHandler extends EventHandler +{ + Object methodException(Context p0, Class p1, String p2, Exception p3, Info p4); +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/ReferenceInsertionEventHandler.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/ReferenceInsertionEventHandler.java new file mode 100644 index 00000000000..a9002cc5d1c --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/app/event/ReferenceInsertionEventHandler.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.velocity.app.event.ReferenceInsertionEventHandler for testing purposes + +package org.apache.velocity.app.event; + +import org.apache.velocity.app.event.EventHandler; +import org.apache.velocity.context.Context; + +public interface ReferenceInsertionEventHandler extends EventHandler +{ + Object referenceInsert(Context p0, String p1, Object p2); +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/AbstractContext.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/AbstractContext.java new file mode 100644 index 00000000000..9c02132c2a6 --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/AbstractContext.java @@ -0,0 +1,23 @@ +// Generated automatically from org.apache.velocity.context.AbstractContext for testing purposes + +package org.apache.velocity.context; + +import org.apache.velocity.context.Context; +import org.apache.velocity.context.InternalContextBase; + +abstract public class AbstractContext extends InternalContextBase implements Context +{ + public AbstractContext(){} + public AbstractContext(Context p0){} + public Context getChainedContext(){ return null; } + public Object get(String p0){ return null; } + public Object put(String p0, Object p1){ return null; } + public Object remove(String p0){ return null; } + public String[] getKeys(){ return null; } + public abstract Object internalGet(String p0); + public abstract Object internalPut(String p0, Object p1); + public abstract Object internalRemove(String p0); + public abstract String[] internalGetKeys(); + public abstract boolean internalContainsKey(String p0); + public boolean containsKey(String p0){ return false; } +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/Context.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/Context.java new file mode 100644 index 00000000000..f1bea35ff73 --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/Context.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.velocity.context.Context for testing purposes + +package org.apache.velocity.context; + + +public interface Context +{ + Object get(String p0); + Object put(String p0, Object p1); + Object remove(String p0); + String[] getKeys(); + boolean containsKey(String p0); +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/InternalContextAdapter.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/InternalContextAdapter.java new file mode 100644 index 00000000000..05503221609 --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/InternalContextAdapter.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.velocity.context.InternalContextAdapter for testing purposes + +package org.apache.velocity.context; + +import org.apache.velocity.context.Context; +import org.apache.velocity.context.InternalEventContext; +import org.apache.velocity.context.InternalHousekeepingContext; +import org.apache.velocity.context.InternalWrapperContext; + +public interface InternalContextAdapter extends Context, InternalEventContext, InternalHousekeepingContext, InternalWrapperContext +{ +} diff --git a/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/InternalContextBase.java b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/InternalContextBase.java new file mode 100644 index 00000000000..bb8631a18f5 --- /dev/null +++ b/java/ql/test/stubs/apache-velocity-2.3/org/apache/velocity/context/InternalContextBase.java @@ -0,0 +1,32 @@ +// Generated automatically from org.apache.velocity.context.InternalContextBase for testing purposes + +package org.apache.velocity.context; + +import java.util.List; +import org.apache.velocity.Template; +import org.apache.velocity.app.event.EventCartridge; +import org.apache.velocity.context.InternalEventContext; +import org.apache.velocity.context.InternalHousekeepingContext; +import org.apache.velocity.runtime.resource.Resource; +import org.apache.velocity.util.introspection.IntrospectionCacheData; + +class InternalContextBase implements InternalEventContext, InternalHousekeepingContext +{ + public EventCartridge attachEventCartridge(EventCartridge p0){ return null; } + public EventCartridge getEventCartridge(){ return null; } + public IntrospectionCacheData icacheGet(Object p0){ return null; } + public List