diff --git a/.github/workflows/ruby-qltest.yml b/.github/workflows/ruby-qltest.yml index 765ed8ce8c7..b13cfabcd7d 100644 --- a/.github/workflows/ruby-qltest.yml +++ b/.github/workflows/ruby-qltest.yml @@ -14,6 +14,7 @@ on: pull_request: paths: - "ruby/**" + - "shared/**" - .github/workflows/ruby-qltest.yml - .github/actions/fetch-codeql/action.yml - codeql-workspace.yml diff --git a/codeql-workspace.yml b/codeql-workspace.yml index c2258bd1363..2d86498cbea 100644 --- a/codeql-workspace.yml +++ b/codeql-workspace.yml @@ -4,6 +4,8 @@ provide: - "*/ql/test/qlpack.yml" - "*/ql/examples/qlpack.yml" - "*/ql/consistency-queries/qlpack.yml" + - "*/ql/automodel/src/qlpack.yml" + - "*/ql/automodel/test/qlpack.yml" - "shared/*/qlpack.yml" - "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml" - "go/ql/config/legacy-support/qlpack.yml" diff --git a/config/identical-files.json b/config/identical-files.json index 07db15e2d16..214fc402c4f 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -556,5 +556,9 @@ "EncryptionKeySizes Python/Java": [ "python/ql/lib/semmle/python/security/internal/EncryptionKeySizes.qll", "java/ql/lib/semmle/code/java/security/internal/EncryptionKeySizes.qll" + ], + "Python model summaries test extension": [ + "python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml", + "python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml" ] } diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj index 0c9f70c6d6d..abf4f358a24 100644 --- a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj +++ b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj @@ -11,12 +11,12 @@ - - + + all runtime; build; native; contentfiles; analyzers - + diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj b/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj index f8f5c285074..5e0d40cdfe2 100644 --- a/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj +++ b/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj @@ -17,7 +17,7 @@ - + diff --git a/cpp/ql/lib/change-notes/2023-08-25-delete-or-delete-array.md b/cpp/ql/lib/change-notes/2023-08-25-delete-or-delete-array.md new file mode 100644 index 00000000000..f3f3a59e8f0 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-08-25-delete-or-delete-array.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added `DeleteOrDeleteArrayExpr` as a super type of `DeleteExpr` and `DeleteArrayExpr` \ No newline at end of file diff --git a/cpp/ql/lib/change-notes/2023-08-25-getAllocatorCall-deprecated.md b/cpp/ql/lib/change-notes/2023-08-25-getAllocatorCall-deprecated.md new file mode 100644 index 00000000000..b9bb1fada5b --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-08-25-getAllocatorCall-deprecated.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* `getAllocatorCall` on `DeleteExpr` and `DeleteArrayExpr` has been deprecated. `getDeallocatorCall` should be used instead. \ No newline at end of file diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index d2f1c6695ea..1a8ab0be7bb 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 0.9.1 +version: 0.9.2-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/lib/semmle/code/cpp/PrintAST.qll b/cpp/ql/lib/semmle/code/cpp/PrintAST.qll index 46d9b34d890..19ed097cb39 100644 --- a/cpp/ql/lib/semmle/code/cpp/PrintAST.qll +++ b/cpp/ql/lib/semmle/code/cpp/PrintAST.qll @@ -826,17 +826,11 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred) or expr.(Conversion).getExpr() = ele and pred = "getExpr()" or - expr.(DeleteArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()" + expr.(DeleteOrDeleteArrayExpr).getDeallocatorCall() = ele and pred = "getDeallocatorCall()" or - expr.(DeleteArrayExpr).getDestructorCall() = ele and pred = "getDestructorCall()" + expr.(DeleteOrDeleteArrayExpr).getDestructorCall() = ele and pred = "getDestructorCall()" or - expr.(DeleteArrayExpr).getExpr() = ele and pred = "getExpr()" - or - expr.(DeleteExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()" - or - expr.(DeleteExpr).getDestructorCall() = ele and pred = "getDestructorCall()" - or - expr.(DeleteExpr).getExpr() = ele and pred = "getExpr()" + expr.(DeleteOrDeleteArrayExpr).getExpr() = ele and pred = "getExpr()" or expr.(DestructorFieldDestruction).getExpr() = ele and pred = "getExpr()" or diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/internal/CFG.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/internal/CFG.qll index 99aed9702a9..32d9cb9bce4 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/internal/CFG.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/internal/CFG.qll @@ -332,21 +332,12 @@ private Node getControlOrderChildSparse(Node n, int i) { n = any(ConditionDeclExpr cd | i = 0 and result = cd.getInitializingExpr()) or n = - any(DeleteExpr del | + any(DeleteOrDeleteArrayExpr del | i = 0 and result = del.getExpr() or i = 1 and result = del.getDestructorCall() or - i = 2 and result = del.getAllocatorCall() - ) - or - n = - any(DeleteArrayExpr del | - i = 0 and result = del.getExpr() - or - i = 1 and result = del.getDestructorCall() - or - i = 2 and result = del.getAllocatorCall() + i = 2 and result = del.getDeallocatorCall() ) or n = diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll index b2c749ceb4b..79b2cc6df8d 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll @@ -932,19 +932,91 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr { Expr getExtent() { result = this.getChild(2) } } +private class TDeleteOrDeleteArrayExpr = @delete_expr or @delete_array_expr; + +/** + * A C++ `delete` or `delete[]` expression. + */ +class DeleteOrDeleteArrayExpr extends Expr, TDeleteOrDeleteArrayExpr { + override int getPrecedence() { result = 16 } + + /** + * Gets the call to a destructor that occurs prior to the object's memory being deallocated, if any. + * + * In the case of `delete[]` at runtime, the destructor will be called once for each element in the array, but the + * destructor call only exists once in the AST. + */ + DestructorCall getDestructorCall() { result = this.getChild(1) } + + /** + * Gets the destructor to be called to destroy the object or array, if any. + */ + Destructor getDestructor() { result = this.getDestructorCall().getTarget() } + + /** + * Gets the `operator delete` or `operator delete[]` that deallocates storage. + * Does not hold if the type being destroyed has a virtual destructor. In that case, the + * `operator delete` that will be called is determined at runtime based on the + * dynamic type of the object. + */ + Function getDeallocator() { + expr_deallocator(underlyingElement(this), unresolveElement(result), _) + } + + /** + * DEPRECATED: use `getDeallocatorCall` instead. + */ + deprecated FunctionCall getAllocatorCall() { result = this.getChild(0) } + + /** + * Gets the call to a non-default `operator delete`/`delete[]` that deallocates storage, if any. + * + * This will only be present when the type being deleted has a custom `operator delete` and + * does not have a virtual destructor. + */ + FunctionCall getDeallocatorCall() { result = this.getChild(0) } + + /** + * Holds if the deallocation function expects a size argument. + */ + predicate hasSizedDeallocation() { + exists(int form | + expr_deallocator(underlyingElement(this), _, form) and + form.bitAnd(1) != 0 // Bit zero is the "size" bit + ) + } + + /** + * Holds if the deallocation function expects an alignment argument. + */ + predicate hasAlignedDeallocation() { + exists(int form | + expr_deallocator(underlyingElement(this), _, form) and + form.bitAnd(2) != 0 // Bit one is the "alignment" bit + ) + } + + /** + * Gets the object or array being deleted. + */ + Expr getExpr() { + // If there is a destructor call, the object being deleted is the qualifier + // otherwise it is the third child. + result = this.getChild(3) or result = this.getDestructorCall().getQualifier() + } +} + /** * A C++ `delete` (non-array) expression. * ``` * delete ptr; * ``` */ -class DeleteExpr extends Expr, @delete_expr { +class DeleteExpr extends DeleteOrDeleteArrayExpr, @delete_expr { override string toString() { result = "delete" } override string getAPrimaryQlClass() { result = "DeleteExpr" } - override int getPrecedence() { result = 16 } - /** * Gets the compile-time type of the object being deleted. */ @@ -957,58 +1029,6 @@ class DeleteExpr extends Expr, @delete_expr { .(PointerType) .getBaseType() } - - /** - * Gets the call to a destructor that occurs prior to the object's memory being deallocated, if any. - */ - DestructorCall getDestructorCall() { result = this.getChild(1) } - - /** - * Gets the destructor to be called to destroy the object, if any. - */ - Destructor getDestructor() { result = this.getDestructorCall().getTarget() } - - /** - * Gets the `operator delete` that deallocates storage. Does not hold - * if the type being destroyed has a virtual destructor. In that case, the - * `operator delete` that will be called is determined at runtime based on the - * dynamic type of the object. - */ - Function getDeallocator() { - expr_deallocator(underlyingElement(this), unresolveElement(result), _) - } - - /** - * Holds if the deallocation function expects a size argument. - */ - predicate hasSizedDeallocation() { - exists(int form | - expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(1) != 0 // Bit zero is the "size" bit - ) - } - - /** - * Holds if the deallocation function expects an alignment argument. - */ - predicate hasAlignedDeallocation() { - exists(int form | - expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(2) != 0 // Bit one is the "alignment" bit - ) - } - - /** - * Gets the call to a non-default `operator delete` that deallocates storage, if any. - * - * This will only be present when the type being deleted has a custom `operator delete`. - */ - FunctionCall getAllocatorCall() { result = this.getChild(0) } - - /** - * Gets the object being deleted. - */ - Expr getExpr() { result = this.getChild(3) or result = this.getChild(1).getChild(-1) } } /** @@ -1017,13 +1037,11 @@ class DeleteExpr extends Expr, @delete_expr { * delete[] arr; * ``` */ -class DeleteArrayExpr extends Expr, @delete_array_expr { +class DeleteArrayExpr extends DeleteOrDeleteArrayExpr, @delete_array_expr { override string toString() { result = "delete[]" } override string getAPrimaryQlClass() { result = "DeleteArrayExpr" } - override int getPrecedence() { result = 16 } - /** * Gets the element type of the array being deleted. */ @@ -1036,58 +1054,6 @@ class DeleteArrayExpr extends Expr, @delete_array_expr { .(PointerType) .getBaseType() } - - /** - * Gets the call to a destructor that occurs prior to the array's memory being deallocated, if any. - * - * At runtime, the destructor will be called once for each element in the array, but the - * destructor call only exists once in the AST. - */ - DestructorCall getDestructorCall() { result = this.getChild(1) } - - /** - * Gets the destructor to be called to destroy each element in the array, if any. - */ - Destructor getDestructor() { result = this.getDestructorCall().getTarget() } - - /** - * Gets the `operator delete[]` that deallocates storage. - */ - Function getDeallocator() { - expr_deallocator(underlyingElement(this), unresolveElement(result), _) - } - - /** - * Holds if the deallocation function expects a size argument. - */ - predicate hasSizedDeallocation() { - exists(int form | - expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(1) != 0 // Bit zero is the "size" bit - ) - } - - /** - * Holds if the deallocation function expects an alignment argument. - */ - predicate hasAlignedDeallocation() { - exists(int form | - expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(2) != 0 // Bit one is the "alignment" bit - ) - } - - /** - * Gets the call to a non-default `operator delete` that deallocates storage, if any. - * - * This will only be present when the type being deleted has a custom `operator delete`. - */ - FunctionCall getAllocatorCall() { result = this.getChild(0) } - - /** - * Gets the array being deleted. - */ - Expr getExpr() { result = this.getChild(3) or result = this.getChild(1).getChild(-1) } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 6470741d541..9355493303a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -550,11 +550,14 @@ class SsaPhiNode extends Node, TSsaPhiNode { * `fromBackEdge` is true if data flows along a back-edge, * and `false` otherwise. */ + cached final Node getAnInput(boolean fromBackEdge) { localFlowStep(result, this) and - if phi.getBasicBlock().dominates(result.getBasicBlock()) - then fromBackEdge = true - else fromBackEdge = false + exists(IRBlock bPhi, IRBlock bResult | + bPhi = phi.getBasicBlock() and bResult = result.getBasicBlock() + | + if bPhi.dominates(bResult) then fromBackEdge = true else fromBackEdge = false + ) } /** Gets a node that is used as input to this phi node. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ProductFlow.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ProductFlow.qll index c5d8eae5799..acd59147301 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ProductFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ProductFlow.qll @@ -87,6 +87,30 @@ module ProductFlow { * dataflow graph. */ default predicate isBarrierIn2(DataFlow::Node node) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow in the first + * projection of the product dataflow graph. + * + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit1() { + // NOTE: This should be synchronized with the default value in the shared dataflow library + result = 2 + } + + /** + * Gets the virtual dispatch branching limit when calculating field flow in the second + * projection of the product dataflow graph. + * + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit2() { + // NOTE: This should be synchronized with the default value in the shared dataflow library + result = 2 + } } /** @@ -272,6 +296,30 @@ module ProductFlow { * dataflow graph. */ default predicate isBarrierIn2(DataFlow::Node node) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow in the first + * projection of the product dataflow graph. + * + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit1() { + // NOTE: This should be synchronized with the default value in the shared dataflow library + result = 2 + } + + /** + * Gets the virtual dispatch branching limit when calculating field flow in the second + * projection of the product dataflow graph. + * + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit2() { + // NOTE: This should be synchronized with the default value in the shared dataflow library + result = 2 + } } /** @@ -335,6 +383,8 @@ module ProductFlow { } predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn1(node) } + + int fieldFlowBranchLimit() { result = Config::fieldFlowBranchLimit1() } } private module Flow1 = DataFlow::GlobalWithState; @@ -367,6 +417,8 @@ module ProductFlow { } predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn2(node) } + + int fieldFlowBranchLimit() { result = Config::fieldFlowBranchLimit2() } } private module Flow2 = DataFlow::GlobalWithState; diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 2149f148fef..0efc7e7af3a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -84,9 +84,9 @@ private predicate ignoreExprAndDescendants(Expr expr) { or // We do not yet translate destructors properly, so for now we ignore any // custom deallocator call, if present. - exists(DeleteExpr deleteExpr | deleteExpr.getAllocatorCall() = expr) + exists(DeleteExpr deleteExpr | deleteExpr.getDeallocatorCall() = expr) or - exists(DeleteArrayExpr deleteArrayExpr | deleteArrayExpr.getAllocatorCall() = expr) + exists(DeleteArrayExpr deleteArrayExpr | deleteArrayExpr.getDeallocatorCall() = expr) or exists(BuiltInVarArgsStart vaStartExpr | vaStartExpr.getLastNamedParameter().getFullyConverted() = expr diff --git a/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/RangeAnalysisUtil.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/RangeAnalysisUtil.qll similarity index 92% rename from cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/RangeAnalysisUtil.qll rename to cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/RangeAnalysisUtil.qll index 0e86b68418a..4fa2ce85e50 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/RangeAnalysisUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/RangeAnalysisUtil.qll @@ -1,6 +1,6 @@ /** - * This file contains the range-analysis specific parts of the `cpp/invalid-pointer-deref` query - * that is used by both `AllocationToInvalidPointer.qll` and `InvalidPointerToDereference.qll`. + * This file contains the range-analysis specific parts of the `cpp/invalid-pointer-deref` + * and `cpp/overrun-write` query. */ private import cpp diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticGuard.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticGuard.qll index 8faf6a3a1de..e7f77c31486 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticGuard.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticGuard.qll @@ -39,6 +39,7 @@ predicate semImplies_v2(SemGuard g1, boolean b1, SemGuard g2, boolean b2) { * Holds if `guard` directly controls the position `controlled` with the * value `testIsTrue`. */ +pragma[nomagic] predicate semGuardDirectlyControlsSsaRead( SemGuard guard, SemSsaReadPosition controlled, boolean testIsTrue ) { diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysis.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysis.qll index 42632f602de..9b00aca362f 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysis.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysis.qll @@ -17,19 +17,27 @@ private import RangeUtils private import RangeAnalysisStage module ModulusAnalysis Bounds, UtilSig U> { - /** - * Holds if `e + delta` equals `v` at `pos`. - */ - private predicate valueFlowStepSsa(SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta) { - U::semSsaUpdateStep(v, e, D::fromInt(delta)) and pos.hasReadOfVar(v) - or + pragma[nomagic] + private predicate valueFlowStepSsaEqFlowCond( + SemSsaReadPosition pos, SemSsaVariable v, SemExpr e, int delta + ) { exists(SemGuard guard, boolean testIsTrue | - pos.hasReadOfVar(v) and guard = U::semEqFlowCond(v, e, D::fromInt(delta), true, testIsTrue) and semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) ) } + /** + * Holds if `e + delta` equals `v` at `pos`. + */ + pragma[nomagic] + private predicate valueFlowStepSsa(SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta) { + U::semSsaUpdateStep(v, e, D::fromInt(delta)) and pos.hasReadOfVar(v) + or + pos.hasReadOfVar(v) and + valueFlowStepSsaEqFlowCond(pos, v, e, delta) + } + /** * Holds if `add` is the addition of `larg` and `rarg`, neither of which are * `ConstantIntegerExpr`s. diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll index 0bd665ed10c..8f701cbc111 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll @@ -660,7 +660,7 @@ module RangeStage< * - `upper = false` : `v >= b + delta` */ private predicate boundedSsa( - SemSsaVariable v, SemSsaReadPosition pos, SemBound b, D::Delta delta, boolean upper, + SemSsaVariable v, SemBound b, D::Delta delta, SemSsaReadPosition pos, boolean upper, boolean fromBackEdge, D::Delta origdelta, SemReason reason ) { exists(SemExpr mid, D::Delta d1, D::Delta d2, SemReason r1, SemReason r2 | @@ -673,10 +673,13 @@ module RangeStage< ) or exists(D::Delta d, SemReason r1, SemReason r2 | - boundedSsa(v, pos, b, d, upper, fromBackEdge, origdelta, r2) or - boundedPhi(v, b, d, upper, fromBackEdge, origdelta, r2) + boundedSsa(pragma[only_bind_into](v), pragma[only_bind_into](b), pragma[only_bind_into](d), + pragma[only_bind_into](pos), upper, fromBackEdge, origdelta, r2) + or + boundedPhi(pragma[only_bind_into](v), pragma[only_bind_into](b), pragma[only_bind_into](d), + upper, fromBackEdge, origdelta, r2) | - unequalIntegralSsa(v, pos, b, d, r1) and + unequalIntegralSsa(v, b, d, pos, r1) and ( upper = true and delta = D::fromFloat(D::toFloat(d) - 1) or @@ -694,7 +697,7 @@ module RangeStage< * Holds if `v != b + delta` at `pos` and `v` is of integral type. */ private predicate unequalIntegralSsa( - SemSsaVariable v, SemSsaReadPosition pos, SemBound b, D::Delta delta, SemReason reason + SemSsaVariable v, SemBound b, D::Delta delta, SemSsaReadPosition pos, SemReason reason ) { exists(SemExpr e, D::Delta d1, D::Delta d2 | unequalFlowStepIntegralSsa(v, pos, e, d1, reason) and @@ -746,7 +749,7 @@ module RangeStage< ) { edge.phiInput(phi, inp) and exists(D::Delta d, boolean fromBackEdge0 | - boundedSsa(inp, edge, b, d, upper, fromBackEdge0, origdelta, reason) + boundedSsa(inp, b, d, edge, upper, fromBackEdge0, origdelta, reason) or boundedPhi(inp, b, d, upper, fromBackEdge0, origdelta, reason) or @@ -1022,7 +1025,7 @@ module RangeStage< reason = TSemNoReason() or exists(SemSsaVariable v, SemSsaReadPositionBlock bb | - boundedSsa(v, bb, b, delta, upper, fromBackEdge, origdelta, reason) and + boundedSsa(v, b, delta, bb, upper, fromBackEdge, origdelta, reason) and e = v.getAUse() and bb.getBlock() = e.getBasicBlock() ) diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeUtils.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeUtils.qll index 52377c5d14a..1b5da03feec 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeUtils.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeUtils.qll @@ -49,6 +49,7 @@ module RangeUtil Lang> implements Range::Ut * - `isEq = true` : `v == e + delta` * - `isEq = false` : `v != e + delta` */ + pragma[nomagic] SemGuard semEqFlowCond( SemSsaVariable v, SemExpr e, D::Delta delta, boolean isEq, boolean testIsTrue ) { diff --git a/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/AllocationToInvalidPointer.qll b/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/AllocationToInvalidPointer.qll index a49f7322e6a..cc1e223410a 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/AllocationToInvalidPointer.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/AllocationToInvalidPointer.qll @@ -56,7 +56,7 @@ private import semmle.code.cpp.ir.dataflow.internal.ProductFlow private import semmle.code.cpp.ir.ValueNumbering private import semmle.code.cpp.controlflow.IRGuards private import codeql.util.Unit -private import RangeAnalysisUtil +private import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil private VariableAccess getAVariableAccess(Expr e) { e.getAChild*() = result } @@ -77,6 +77,15 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) { ) } +/** + * Gets the virtual dispatch branching limit when calculating field flow while searching + * for flow from an allocation to the construction of an out-of-bounds pointer. + * + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ +int allocationToInvalidPointerFieldFlowBranchLimit() { result = 0 } + /** * A module that encapsulates a barrier guard to remove false positives from flow like: * ```cpp @@ -101,9 +110,12 @@ private module SizeBarrier { predicate isSource(DataFlow::Node source) { // The sources is the same as in the sources for the second // projection in the `AllocToInvalidPointerConfig` module. - hasSize(_, source, _) + hasSize(_, source, _) and + InterestingPointerAddInstruction::isInterestingSize(source) } + int fieldFlowBranchLimit() { result = allocationToInvalidPointerFieldFlowBranchLimit() } + /** * Holds if `small <= large + k` holds if `g` evaluates to `testIsTrue`. */ @@ -201,6 +213,8 @@ private module InterestingPointerAddInstruction { hasSize(source.asConvertedExpr(), _, _) } + int fieldFlowBranchLimit() { result = allocationToInvalidPointerFieldFlowBranchLimit() } + predicate isSink(DataFlow::Node sink) { sink.asInstruction() = any(PointerAddInstruction pai).getLeft() } @@ -220,6 +234,19 @@ private module InterestingPointerAddInstruction { flowTo(n) ) } + + /** + * Holds if `n` is a size of an allocation whose result flows to the left operand + * of a pointer-arithmetic instruction. + * + * This predicate is used to reduce the set of tuples in `SizeBarrierConfig::isSource`. + */ + predicate isInterestingSize(DataFlow::Node n) { + exists(DataFlow::Node alloc | + hasSize(alloc.asConvertedExpr(), n, _) and + flow(alloc, _) + ) + } } /** @@ -244,6 +271,10 @@ private module Config implements ProductFlow::StateConfigSig { hasSize(allocSource.asConvertedExpr(), sizeSource, sizeAddend) } + int fieldFlowBranchLimit1() { result = allocationToInvalidPointerFieldFlowBranchLimit() } + + int fieldFlowBranchLimit2() { result = allocationToInvalidPointerFieldFlowBranchLimit() } + predicate isSinkPair( DataFlow::Node allocSink, FlowState1 unit, DataFlow::Node sizeSink, FlowState2 sizeAddend ) { diff --git a/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/InvalidPointerToDereference.qll b/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/InvalidPointerToDereference.qll index 4a2175809e6..69208a94cf5 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/InvalidPointerToDereference.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/InvalidPointerToDereference.qll @@ -81,7 +81,17 @@ private import semmle.code.cpp.dataflow.new.DataFlow private import semmle.code.cpp.ir.ValueNumbering private import semmle.code.cpp.controlflow.IRGuards private import AllocationToInvalidPointer as AllocToInvalidPointer -private import RangeAnalysisUtil +private import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil + +/** + * Gets the virtual dispatch branching limit when calculating field flow while + * searching for flow from an out-of-bounds pointer to a dereference of the + * pointer. + * + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ +int invalidPointerToDereferenceFieldFlowBranchLimit() { result = 0 } private module InvalidPointerToDerefBarrier { private module BarrierConfig implements DataFlow::ConfigSig { @@ -101,6 +111,8 @@ private module InvalidPointerToDerefBarrier { } predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) } + + int fieldFlowBranchLimit() { result = invalidPointerToDereferenceFieldFlowBranchLimit() } } private module BarrierFlow = DataFlow::Global; @@ -178,6 +190,8 @@ private module InvalidPointerToDerefConfig implements DataFlow::StateConfigSig { // Note that this is the only place where the `FlowState` is used in this configuration. node = InvalidPointerToDerefBarrier::getABarrierNode(pai) } + + int fieldFlowBranchLimit() { result = invalidPointerToDereferenceFieldFlowBranchLimit() } } private import DataFlow::GlobalWithState diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/CompareWhereAssignMeant.ql b/cpp/ql/src/Likely Bugs/Likely Typos/CompareWhereAssignMeant.ql index 402f26d875e..46c271b11d7 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/CompareWhereAssignMeant.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/CompareWhereAssignMeant.ql @@ -16,6 +16,7 @@ import cpp from ExprInVoidContext op where not op.isUnevaluated() and + not inMacroExpansion(op) and ( op instanceof EQExpr or diff --git a/cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.ql b/cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.ql index 510b7e8b6c4..f87acaf96e3 100644 --- a/cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.ql +++ b/cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.ql @@ -20,28 +20,10 @@ import semmle.code.cpp.models.interfaces.Allocation import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific +import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil import StringSizeFlow::PathGraph1 import codeql.util.Unit -pragma[nomagic] -Instruction getABoundIn(SemBound b, IRFunction func) { - getSemanticExpr(result) = b.getExpr(0) and - result.getEnclosingIRFunction() = func -} - -/** - * Holds if `i <= b + delta`. - */ -bindingset[i] -pragma[inline_late] -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 - ) -} - VariableAccess getAVariableAccess(Expr e) { e.getAChild*() = result } /** diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.cpp b/cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.cpp similarity index 100% rename from cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.cpp rename to cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.cpp diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.qhelp b/cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.qhelp similarity index 81% rename from cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.qhelp rename to cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.qhelp index 4f590659112..19c0e00215b 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.qhelp @@ -3,7 +3,7 @@ "qhelp.dtd"> -

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.

+

The program performs an out-of-bounds read or write operation, which can cause program instability. In addition, attackers may take advantage of the situation, and implement techniques to use this vulnerability to execute arbitrary code.

@@ -13,7 +13,7 @@

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. +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.

diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql b/cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.ql similarity index 95% rename from cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql rename to cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.ql index f778b4f776f..0a0026ef0f4 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql +++ b/cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.ql @@ -1,10 +1,10 @@ /** * @name Invalid pointer dereference - * @description Dereferencing a pointer that points past it allocation is undefined behavior - * and may lead to security vulnerabilities. + * @description Dereferencing an out-of-bounds pointer is undefined behavior and may lead to security vulnerabilities. * @kind path-problem * @problem.severity error - * @precision high + * @security-severity 9.3 + * @precision medium * @id cpp/invalid-pointer-deref * @tags reliability * security @@ -94,6 +94,12 @@ module FinalConfig implements DataFlow::StateConfigSig { ) } + int fieldFlowBranchLimit() { + result = + allocationToInvalidPointerFieldFlowBranchLimit() + .maximum(invalidPointerToDereferenceFieldFlowBranchLimit()) + } + predicate isAdditionalFlowStep( DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { diff --git a/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql b/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql index 357e6375570..1f743f7e4fb 100644 --- a/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql +++ b/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql @@ -17,21 +17,6 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering import semmle.code.cpp.controlflow.Guards -/** - * A C++ `delete` or `delete[]` expression. - */ -class DeleteOrDeleteArrayExpr extends Expr { - DeleteOrDeleteArrayExpr() { this instanceof DeleteExpr or this instanceof DeleteArrayExpr } - - DeallocationFunction getDeallocator() { - result = [this.(DeleteExpr).getDeallocator(), this.(DeleteArrayExpr).getDeallocator()] - } - - Destructor getDestructor() { - result = [this.(DeleteExpr).getDestructor(), this.(DeleteArrayExpr).getDestructor()] - } -} - /** Gets the `Constructor` invoked when `newExpr` allocates memory. */ Constructor getConstructorForAllocation(NewOrNewArrayExpr newExpr) { result.getACallToThisFunction() = newExpr.getInitializer() diff --git a/cpp/ql/src/change-notes/2023-08-21-invalid-pointer-deref.md b/cpp/ql/src/change-notes/2023-08-21-invalid-pointer-deref.md new file mode 100644 index 00000000000..d8207a75604 --- /dev/null +++ b/cpp/ql/src/change-notes/2023-08-21-invalid-pointer-deref.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* Added a new query, `cpp/invalid-pointer-deref`, to detect out-of-bounds pointer reads and writes. diff --git a/cpp/ql/src/change-notes/2023-08-25-compare-where-assign-meant.md b/cpp/ql/src/change-notes/2023-08-25-compare-where-assign-meant.md new file mode 100644 index 00000000000..8872ba413fb --- /dev/null +++ b/cpp/ql/src/change-notes/2023-08-25-compare-where-assign-meant.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The "Comparison where assignment was intended" query (`cpp/compare-where-assign-meant`) no longer reports comparisons that appear in macro expansions. diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index 46de6334bbb..fd076044593 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 0.7.3 +version: 0.7.4-dev groups: - cpp - queries 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 deleted file mode 100644 index 76da29dc7a0..00000000000 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index 5e7d573c83e..8ed64b76dfe 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -34,11 +34,11 @@ newArrayExprDeallocators | allocators.cpp:108:3:108:19 | new[] | FailedInit | void FailedInit::operator delete[](void*, size_t) | 1 | 1 | sized | | allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned | void FailedInitOveraligned::operator delete[](void*, std::align_val_t, float) | 128 | 128 | aligned | deleteExprs -| allocators.cpp:59:3:59:35 | delete | int | void operator delete(void*, unsigned long) | 4 | 4 | sized | -| allocators.cpp:60:3:60:38 | delete | String | void operator delete(void*, unsigned long) | 8 | 8 | sized | -| allocators.cpp:61:3:61:44 | delete | SizedDealloc | void SizedDealloc::operator delete(void*, size_t) | 32 | 1 | sized | -| allocators.cpp:62:3:62:43 | delete | Overaligned | void operator delete(void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned | -| allocators.cpp:64:3:64:44 | delete | const String | void operator delete(void*, unsigned long) | 8 | 8 | sized | +| allocators.cpp:59:3:59:35 | delete | int | void operator delete(void*, unsigned long) | 4 | 4 | sized | false | +| allocators.cpp:60:3:60:38 | delete | String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false | +| allocators.cpp:61:3:61:44 | delete | SizedDealloc | void SizedDealloc::operator delete(void*, size_t) | 32 | 1 | sized | true | +| allocators.cpp:62:3:62:43 | delete | Overaligned | void operator delete(void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned | false | +| allocators.cpp:64:3:64:44 | delete | const String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false | deleteArrayExprs | allocators.cpp:78:3:78:37 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized | | allocators.cpp:79:3:79:40 | delete[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized | diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index 2d70f2f5083..aba72adf5ba 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -77,7 +77,8 @@ query predicate newArrayExprDeallocators( } query predicate deleteExprs( - DeleteExpr expr, string type, string sig, int size, int alignment, string form + DeleteExpr expr, string type, string sig, int size, int alignment, string form, + boolean hasDeallocatorCall ) { exists(Function deallocator, Type deletedType | expr.getDeallocator() = deallocator and @@ -90,7 +91,10 @@ query predicate deleteExprs( (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and form = sized + " " + aligned - ) + ) and + if exists(expr.getDeallocatorCall()) + then hasDeallocatorCall = true + else hasDeallocatorCall = false ) } diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 5de871e4c68..02e9045bcdb 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -8477,7 +8477,7 @@ ir.cpp: # 1018| getExpr(): [DeleteExpr] delete # 1018| Type = [VoidType] void # 1018| ValueCategory = prvalue -# 1018| getAllocatorCall(): [FunctionCall] call to operator delete +# 1018| getDeallocatorCall(): [FunctionCall] call to operator delete # 1018| Type = [VoidType] void # 1018| ValueCategory = prvalue # 1018| getExpr(): [Literal] 0 @@ -8555,7 +8555,7 @@ ir.cpp: # 1027| getExpr(): [DeleteArrayExpr] delete[] # 1027| Type = [VoidType] void # 1027| ValueCategory = prvalue -# 1027| getAllocatorCall(): [FunctionCall] call to operator delete[] +# 1027| getDeallocatorCall(): [FunctionCall] call to operator delete[] # 1027| Type = [VoidType] void # 1027| ValueCategory = prvalue # 1027| getExpr(): [Literal] 0 diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/CompareWhereAssignMeant/CompareWhereAssignMeant.expected b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/CompareWhereAssignMeant/CompareWhereAssignMeant.expected index 1beb220e5a1..75ecd8f2452 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/CompareWhereAssignMeant/CompareWhereAssignMeant.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/CompareWhereAssignMeant/CompareWhereAssignMeant.expected @@ -6,3 +6,5 @@ | test.cpp:39:23:39:28 | ... == ... | This '==' operator has no effect. The assignment ('=') operator was probably intended. | | test.cpp:42:23:42:28 | ... == ... | This '==' operator has no effect. The assignment ('=') operator was probably intended. | | test.cpp:51:13:51:13 | call to operator== | This '==' operator has no effect. The assignment ('=') operator was probably intended. | +| test.cpp:72:3:72:8 | ... == ... | This '==' operator has no effect. The assignment ('=') operator was probably intended. | +| test.cpp:73:3:73:12 | ... == ... | This '==' operator has no effect. The assignment ('=') operator was probably intended. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/CompareWhereAssignMeant/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/CompareWhereAssignMeant/test.cpp index d3adcb50421..2fa42105905 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/CompareWhereAssignMeant/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/CompareWhereAssignMeant/test.cpp @@ -61,3 +61,14 @@ template auto sfinaeTrick(T1 x1, T2 x2) -> decltype(x1 == x2, bool()) { // GOOD return x1 == x2; } + +void report_error(const char*); + +#define DOES_NOT_THROW(E) do { try { E; } catch (...) { report_error(""); } } while(0) +#define ID(X) (X) + +void test_inside_macro_expansion(int x, int y) { + DOES_NOT_THROW(x == y); // GOOD + x == y; // BAD + x == ID(y); // BAD +} diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/AllocationToInvalidPointer.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-193/AllocationToInvalidPointer.expected similarity index 100% rename from cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/AllocationToInvalidPointer.expected rename to cpp/ql/test/query-tests/Security/CWE/CWE-193/AllocationToInvalidPointer.expected index 48de9172b36..8ec8033d086 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/AllocationToInvalidPointer.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-193/AllocationToInvalidPointer.expected @@ -1,2 +1,2 @@ -failures testFailures +failures diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/AllocationToInvalidPointer.ql b/cpp/ql/test/query-tests/Security/CWE/CWE-193/AllocationToInvalidPointer.ql similarity index 100% rename from cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/AllocationToInvalidPointer.ql rename to cpp/ql/test/query-tests/Security/CWE/CWE-193/AllocationToInvalidPointer.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerDeref.expected similarity index 76% rename from cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected rename to cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerDeref.expected index 0215848c5f2..edc9be764a6 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerDeref.expected @@ -45,58 +45,6 @@ edges | test.cpp:53:5:53:23 | ... = ... | test.cpp:51:33:51:35 | end | | test.cpp:53:12:53:23 | ... + ... | test.cpp:53:5:53:23 | ... = ... | | test.cpp:60:34:60:37 | mk_array output argument | test.cpp:67:9:67:14 | ... = ... | -| test.cpp:80:9:80:16 | mk_array indirection [end] | test.cpp:89:19:89:26 | call to mk_array [end] | -| test.cpp:80:9:80:16 | mk_array indirection [end] | test.cpp:119:18:119:25 | call to mk_array [end] | -| test.cpp:82:5:82:28 | ... = ... | test.cpp:82:9:82:13 | arr indirection [post update] [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 | ... = ... | -| test.cpp:83:5:83:30 | ... = ... | 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 | mk_array indirection [end] | -| test.cpp:83:15:83:17 | arr indirection [begin] | test.cpp:83:19:83:23 | begin indirection | -| test.cpp:83:15:83:30 | ... + ... | test.cpp:83:5:83:30 | ... = ... | -| test.cpp:83:19:83:23 | begin indirection | test.cpp:83:5:83:30 | ... = ... | -| test.cpp:83:19:83:23 | begin indirection | test.cpp:83:15:83:30 | ... + ... | -| test.cpp:89:19:89:26 | call to mk_array [end] | test.cpp:91:36:91:38 | arr indirection [end] | -| test.cpp:89:19:89:26 | call to mk_array [end] | test.cpp:95:36:95:38 | arr indirection [end] | -| test.cpp:91:36:91:38 | arr indirection [end] | test.cpp:91:40:91:42 | end indirection | -| test.cpp:91:36:91:38 | arr indirection [end] | test.cpp:96:9:96:14 | ... = ... | -| test.cpp:91:40:91:42 | end indirection | test.cpp:96:9:96:14 | ... = ... | -| test.cpp:95:36:95:38 | arr indirection [end] | test.cpp:95:40:95:42 | end indirection | -| test.cpp:95:36:95:38 | arr indirection [end] | test.cpp:96:9:96:14 | ... = ... | -| test.cpp:95:40:95:42 | end indirection | test.cpp:96:9:96:14 | ... = ... | -| 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:105:36:105:38 | arr indirection [end] | test.cpp:105:40:105:42 | end indirection | -| test.cpp:105:36:105:38 | arr indirection [end] | test.cpp:110:9:110:14 | ... = ... | -| test.cpp:105:40:105:42 | end indirection | test.cpp:110:9:110:14 | ... = ... | -| test.cpp:109:36:109:38 | arr indirection [end] | test.cpp:109:40:109:42 | end indirection | -| test.cpp:109:36:109:38 | arr indirection [end] | test.cpp:110:9:110:14 | ... = ... | -| test.cpp:109:40:109:42 | end indirection | test.cpp:110:9:110:14 | ... = ... | -| test.cpp:119:18:119:25 | call to mk_array [end] | test.cpp:104:27:104:29 | arr [end] | -| test.cpp:141:10:141:19 | mk_array_p indirection [end] | test.cpp:150:20:150:29 | call to mk_array_p indirection [end] | -| test.cpp:141:10:141:19 | mk_array_p indirection [end] | test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | -| test.cpp:143:5:143:29 | ... = ... | test.cpp:143:10:143:14 | arr indirection [post update] [begin] | -| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | test.cpp:144:16:144:18 | arr indirection [begin] | -| test.cpp:143:18:143:23 | call to malloc | test.cpp:143:5:143:29 | ... = ... | -| test.cpp:144:5:144:32 | ... = ... | test.cpp:144:10:144:12 | arr indirection [post update] [end] | -| test.cpp:144:10:144:12 | arr indirection [post update] [end] | test.cpp:141:10:141:19 | mk_array_p indirection [end] | -| test.cpp:144:16:144:18 | arr indirection [begin] | test.cpp:144:21:144:25 | begin indirection | -| test.cpp:144:16:144:32 | ... + ... | test.cpp:144:5:144:32 | ... = ... | -| test.cpp:144:21:144:25 | begin indirection | test.cpp:144:5:144:32 | ... = ... | -| test.cpp:144:21:144:25 | begin indirection | test.cpp:144:16:144:32 | ... + ... | -| test.cpp:150:20:150:29 | call to mk_array_p indirection [end] | test.cpp:156:37:156:39 | arr indirection [end] | -| test.cpp:156:37:156:39 | arr indirection [end] | test.cpp:156:42:156:44 | end indirection | -| test.cpp:156:37:156:39 | arr indirection [end] | test.cpp:157:9:157:14 | ... = ... | -| test.cpp:156:42:156:44 | end indirection | test.cpp:157:9:157:14 | ... = ... | -| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:166:37:166:39 | arr indirection [end] | -| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:170:37:170:39 | arr indirection [end] | -| test.cpp:166:37:166:39 | arr indirection [end] | test.cpp:166:42:166:44 | end indirection | -| test.cpp:166:37:166:39 | arr indirection [end] | test.cpp:171:9:171:14 | ... = ... | -| test.cpp:166:42:166:44 | end indirection | test.cpp:171:9:171:14 | ... = ... | -| test.cpp:170:37:170:39 | arr indirection [end] | test.cpp:170:42:170:44 | end indirection | -| test.cpp:170:37:170:39 | arr indirection [end] | test.cpp:171:9:171:14 | ... = ... | -| test.cpp:170:42:170:44 | end indirection | test.cpp:171:9:171:14 | ... = ... | -| test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | test.cpp:165:29:165:31 | arr indirection [end] | | test.cpp:194:23:194:28 | call to malloc | test.cpp:195:17:195:23 | ... + ... | | test.cpp:194:23:194:28 | call to malloc | test.cpp:195:17:195:23 | ... + ... | | test.cpp:194:23:194:28 | call to malloc | test.cpp:201:5:201:19 | ... = ... | @@ -233,6 +181,18 @@ edges | test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array | | test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array | | test.cpp:781:14:781:27 | new[] | test.cpp:786:18:786:27 | access to array | +| test.cpp:792:60:792:62 | end | test.cpp:800:40:800:43 | mk_array_no_field_flow output argument | +| test.cpp:792:60:792:62 | end | test.cpp:832:40:832:43 | mk_array_no_field_flow output argument | +| test.cpp:793:14:793:19 | call to malloc | test.cpp:794:5:794:24 | ... = ... | +| test.cpp:793:14:793:19 | call to malloc | test.cpp:794:12:794:24 | ... + ... | +| test.cpp:794:5:794:24 | ... = ... | test.cpp:792:60:792:62 | end | +| test.cpp:794:12:794:24 | ... + ... | test.cpp:794:5:794:24 | ... = ... | +| test.cpp:800:40:800:43 | mk_array_no_field_flow output argument | test.cpp:807:7:807:12 | ... = ... | +| test.cpp:815:52:815:54 | end | test.cpp:815:52:815:54 | end | +| test.cpp:815:52:815:54 | end | test.cpp:821:7:821:12 | ... = ... | +| test.cpp:815:52:815:54 | end | test.cpp:821:7:821:12 | ... = ... | +| test.cpp:832:40:832:43 | mk_array_no_field_flow output argument | test.cpp:833:37:833:39 | end | +| test.cpp:833:37:833:39 | end | test.cpp:815:52:815:54 | end | nodes | test.cpp:4:15:4:20 | call to malloc | semmle.label | call to malloc | | test.cpp:5:15:5:22 | ... + ... | semmle.label | ... + ... | @@ -260,48 +220,6 @@ nodes | test.cpp:53:12:53:23 | ... + ... | semmle.label | ... + ... | | test.cpp:60:34:60:37 | mk_array output argument | semmle.label | mk_array output argument | | test.cpp:67:9:67:14 | ... = ... | semmle.label | ... = ... | -| test.cpp:80:9:80:16 | mk_array indirection [end] | semmle.label | mk_array indirection [end] | -| test.cpp:82:5:82:28 | ... = ... | semmle.label | ... = ... | -| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | semmle.label | arr indirection [post update] [begin] | -| test.cpp:82:17:82:22 | call to malloc | semmle.label | call to malloc | -| test.cpp:83:5:83:30 | ... = ... | semmle.label | ... = ... | -| test.cpp:83:9:83:11 | arr indirection [post update] [end] | semmle.label | arr indirection [post update] [end] | -| test.cpp:83:15:83:17 | arr indirection [begin] | semmle.label | arr indirection [begin] | -| test.cpp:83:15:83:30 | ... + ... | semmle.label | ... + ... | -| test.cpp:83:19:83:23 | begin indirection | semmle.label | begin indirection | -| test.cpp:89:19:89:26 | call to mk_array [end] | semmle.label | call to mk_array [end] | -| test.cpp:91:36:91:38 | arr indirection [end] | semmle.label | arr indirection [end] | -| test.cpp:91:40:91:42 | end indirection | semmle.label | end indirection | -| test.cpp:95:36:95:38 | arr indirection [end] | semmle.label | arr indirection [end] | -| test.cpp:95:40:95:42 | end indirection | semmle.label | end indirection | -| test.cpp:96:9:96:14 | ... = ... | semmle.label | ... = ... | -| test.cpp:104:27:104:29 | arr [end] | semmle.label | arr [end] | -| test.cpp:105:36:105:38 | arr indirection [end] | semmle.label | arr indirection [end] | -| test.cpp:105:40:105:42 | end indirection | semmle.label | end indirection | -| test.cpp:109:36:109:38 | arr indirection [end] | semmle.label | arr indirection [end] | -| test.cpp:109:40:109:42 | end indirection | semmle.label | end indirection | -| test.cpp:110:9:110:14 | ... = ... | semmle.label | ... = ... | -| test.cpp:119:18:119:25 | call to mk_array [end] | semmle.label | call to mk_array [end] | -| test.cpp:141:10:141:19 | mk_array_p indirection [end] | semmle.label | mk_array_p indirection [end] | -| test.cpp:143:5:143:29 | ... = ... | semmle.label | ... = ... | -| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | semmle.label | arr indirection [post update] [begin] | -| test.cpp:143:18:143:23 | call to malloc | semmle.label | call to malloc | -| test.cpp:144:5:144:32 | ... = ... | semmle.label | ... = ... | -| test.cpp:144:10:144:12 | arr indirection [post update] [end] | semmle.label | arr indirection [post update] [end] | -| test.cpp:144:16:144:18 | arr indirection [begin] | semmle.label | arr indirection [begin] | -| test.cpp:144:16:144:32 | ... + ... | semmle.label | ... + ... | -| test.cpp:144:21:144:25 | begin indirection | semmle.label | begin indirection | -| test.cpp:150:20:150:29 | call to mk_array_p indirection [end] | semmle.label | call to mk_array_p indirection [end] | -| test.cpp:156:37:156:39 | arr indirection [end] | semmle.label | arr indirection [end] | -| test.cpp:156:42:156:44 | end indirection | semmle.label | end indirection | -| test.cpp:157:9:157:14 | ... = ... | semmle.label | ... = ... | -| test.cpp:165:29:165:31 | arr indirection [end] | semmle.label | arr indirection [end] | -| test.cpp:166:37:166:39 | arr indirection [end] | semmle.label | arr indirection [end] | -| test.cpp:166:42:166:44 | end indirection | semmle.label | end indirection | -| test.cpp:170:37:170:39 | arr indirection [end] | semmle.label | arr indirection [end] | -| test.cpp:170:42:170:44 | end indirection | semmle.label | end indirection | -| test.cpp:171:9:171:14 | ... = ... | semmle.label | ... = ... | -| test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | semmle.label | call to mk_array_p indirection [end] | | test.cpp:194:23:194:28 | call to malloc | semmle.label | call to malloc | | test.cpp:195:17:195:23 | ... + ... | semmle.label | ... + ... | | test.cpp:195:17:195:23 | ... + ... | semmle.label | ... + ... | @@ -394,6 +312,17 @@ nodes | test.cpp:772:16:772:29 | access to array | semmle.label | access to array | | test.cpp:781:14:781:27 | new[] | semmle.label | new[] | | test.cpp:786:18:786:27 | access to array | semmle.label | access to array | +| test.cpp:792:60:792:62 | end | semmle.label | end | +| test.cpp:793:14:793:19 | call to malloc | semmle.label | call to malloc | +| test.cpp:794:5:794:24 | ... = ... | semmle.label | ... = ... | +| test.cpp:794:12:794:24 | ... + ... | semmle.label | ... + ... | +| test.cpp:800:40:800:43 | mk_array_no_field_flow output argument | semmle.label | mk_array_no_field_flow output argument | +| test.cpp:807:7:807:12 | ... = ... | semmle.label | ... = ... | +| test.cpp:815:52:815:54 | end | semmle.label | end | +| test.cpp:815:52:815:54 | end | semmle.label | end | +| test.cpp:821:7:821:12 | ... = ... | semmle.label | ... = ... | +| test.cpp:832:40:832:43 | mk_array_no_field_flow output argument | semmle.label | mk_array_no_field_flow output argument | +| test.cpp:833:37:833:39 | end | semmle.label | end | subpaths #select | test.cpp:6:14:6:15 | * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | * ... | 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 | @@ -404,10 +333,6 @@ subpaths | test.cpp:42:14:42:15 | * ... | test.cpp:40:15:40:20 | call to malloc | test.cpp:42:14:42:15 | * ... | 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 | * ... | test.cpp:40:15:40:20 | call to malloc | test.cpp:44:14:44:21 | * ... | 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:67:9:67:14 | ... = ... | test.cpp:52:19:52:24 | call to malloc | test.cpp:67:9:67:14 | ... = ... | 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 | ... = ... | test.cpp:82:17:82:22 | call to malloc | test.cpp:96:9:96:14 | ... = ... | 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 | ... = ... | test.cpp:82:17:82:22 | call to malloc | test.cpp:110:9:110:14 | ... = ... | 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 | ... = ... | test.cpp:143:18:143:23 | call to malloc | test.cpp:157:9:157:14 | ... = ... | 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 | ... = ... | test.cpp:143:18:143:23 | call to malloc | test.cpp:171:9:171:14 | ... = ... | 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:201:5:201:19 | ... = ... | test.cpp:194:23:194:28 | call to malloc | test.cpp:201:5:201:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:194:23:194:28 | call to malloc | call to malloc | test.cpp:195:21:195:23 | len | len | | test.cpp:213:5:213:13 | ... = ... | test.cpp:205:23:205:28 | call to malloc | test.cpp:213:5:213:13 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:205:23:205:28 | call to malloc | call to malloc | test.cpp:206:21:206:23 | len | len | | test.cpp:232:3:232:20 | ... = ... | test.cpp:231:18:231:30 | new[] | test.cpp:232:3:232:20 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:231:18:231:30 | new[] | new[] | test.cpp:232:11:232:15 | index | index | @@ -434,3 +359,5 @@ subpaths | test.cpp:772:16:772:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:767:22:767:28 | ... + ... | ... + ... | | test.cpp:772:16:772:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:772:22:772:28 | ... + ... | ... + ... | | test.cpp:786:18:786:27 | access to array | test.cpp:781:14:781:27 | new[] | test.cpp:786:18:786:27 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:781:14:781:27 | new[] | new[] | test.cpp:786:20:786:26 | ... + ... | ... + ... | +| test.cpp:807:7:807:12 | ... = ... | test.cpp:793:14:793:19 | call to malloc | test.cpp:807:7:807:12 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:793:14:793:19 | call to malloc | call to malloc | test.cpp:794:21:794:24 | size | size | +| test.cpp:821:7:821:12 | ... = ... | test.cpp:793:14:793:19 | call to malloc | test.cpp:821:7:821:12 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:793:14:793:19 | call to malloc | call to malloc | test.cpp:794:21:794:24 | size | size | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerDeref.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerDeref.qlref new file mode 100644 index 00000000000..b899b6eeb20 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerDeref.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-193/InvalidPointerDeref.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerToDereference.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerToDereference.expected similarity index 100% rename from cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerToDereference.expected rename to cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerToDereference.expected index 48de9172b36..8ec8033d086 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerToDereference.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerToDereference.expected @@ -1,2 +1,2 @@ -failures testFailures +failures diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerToDereference.ql b/cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerToDereference.ql similarity index 100% rename from cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerToDereference.ql rename to cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerToDereference.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-193/test.cpp similarity index 91% rename from cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp rename to cpp/ql/test/query-tests/Security/CWE/CWE-193/test.cpp index 13ddb2cf1b1..aba60b79ebf 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-193/test.cpp @@ -80,7 +80,7 @@ struct array_t { array_t mk_array(int size) { array_t arr; arr.begin = malloc(size); - arr.end = arr.begin + size; // $ alloc=L82 + arr.end = arr.begin + size; // $ MISSING: alloc=L82 return arr; } @@ -93,7 +93,7 @@ void test6(int size) { } for (char* p = arr.begin; p <= arr.end; ++p) { - *p = 0; // $ deref=L83->L91->L96 deref=L83->L95->L96 // BAD + *p = 0; // $ MISSING: deref=L83->L91->L96 deref=L83->L95->L96 // BAD [NOT DETECTED] } for (char* p = arr.begin; p < arr.end; ++p) { @@ -107,7 +107,7 @@ void test7_callee(array_t arr) { } for (char* p = arr.begin; p <= arr.end; ++p) { - *p = 0; // $ deref=L83->L105->L110 deref=L83->L109->L110 // BAD + *p = 0; // $ MISSING: deref=L83->L105->L110 deref=L83->L109->L110 // BAD [NOT DETECTED] } for (char* p = arr.begin; p < arr.end; ++p) { @@ -141,7 +141,7 @@ void test8(int size) { 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; // $ alloc=L143 + arr->end = arr->begin + size; // $ MISSING: alloc=L143 return arr; } @@ -154,7 +154,7 @@ void test9(int size) { } for (char* p = arr->begin; p <= arr->end; ++p) { - *p = 0; // $ deref=L144->L156->L157 // BAD + *p = 0; // $ MISSING: deref=L144->L156->L157 // BAD [NOT DETECTED] } for (char* p = arr->begin; p < arr->end; ++p) { @@ -168,7 +168,7 @@ void test10_callee(array_t *arr) { } for (char* p = arr->begin; p <= arr->end; ++p) { - *p = 0; // $ deref=L144->L166->L171 deref=L144->L170->L171 // BAD + *p = 0; // $ MISSING: deref=L144->L166->L171 deref=L144->L170->L171 // BAD [NOT DETECTED] } for (char* p = arr->begin; p < arr->end; ++p) { @@ -787,4 +787,48 @@ void test38_simple(unsigned size, unsigned pos, unsigned numParams) { } } } -} \ No newline at end of file +} + +void mk_array_no_field_flow(int size, char** begin, char** end) { + *begin = malloc(size); + *end = *begin + size; // $ alloc=L793 +} + +void test6_no_field_flow(int size) { + char* begin; + char* end; + mk_array_no_field_flow(size, &begin, &end); + + for (char* p = begin; p != end; ++p) { + *p = 0; // GOOD + } + + for (char* p = begin; p <= end; ++p) { + *p = 0; // $ deref=L794->L802->L807 deref=L794->L806->L807 // BAD + } + + for (char* p = begin; p < end; ++p) { + *p = 0; // GOOD + } +} + +void test7_callee_no_field_flow(char* begin, char* end) { + for (char* p = begin; p != end; ++p) { + *p = 0; // GOOD + } + + for (char* p = begin; p <= end; ++p) { + *p = 0; // $ deref=L794->L815->L821 deref=L794->L816->L821 deref=L794->L820->L821 // BAD + } + + for (char* p = begin; p < end; ++p) { + *p = 0; // GOOD + } +} + +void test7_no_field_flow(int size) { + char* begin; + char* end; + mk_array_no_field_flow(size, &begin, &end); + test7_callee_no_field_flow(begin, end); +} diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs index fb07ae02f60..d2644d326a4 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs @@ -1,12 +1,12 @@ using Xunit; -using Semmle.Autobuild.Shared; -using Semmle.Util; -using System.Collections.Generic; using System; -using System.Linq; -using Microsoft.Build.Construction; -using System.Xml; +using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Semmle.Util; +using Semmle.Autobuild.Shared; namespace Semmle.Autobuild.CSharp.Tests { diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj index 590c03738b0..ecc67fa5695 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj @@ -8,12 +8,12 @@ - - + + all runtime; build; native; contentfiles; analyzers - + diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpAutobuilder.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpAutobuilder.cs index 92c615419cc..ed368d006bc 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpAutobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpAutobuilder.cs @@ -1,8 +1,8 @@ -using Semmle.Extraction.CSharp; +using System.Linq; +using Semmle.Util; using Semmle.Util.Logging; using Semmle.Autobuild.Shared; -using Semmle.Util; -using System.Linq; +using Semmle.Extraction.CSharp; namespace Semmle.Autobuild.CSharp { diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpDiagnosticClassifier.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpDiagnosticClassifier.cs index 821ad3222e1..85d6c872c84 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpDiagnosticClassifier.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpDiagnosticClassifier.cs @@ -2,8 +2,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; -using Semmle.Autobuild.Shared; using Semmle.Util; +using Semmle.Autobuild.Shared; namespace Semmle.Autobuild.CSharp { diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs index e18058339f5..9a161414a03 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs @@ -1,11 +1,11 @@ using System; -using Semmle.Util.Logging; -using System.Linq; -using Newtonsoft.Json.Linq; using System.Collections.Generic; using System.IO; +using System.Linq; using Semmle.Util; +using Semmle.Util.Logging; using Semmle.Autobuild.Shared; +using Newtonsoft.Json.Linq; namespace Semmle.Autobuild.CSharp { diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj b/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj index 1083564dd26..6edc9fdcd97 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj @@ -3,9 +3,9 @@ net7.0 Semmle.Autobuild.CSharp Semmle.Autobuild.CSharp - + Exe - + false win-x64;linux-x64;osx-x64 enable @@ -14,8 +14,8 @@ - - + + diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs index 29d60331d5d..6bed39efe76 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs @@ -1,9 +1,9 @@ -using Semmle.Util; -using Semmle.Util.Logging; using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Semmle.Util; +using Semmle.Util.Logging; namespace Semmle.Autobuild.Shared { diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs index 46c32ecbd72..f917e3efc8a 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs @@ -1,13 +1,11 @@ -using Semmle.Util; -using System; +using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; -using System.Xml; -using System.Net.Http; using System.Diagnostics.CodeAnalysis; -using System.Threading.Tasks; +using System.IO; using System.Runtime.InteropServices; +using System.Xml; +using Semmle.Util; namespace Semmle.Autobuild.Shared { @@ -283,17 +281,8 @@ namespace Semmle.Autobuild.Shared public string EnvironmentExpandEnvironmentVariables(string s) => Environment.ExpandEnvironmentVariables(s); - private static async Task DownloadFileAsync(string address, string filename) - { - using var httpClient = new HttpClient(); - using var request = new HttpRequestMessage(HttpMethod.Get, address); - using var contentStream = await (await httpClient.SendAsync(request)).Content.ReadAsStreamAsync(); - using var stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true); - await contentStream.CopyToAsync(stream); - } - public void DownloadFile(string address, string fileName) => - DownloadFileAsync(address, fileName).Wait(); + FileUtils.DownloadFile(address, fileName); public IDiagnosticsWriter CreateDiagnosticsWriter(string filename) => new DiagnosticsStream(filename); diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs index e0e4404f312..bebf2a1eea4 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs @@ -1,6 +1,7 @@ -using Semmle.Util.Logging; using System.Collections.Generic; using System.Linq; +using Semmle.Util; +using Semmle.Util.Logging; namespace Semmle.Autobuild.Shared { @@ -190,7 +191,7 @@ namespace Semmle.Autobuild.Shared }) & BuildScript.DownloadFile( - "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", + FileUtils.NugetExeUrl, path, e => builder.Log(Severity.Warning, $"Failed to download 'nuget.exe': {e.Message}")) & diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj b/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj index 7a1f537fe75..83c53552cc0 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj @@ -11,7 +11,7 @@ - + diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs index 78929b3a93e..d48cfa15913 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs @@ -1,9 +1,9 @@ -using Microsoft.Build.Construction; -using Microsoft.Build.Exceptions; -using System; +using System; using System.Collections.Generic; -using System.Linq; using System.IO; +using System.Linq; +using Microsoft.Build.Construction; +using Microsoft.Build.Exceptions; using Semmle.Util.Logging; namespace Semmle.Autobuild.Shared diff --git a/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj b/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj index 5bf70a9346b..c37242cd890 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj +++ b/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj @@ -24,7 +24,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs index 5109b7df056..d6a19b9cd1a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs @@ -59,13 +59,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching this.progressMonitor.FindingFiles(srcDir); packageDirectory = new TemporaryDirectory(ComputeTempDirectory(sourceDir.FullName)); - - this.fileContent = new FileContent(progressMonitor, () => GetFiles("*.*")); - this.allSources = GetFiles("*.cs").ToList(); - var allProjects = GetFiles("*.csproj"); + var allFiles = GetAllFiles().ToList(); + var smallFiles = allFiles.SelectSmallFiles(progressMonitor).SelectFileNames(); + this.fileContent = new FileContent(progressMonitor, smallFiles); + this.allSources = allFiles.SelectFileNamesByExtension(".cs").ToList(); + var allProjects = allFiles.SelectFileNamesByExtension(".csproj"); var solutions = options.SolutionFile is not null ? new[] { options.SolutionFile } - : GetFiles("*.sln"); + : allFiles.SelectFileNamesByExtension(".sln"); var dllDirNames = options.DllDirs.Select(Path.GetFullPath).ToList(); @@ -107,7 +108,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching { Restore(solutions); Restore(allProjects); - DownloadMissingPackages(); + DownloadMissingPackages(allFiles); } } @@ -136,7 +137,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching if (bool.TryParse(webViewExtractionOption, out var shouldExtractWebViews) && shouldExtractWebViews) { - GenerateSourceFilesFromWebViews(); + GenerateSourceFilesFromWebViews(allFiles); } progressMonitor.Summary( @@ -151,13 +152,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching DateTime.Now - startTime); } - private void GenerateSourceFilesFromWebViews() + private void GenerateSourceFilesFromWebViews(List allFiles) { progressMonitor.LogInfo($"Generating source files from cshtml and razor files."); - var views = GetFiles("*.cshtml") - .Concat(GetFiles("*.razor")) - .ToArray(); + var views = allFiles.SelectFileNamesByExtension(".cshtml", ".razor").ToArray(); if (views.Length > 0) { @@ -185,15 +184,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching public DependencyManager(string srcDir) : this(srcDir, DependencyOptions.Default, new ConsoleLogger(Verbosity.Info)) { } - private IEnumerable GetFiles(string pattern, bool recurseSubdirectories = true) => - sourceDir.GetFiles(pattern, new EnumerationOptions - { - RecurseSubdirectories = recurseSubdirectories, - MatchCasing = MatchCasing.CaseInsensitive - }) - .Where(d => d.Extension != ".dll") - .Select(d => d.FullName) - .Where(d => !options.ExcludesFile(d)); + private IEnumerable GetAllFiles() => + sourceDir.GetFiles("*.*", new EnumerationOptions { RecurseSubdirectories = true }) + .Where(d => d.Extension != ".dll" && !options.ExcludesFile(d.FullName)); /// /// Computes a unique temp directory for the packages associated @@ -374,14 +367,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching } } - private void DownloadMissingPackages() + private void DownloadMissingPackages(List allFiles) { - var nugetConfigs = GetFiles("nuget.config", recurseSubdirectories: true).ToArray(); + var nugetConfigs = allFiles.SelectFileNamesByName("nuget.config").ToArray(); string? nugetConfig = null; if (nugetConfigs.Length > 1) { progressMonitor.MultipleNugetConfig(nugetConfigs); - nugetConfig = GetFiles("nuget.config", recurseSubdirectories: false).FirstOrDefault(); + nugetConfig = allFiles + .SelectRootFiles(sourceDir) + .SelectFileNamesByName("nuget.config") + .FirstOrDefault(); if (nugetConfig == null) { progressMonitor.NoTopLevelNugetConfig(); @@ -393,8 +389,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching } var alreadyDownloadedPackages = Directory.GetDirectories(packageDirectory.DirInfo.FullName) - .Select(d => Path.GetFileName(d) - .ToLowerInvariant()); + .Select(d => Path.GetFileName(d).ToLowerInvariant()); var notYetDownloadedPackages = fileContent.AllPackages.Except(alreadyDownloadedPackages); foreach (var package in notYetDownloadedPackages) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs index 74a1ba87428..35bdce4750d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text.RegularExpressions; using Semmle.Util; @@ -18,7 +17,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching { private readonly ProgressMonitor progressMonitor; private readonly IUnsafeFileReader unsafeFileReader; - private readonly Func> getFiles; + private readonly IEnumerable files; private readonly HashSet allPackages = new HashSet(); private readonly Initializer initialize; @@ -50,17 +49,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching } internal FileContent(ProgressMonitor progressMonitor, - Func> getFiles, + IEnumerable files, IUnsafeFileReader unsafeFileReader) { this.progressMonitor = progressMonitor; - this.getFiles = getFiles; + this.files = files; this.unsafeFileReader = unsafeFileReader; this.initialize = new Initializer(DoInitialize); } - public FileContent(ProgressMonitor progressMonitor, Func> getFiles) : this(progressMonitor, getFiles, new UnsafeFileReader()) + public FileContent(ProgressMonitor progressMonitor, IEnumerable files) : this(progressMonitor, files, new UnsafeFileReader()) { } private static string GetGroup(ReadOnlySpan input, ValueMatch valueMatch, string groupPrefix) @@ -95,7 +94,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching private void DoInitialize() { - foreach (var file in getFiles()) + foreach (var file in files) { try { diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileInfoExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileInfoExtensions.cs new file mode 100644 index 00000000000..1d285d03d04 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileInfoExtensions.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Semmle.Extraction.CSharp.DependencyFetching +{ + public static class FileInfoExtensions + { + private static IEnumerable SelectFilesAux(this IEnumerable files, Predicate p) => + files.Where(f => p(f)).Select(fi => fi.FullName); + + public static IEnumerable SelectRootFiles(this IEnumerable files, DirectoryInfo dir) => + files.Where(file => file.DirectoryName == dir.FullName); + + internal static IEnumerable SelectSmallFiles(this IEnumerable files, ProgressMonitor progressMonitor) + { + const int oneMb = 1_048_576; + return files.Where(file => + { + if (file.Length > oneMb) + { + progressMonitor.LogDebug($"Skipping {file.FullName} because it is bigger than 1MB."); + return false; + } + return true; + }); + } + + public static IEnumerable SelectFileNamesByExtension(this IEnumerable files, params string[] extensions) => + files.SelectFilesAux(fi => extensions.Contains(fi.Extension)); + + public static IEnumerable SelectFileNamesByName(this IEnumerable files, params string[] names) => + files.SelectFilesAux(fi => names.Any(name => string.Compare(name, fi.Name, true) == 0)); + + public static IEnumerable SelectFileNames(this IEnumerable files) => + files.SelectFilesAux(_ => true); + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackages.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackages.cs index 83205c0ce6f..6443c99127e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackages.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackages.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -14,70 +13,91 @@ namespace Semmle.Extraction.CSharp.DependencyFetching /// internal class NugetPackages { - /// - /// Create the package manager for a specified source tree. - /// - public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory, ProgressMonitor progressMonitor) - { - SourceDirectory = sourceDir; - PackageDirectory = packageDirectory; - this.progressMonitor = progressMonitor; - - // Expect nuget.exe to be in a `nuget` directory under the directory containing this exe. - var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location; - var directory = Path.GetDirectoryName(currentAssembly) - ?? throw new FileNotFoundException($"Directory path '{currentAssembly}' of current assembly is null"); - nugetExe = Path.Combine(directory, "nuget", "nuget.exe"); - - if (!File.Exists(nugetExe)) - throw new FileNotFoundException(string.Format("NuGet could not be found at {0}", nugetExe)); - - packages = new DirectoryInfo(SourceDirectory) - .EnumerateFiles("packages.config", SearchOption.AllDirectories) - .ToArray(); - } - - // List of package files to download. - private readonly FileInfo[] packages; + private readonly string nugetExe; + private readonly ProgressMonitor progressMonitor; /// /// The list of package files. /// - public IEnumerable PackageFiles => packages; - - /// - /// Download the packages to the temp folder. - /// - /// The progress monitor used for reporting errors etc. - public void InstallPackages() - { - foreach (var package in packages) - { - RestoreNugetPackage(package.FullName); - } - } - - /// - /// The source directory used. - /// - public string SourceDirectory - { - get; - private set; - } + private readonly FileInfo[] packageFiles; /// /// The computed packages directory. /// This will be in the Temp location /// so as to not trample the source tree. /// - public TemporaryDirectory PackageDirectory { get; } + private readonly TemporaryDirectory packageDirectory; + + /// + /// Create the package manager for a specified source tree. + /// + public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory, ProgressMonitor progressMonitor) + { + this.packageDirectory = packageDirectory; + this.progressMonitor = progressMonitor; + + nugetExe = ResolveNugetExe(sourceDir); + packageFiles = new DirectoryInfo(sourceDir) + .EnumerateFiles("packages.config", SearchOption.AllDirectories) + .ToArray(); + } + + /// + /// Tries to find the location of `nuget.exe` in the nuget directory under the directory + /// containing the executing assembly. If it can't be found, it is downloaded to the + /// `.nuget` directory under the source directory. + /// + /// The source directory. + private string ResolveNugetExe(string sourceDir) + { + var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location; + var directory = Path.GetDirectoryName(currentAssembly) + ?? throw new FileNotFoundException($"Directory path '{currentAssembly}' of current assembly is null"); + + var nuget = Path.Combine(directory, "nuget", "nuget.exe"); + if (File.Exists(nuget)) + { + progressMonitor.FoundNuGet(nuget); + return nuget; + } + else + { + progressMonitor.LogInfo($"Nuget.exe could not be found at {nuget}"); + return DownloadNugetExe(sourceDir); + } + } + + private string DownloadNugetExe(string sourceDir) + { + var directory = Path.Combine(sourceDir, ".nuget"); + var nuget = Path.Combine(directory, "nuget.exe"); + + // Nuget.exe already exists in the .nuget directory. + if (File.Exists(nuget)) + { + progressMonitor.FoundNuGet(nuget); + return nuget; + } + + Directory.CreateDirectory(directory); + progressMonitor.LogInfo("Attempting to download nuget.exe"); + try + { + FileUtils.DownloadFile(FileUtils.NugetExeUrl, nuget); + progressMonitor.LogInfo($"Downloaded nuget.exe to {nuget}"); + return nuget; + } + catch + { + // Download failed. + throw new FileNotFoundException("Download of nuget.exe failed."); + } + } /// /// Restore all files in a specified package. /// /// The package file. - /// Where to log progress/errors. private void RestoreNugetPackage(string package) { progressMonitor.NugetInstall(package); @@ -92,12 +112,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching if (Util.Win32.IsWindows()) { exe = nugetExe; - args = string.Format("install -OutputDirectory {0} {1}", PackageDirectory, package); + args = string.Format("install -OutputDirectory {0} {1}", packageDirectory, package); } else { exe = "mono"; - args = string.Format("{0} install -OutputDirectory {1} {2}", nugetExe, PackageDirectory, package); + args = string.Format("{0} install -OutputDirectory {1} {2}", nugetExe, packageDirectory, package); } var pi = new ProcessStartInfo(exe, args) @@ -133,7 +153,15 @@ namespace Semmle.Extraction.CSharp.DependencyFetching } } - private readonly string nugetExe; - private readonly ProgressMonitor progressMonitor; + /// + /// Download the packages to the temp folder. + /// + public void InstallPackages() + { + foreach (var package in packageFiles) + { + RestoreNugetPackage(package.FullName); + } + } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/ProgressMonitor.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/ProgressMonitor.cs index 0d940873c2c..fe4c7ef54f6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/ProgressMonitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/ProgressMonitor.cs @@ -18,7 +18,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching public void LogInfo(string message) => logger.Log(Severity.Info, message); - private void LogDebug(string message) => + public void LogDebug(string message) => logger.Log(Severity.Debug, message); private void LogError(string message) => @@ -88,6 +88,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching public void MissingNuGet() => LogError("Missing nuget.exe"); + public void FoundNuGet(string path) => + LogInfo($"Found nuget.exe at {path}"); + public void MissingDotNet() => LogError("Missing dotnet CLI"); diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj index 525b1081bff..38ba70ce285 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj @@ -6,7 +6,7 @@ Semmle.Extraction.CSharp.Standalone false false - + win-x64;linux-x64;osx-x64 enable @@ -19,7 +19,7 @@ - + diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj b/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj index a06a1df38f2..4227a1df710 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj @@ -18,7 +18,7 @@ - - + + \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.Tests/FileContent.cs b/csharp/extractor/Semmle.Extraction.Tests/FileContent.cs index 82ac04e4310..131096769e1 100644 --- a/csharp/extractor/Semmle.Extraction.Tests/FileContent.cs +++ b/csharp/extractor/Semmle.Extraction.Tests/FileContent.cs @@ -35,7 +35,7 @@ namespace Semmle.Extraction.Tests internal class TestFileContent : FileContent { public TestFileContent(List lines) : base(new ProgressMonitor(new LoggerStub()), - () => new List() { "test1.cs" }, + new List() { "test1.cs" }, new UnsafeFileReaderStub(lines)) { } } diff --git a/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj b/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj index 92bf46deb44..4e04bafc638 100644 --- a/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj +++ b/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj @@ -8,12 +8,12 @@ - - + + all runtime; build; native; contentfiles; analyzers - + diff --git a/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj b/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj index 433bb15ab1f..1c15b614ce4 100644 --- a/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj +++ b/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj @@ -12,9 +12,9 @@ TRACE;DEBUG;DEBUG_LABELS - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj b/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj index 384555bf18c..cb362f6df33 100644 --- a/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj +++ b/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj @@ -6,12 +6,12 @@ enable - - + + all runtime; build; native; contentfiles; analyzers - + diff --git a/csharp/extractor/Semmle.Util/FileUtils.cs b/csharp/extractor/Semmle.Util/FileUtils.cs index 2c43a46f0f8..90d0cc0a635 100644 --- a/csharp/extractor/Semmle.Util/FileUtils.cs +++ b/csharp/extractor/Semmle.Util/FileUtils.cs @@ -1,13 +1,17 @@ using System; using System.IO; using System.Linq; +using System.Net.Http; using System.Security.Cryptography; using System.Text; +using System.Threading.Tasks; namespace Semmle.Util { public static class FileUtils { + public const string NugetExeUrl = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"; + public static string ConvertToWindows(string path) { return path.Replace('/', '\\'); @@ -91,5 +95,20 @@ namespace Semmle.Util hex.AppendFormat("{0:x2}", b); return hex.ToString(); } + + private static async Task DownloadFileAsync(string address, string filename) + { + using var httpClient = new HttpClient(); + using var request = new HttpRequestMessage(HttpMethod.Get, address); + using var contentStream = await (await httpClient.SendAsync(request)).Content.ReadAsStreamAsync(); + using var stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true); + await contentStream.CopyToAsync(stream); + } + + /// + /// Downloads the file at to . + /// + public static void DownloadFile(string address, string fileName) => + DownloadFileAsync(address, fileName).Wait(); } } diff --git a/csharp/extractor/Semmle.Util/Semmle.Util.csproj b/csharp/extractor/Semmle.Util/Semmle.Util.csproj index 894488f9f84..b2f15484886 100644 --- a/csharp/extractor/Semmle.Util/Semmle.Util.csproj +++ b/csharp/extractor/Semmle.Util/Semmle.Util.csproj @@ -15,7 +15,7 @@ - + diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index 3d1ab3cc424..5719e05afcf 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.6.3 +version: 1.6.4-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/publish.sh b/csharp/ql/campaigns/Solorigate/publish.sh index 2d1dcfa3bfb..0c57fd6c488 100755 --- a/csharp/ql/campaigns/Solorigate/publish.sh +++ b/csharp/ql/campaigns/Solorigate/publish.sh @@ -1,7 +1,7 @@ #!/bin/sh set -e -SOLORIGATE_ROOT="$(dirname $0)" +SOLORIGATE_ROOT="$(readlink -f "$(dirname $0)")" WORKSPACE_ROOT="$SOLORIGATE_ROOT/../../../.." GRPS="solorigate,-test" diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index bbde211d1b9..2a3524ece6d 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.6.3 +version: 1.6.4-dev groups: - csharp - solorigate 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 index 968726df756..5ea4974db7f 100644 --- a/csharp/ql/integration-tests/posix-only/dotnet_test/dotnet_test.csproj +++ b/csharp/ql/integration-tests/posix-only/dotnet_test/dotnet_test.csproj @@ -8,10 +8,10 @@ - + - - + + diff --git a/csharp/ql/integration-tests/posix-only/dotnet_test_mstest/dotnet_test_mstest.csproj b/csharp/ql/integration-tests/posix-only/dotnet_test_mstest/dotnet_test_mstest.csproj index 95c7586e04e..dfa6909c44b 100644 --- a/csharp/ql/integration-tests/posix-only/dotnet_test_mstest/dotnet_test_mstest.csproj +++ b/csharp/ql/integration-tests/posix-only/dotnet_test_mstest/dotnet_test_mstest.csproj @@ -10,10 +10,10 @@ - - - - + + + + diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 2a17f2f5ba1..ba47a23065f 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 0.7.3 +version: 0.7.4-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/lib/semmle/code/csharp/Unification.qll b/csharp/ql/lib/semmle/code/csharp/Unification.qll index 7570070078f..1e01aebfb42 100644 --- a/csharp/ql/lib/semmle/code/csharp/Unification.qll +++ b/csharp/ql/lib/semmle/code/csharp/Unification.qll @@ -538,7 +538,8 @@ module Unification { * * Note: This predicate is inlined. */ - bindingset[t] + bindingset[this] + pragma[inline_late] predicate unifiable(Type t) { none() } /** @@ -546,7 +547,8 @@ module Unification { * * Note: This predicate is inlined. */ - bindingset[t] + bindingset[this] + pragma[inline_late] predicate subsumes(Type t) { none() } } @@ -554,7 +556,8 @@ module Unification { private class SingleConstraintTypeParameter extends ConstrainedTypeParameter { SingleConstraintTypeParameter() { constraintCount = 1 } - bindingset[t] + bindingset[this] + pragma[inline_late] override predicate unifiable(Type t) { exists(TTypeParameterConstraint ttc | ttc = getATypeConstraint(this) | ttc = TRefTypeConstraint() and @@ -567,7 +570,8 @@ module Unification { ) } - bindingset[t] + bindingset[this] + pragma[inline_late] override predicate subsumes(Type t) { exists(TTypeParameterConstraint ttc | ttc = getATypeConstraint(this) | ttc = TRefTypeConstraint() and @@ -585,9 +589,13 @@ module Unification { private class MultiConstraintTypeParameter extends ConstrainedTypeParameter { MultiConstraintTypeParameter() { constraintCount > 1 } - bindingset[t] + pragma[nomagic] + TTypeParameterConstraint getATypeConstraint() { result = getATypeConstraint(this) } + + bindingset[this] + pragma[inline_late] override predicate unifiable(Type t) { - forex(TTypeParameterConstraint ttc | ttc = getATypeConstraint(this) | + forex(TTypeParameterConstraint ttc | ttc = this.getATypeConstraint() | ttc = TRefTypeConstraint() and t.isRefType() or @@ -598,9 +606,10 @@ module Unification { ) } - bindingset[t] + bindingset[this] + pragma[inline_late] override predicate subsumes(Type t) { - forex(TTypeParameterConstraint ttc | ttc = getATypeConstraint(this) | + forex(TTypeParameterConstraint ttc | ttc = this.getATypeConstraint() | ttc = TRefTypeConstraint() and t.isRefType() or diff --git a/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll b/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll index ccd1e42582a..b93c59123e9 100644 --- a/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll +++ b/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll @@ -299,6 +299,12 @@ class NUnitAssertNonNullMethod extends NullnessAssertMethod, NUnitAssertMethod { override int getAnAssertionIndex(boolean b) { result = this.getAnAssertionIndex() and b = false } } +pragma[nomagic] +private predicate parameterAssertion(Assertion a, int index, Parameter p) { + strictcount(AssignableDefinition def | def.getTarget() = p) = 1 and + a.getExpr(index) = p.getAnAccess() +} + /** A method that forwards to another assertion method. */ class ForwarderAssertMethod extends AssertMethod { private Assertion a; @@ -307,10 +313,9 @@ class ForwarderAssertMethod extends AssertMethod { ForwarderAssertMethod() { p = this.getAParameter() and - strictcount(AssignableDefinition def | def.getTarget() = p) = 1 and forex(ControlFlowElement body | body = this.getBody() | bodyAsserts(this, body, a) and - a.getExpr(forwarderIndex) = p.getAnAccess() + parameterAssertion(a, forwarderIndex, p) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll index 511855b1eae..596ddde0f55 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll @@ -1159,6 +1159,7 @@ private predicate adjacentDefReachesUncertainRead( ) } +pragma[nomagic] private predicate adjacentDefReachesUncertainReadExt( DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 ) { diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll index 3acf6e4ed3a..44d23fb9d3f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll @@ -862,9 +862,7 @@ private module Internal { or Unification::subsumes(t, qualifierType) or - t.(Unification::ConstrainedTypeParameter).unifiable(qualifierType) - or - qualifierType = t.(Unification::UnconstrainedTypeParameter).getAnUltimatelySuppliedType() + qualifierType = t.(TypeParameter).getAnUltimatelySuppliedType() ) } diff --git a/csharp/ql/src/Concurrency/UnsynchronizedStaticAccess.qhelp b/csharp/ql/src/Concurrency/UnsynchronizedStaticAccess.qhelp index fae15806e93..a6a4b8a12ef 100644 --- a/csharp/ql/src/Concurrency/UnsynchronizedStaticAccess.qhelp +++ b/csharp/ql/src/Concurrency/UnsynchronizedStaticAccess.qhelp @@ -12,7 +12,7 @@ invariants.

For example, the behavior of Dictionary when a write happens concurrently with another write or a read is -undefined, and frequently leads to data corruption and can lead to ​ issues as serious as livelock. +undefined, and frequently leads to data corruption and can lead to issues as serious as livelock.

@@ -35,6 +35,6 @@ dictionary. This means that multiple threads can access the dictionary, potentia
-
  • MSDN, C# Reference: Dictionary: Thread safety.
  • +
  • MSDN, C# Reference: Dictionary: Thread safety.
  • diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index 4da21c280e1..a9d4c81c0f1 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 0.7.3 +version: 0.7.4-dev groups: - csharp - queries diff --git a/csharp/ql/test/TestUtilities/InlineExpectationsTest.qll b/csharp/ql/test/TestUtilities/InlineExpectationsTest.qll index 19e6ff17ca0..6faee89923c 100644 --- a/csharp/ql/test/TestUtilities/InlineExpectationsTest.qll +++ b/csharp/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -3,19 +3,6 @@ * See `shared/util/codeql/util/test/InlineExpectationsTest.qll` */ -private import csharp as CS private import codeql.util.test.InlineExpectationsTest - -private module Impl implements InlineExpectationsTestSig { - /** - * A class representing line comments in C# used by the InlineExpectations core code - */ - class ExpectationComment extends CS::SinglelineComment { - /** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */ - string getContents() { result = this.getText() } - } - - class Location = CS::Location; -} - +private import internal.InlineExpectationsTestImpl import Make diff --git a/csharp/ql/test/TestUtilities/InlineFlowTest.qll b/csharp/ql/test/TestUtilities/InlineFlowTest.qll index 718752a978a..1d0fe9cc067 100644 --- a/csharp/ql/test/TestUtilities/InlineFlowTest.qll +++ b/csharp/ql/test/TestUtilities/InlineFlowTest.qll @@ -1,120 +1,34 @@ /** - * Provides a simple base test for flow-related tests using inline expectations. - * - * Example for a test.ql: - * ```ql - * import csharp - * import TestUtilities.InlineFlowTest - * import DefaultFlowTest - * import PathGraph - * - * from PathNode source, PathNode sink - * where flowPath(source, sink) - * select sink, source, sink, "$@", source, source.toString() - * - * ``` - * - * To declare expectations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files. - * Example of the corresponding test file, e.g. Test.cs - * ```csharp - * public class Test - * { - * object Source() { return null; } - * string Taint() { return null; } - * void Sink(object o) { } - * - * public void test() - * { - * var s = Source(1); - * Sink(s); // $ hasValueFlow=1 - * var t = "foo" + Taint(2); - * Sink(t); // $ hasTaintFlow=2 - * } - * } - * ``` - * - * If you are only interested in value flow, then instead of importing `DefaultFlowTest`, you can import - * `ValueFlowTest`. Similarly, if you are only interested in taint flow, then instead of - * importing `DefaultFlowTest`, you can import `TaintFlowTest`. In both cases - * `DefaultFlowConfig` can be replaced by another implementation of `DataFlow::ConfigSig`. - * - * If you need more fine-grained tuning, consider implementing a test using `InlineExpectationsTest`. + * Inline flow tests for CSharp. + * See `shared/util/codeql/dataflow/test/InlineFlowTest.qll` */ import csharp -import TestUtilities.InlineExpectationsTest +private import codeql.dataflow.test.InlineFlowTest +private import semmle.code.csharp.dataflow.internal.DataFlowImplSpecific +private import semmle.code.csharp.dataflow.internal.TaintTrackingImplSpecific +private import internal.InlineExpectationsTestImpl -private predicate defaultSource(DataFlow::Node source) { - source.asExpr().(MethodCall).getTarget().getUndecoratedName() = ["Source", "Taint"] -} - -private predicate defaultSink(DataFlow::Node sink) { - exists(MethodCall mc | mc.getTarget().hasUndecoratedName("Sink") | - sink.asExpr() = mc.getAnArgument() - ) -} - -module DefaultFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { defaultSource(source) } - - predicate isSink(DataFlow::Node sink) { defaultSink(sink) } - - int fieldFlowBranchLimit() { result = 1000 } -} - -private module NoFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { none() } - - predicate isSink(DataFlow::Node sink) { none() } -} - -private string getSourceArgString(DataFlow::Node src) { - defaultSource(src) and - src.asExpr().(MethodCall).getAnArgument().getValue() = result -} - -module FlowTest { - module ValueFlow = DataFlow::Global; - - module TaintFlow = TaintTracking::Global; - - private module InlineTest implements TestSig { - string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } - - predicate hasActualResult(Location location, string element, string tag, string value) { - tag = "hasValueFlow" and - exists(DataFlow::Node src, DataFlow::Node sink | ValueFlow::flow(src, sink) | - sink.getLocation() = location and - element = sink.toString() and - if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" - ) - or - tag = "hasTaintFlow" and - exists(DataFlow::Node src, DataFlow::Node sink | - TaintFlow::flow(src, sink) and not ValueFlow::flow(src, sink) - | - sink.getLocation() = location and - element = sink.toString() and - if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" - ) - } +private module FlowTestImpl implements InputSig { + predicate defaultSource(DataFlow::Node source) { + source.asExpr().(MethodCall).getTarget().getUndecoratedName() = ["Source", "Taint"] } - import MakeTest - import DataFlow::MergePathGraph + predicate defaultSink(DataFlow::Node sink) { + exists(MethodCall mc | mc.getTarget().hasUndecoratedName("Sink") | + sink.asExpr() = mc.getAnArgument() + ) + } - predicate flowPath(PathNode source, PathNode sink) { - ValueFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) or - TaintFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) + private string getSourceArgString(DataFlow::Node src) { + defaultSource(src) and + src.asExpr().(MethodCall).getAnArgument().getValue() = result + } + + string getArgString(DataFlow::Node src, DataFlow::Node sink) { + (if exists(getSourceArgString(src)) then result = getSourceArgString(src) else result = "") and + exists(sink) } } -module DefaultFlowTest = FlowTest; - -module ValueFlowTest { - import FlowTest -} - -module TaintFlowTest { - import FlowTest -} +import InlineFlowTestMake diff --git a/csharp/ql/test/TestUtilities/internal/InlineExpectationsTestImpl.qll b/csharp/ql/test/TestUtilities/internal/InlineExpectationsTestImpl.qll new file mode 100644 index 00000000000..962ea7aa004 --- /dev/null +++ b/csharp/ql/test/TestUtilities/internal/InlineExpectationsTestImpl.qll @@ -0,0 +1,14 @@ +private import csharp as CS +private import codeql.util.test.InlineExpectationsTest + +module Impl implements InlineExpectationsTestSig { + /** + * A class representing line comments in C# used by the InlineExpectations core code + */ + class ExpectationComment extends CS::SinglelineComment { + /** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */ + string getContents() { result = this.getText() } + } + + class Location = CS::Location; +} diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index 7466125341d..7e29b9139e9 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -1,4 +1,3 @@ -failures testFailures edges | A.cs:5:17:5:28 | call to method Source : C | A.cs:6:24:6:24 | access to local variable c : C | diff --git a/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected b/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected index 2bddf573b6a..f5f0902b3a8 100644 --- a/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected @@ -1,4 +1,3 @@ -failures testFailures edges | Operator.cs:9:39:9:39 | x : C | Operator.cs:9:50:9:50 | access to parameter x : C | diff --git a/csharp/ql/test/library-tests/dataflow/patterns/PatternFlow.expected b/csharp/ql/test/library-tests/dataflow/patterns/PatternFlow.expected index f2ab31c12b3..cf6472ea6de 100644 --- a/csharp/ql/test/library-tests/dataflow/patterns/PatternFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/patterns/PatternFlow.expected @@ -1,4 +1,3 @@ -failures testFailures edges nodes diff --git a/csharp/ql/test/library-tests/dataflow/tuples/Tuples.expected b/csharp/ql/test/library-tests/dataflow/tuples/Tuples.expected index 10b9a4b66ac..95c39fd302c 100644 --- a/csharp/ql/test/library-tests/dataflow/tuples/Tuples.expected +++ b/csharp/ql/test/library-tests/dataflow/tuples/Tuples.expected @@ -1,4 +1,3 @@ -failures testFailures edges | Tuples.cs:7:18:7:34 | call to method Source : Object | Tuples.cs:10:21:10:22 | access to local variable o1 : Object | diff --git a/csharp/ql/test/query-tests/Dead Code/NonAssignedFields/options b/csharp/ql/test/query-tests/Dead Code/NonAssignedFields/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Dead Code/NonAssignedFields/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Dead Code/Tests/options b/csharp/ql/test/query-tests/Dead Code/Tests/options index 96c7b4441fe..bd9f6e49ece 100644 --- a/csharp/ql/test/query-tests/Dead Code/Tests/options +++ b/csharp/ql/test/query-tests/Dead Code/Tests/options @@ -1 +1,3 @@ -semmle-extractor-options: /r:System.Dynamic.Runtime.dll /r:System.Linq.Expressions.dll ${testdir}/../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: ${testdir}/../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs diff --git a/csharp/ql/test/query-tests/Documentation/options b/csharp/ql/test/query-tests/Documentation/options new file mode 100644 index 00000000000..77b22963f5c --- /dev/null +++ b/csharp/ql/test/query-tests/Documentation/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/EmptyBlock/options b/csharp/ql/test/query-tests/EmptyBlock/options new file mode 100644 index 00000000000..77b22963f5c --- /dev/null +++ b/csharp/ql/test/query-tests/EmptyBlock/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/CatchOfGenericException/options b/csharp/ql/test/query-tests/Language Abuse/CatchOfGenericException/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Language Abuse/CatchOfGenericException/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/ChainedIs/options b/csharp/ql/test/query-tests/Language Abuse/ChainedIs/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Language Abuse/ChainedIs/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/DubiousTypeTestOfThis/options b/csharp/ql/test/query-tests/Language Abuse/DubiousTypeTestOfThis/options index 993b83a0589..75c39b4541b 100644 --- a/csharp/ql/test/query-tests/Language Abuse/DubiousTypeTestOfThis/options +++ b/csharp/ql/test/query-tests/Language Abuse/DubiousTypeTestOfThis/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Diagnostics.Debug.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/ForeachCapture/options b/csharp/ql/test/query-tests/Language Abuse/ForeachCapture/options index dc973fda28a..75c39b4541b 100644 --- a/csharp/ql/test/query-tests/Language Abuse/ForeachCapture/options +++ b/csharp/ql/test/query-tests/Language Abuse/ForeachCapture/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Runtime.Extensions.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/MissedReadonlyOpportunity/options b/csharp/ql/test/query-tests/Language Abuse/MissedReadonlyOpportunity/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Language Abuse/MissedReadonlyOpportunity/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/MissedTernaryOpportunity/options b/csharp/ql/test/query-tests/Language Abuse/MissedTernaryOpportunity/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Language Abuse/MissedTernaryOpportunity/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/NestedIf/options b/csharp/ql/test/query-tests/Language Abuse/NestedIf/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Language Abuse/NestedIf/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/RethrowException/options b/csharp/ql/test/query-tests/Language Abuse/RethrowException/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Language Abuse/RethrowException/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/SimplifyBoolExpr/options b/csharp/ql/test/query-tests/Language Abuse/SimplifyBoolExpr/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Language Abuse/SimplifyBoolExpr/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Language Abuse/UselessIsBeforeAs/options b/csharp/ql/test/query-tests/Language Abuse/UselessIsBeforeAs/options new file mode 100644 index 00000000000..f9a3f3419c0 --- /dev/null +++ b/csharp/ql/test/query-tests/Language Abuse/UselessIsBeforeAs/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Language Abuse/UselessNullCoalescingExpression/options b/csharp/ql/test/query-tests/Language Abuse/UselessNullCoalescingExpression/options new file mode 100644 index 00000000000..f9a3f3419c0 --- /dev/null +++ b/csharp/ql/test/query-tests/Language Abuse/UselessNullCoalescingExpression/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Language Abuse/UselessUpcast/options b/csharp/ql/test/query-tests/Language Abuse/UselessUpcast/options index c281ba1ee1f..f9a3f3419c0 100644 --- a/csharp/ql/test/query-tests/Language Abuse/UselessUpcast/options +++ b/csharp/ql/test/query-tests/Language Abuse/UselessUpcast/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Linq.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Likely Bugs/BadCheckOdd/options b/csharp/ql/test/query-tests/Likely Bugs/BadCheckOdd/options index dd1744aaa2a..75c39b4541b 100644 --- a/csharp/ql/test/query-tests/Likely Bugs/BadCheckOdd/options +++ b/csharp/ql/test/query-tests/Likely Bugs/BadCheckOdd/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.Linq.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/Collections/ContainerLengthCmpOffByOne/options b/csharp/ql/test/query-tests/Likely Bugs/Collections/ContainerLengthCmpOffByOne/options new file mode 100644 index 00000000000..a5ea8b797c5 --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/Collections/ContainerLengthCmpOffByOne/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/Collections/ContainerSizeCmpZero/options b/csharp/ql/test/query-tests/Likely Bugs/Collections/ContainerSizeCmpZero/options index c4cab52ce8a..a5ea8b797c5 100644 --- a/csharp/ql/test/query-tests/Likely Bugs/Collections/ContainerSizeCmpZero/options +++ b/csharp/ql/test/query-tests/Likely Bugs/Collections/ContainerSizeCmpZero/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.Collections.dll /r:System.Diagnostics.Debug.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/DangerousNonShortCircuitLogic/options b/csharp/ql/test/query-tests/Likely Bugs/DangerousNonShortCircuitLogic/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/DangerousNonShortCircuitLogic/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/Dynamic/options b/csharp/ql/test/query-tests/Likely Bugs/Dynamic/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/Dynamic/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/EqualsArray/options b/csharp/ql/test/query-tests/Likely Bugs/EqualsArray/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/EqualsArray/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/EqualsUsesAs/options b/csharp/ql/test/query-tests/Likely Bugs/EqualsUsesAs/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/EqualsUsesAs/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/EqualsUsesIs/options b/csharp/ql/test/query-tests/Likely Bugs/EqualsUsesIs/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/EqualsUsesIs/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/HashedButNoHash/options b/csharp/ql/test/query-tests/Likely Bugs/HashedButNoHash/options index dc973fda28a..75c39b4541b 100644 --- a/csharp/ql/test/query-tests/Likely Bugs/HashedButNoHash/options +++ b/csharp/ql/test/query-tests/Likely Bugs/HashedButNoHash/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Runtime.Extensions.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/IncomparableEquals/options b/csharp/ql/test/query-tests/Likely Bugs/IncomparableEquals/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/IncomparableEquals/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/InconsistentCompareTo/options b/csharp/ql/test/query-tests/Likely Bugs/InconsistentCompareTo/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/InconsistentCompareTo/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/MishandlingJapaneseEra/options b/csharp/ql/test/query-tests/Likely Bugs/MishandlingJapaneseEra/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/MishandlingJapaneseEra/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/NestedLoopsSameVariable/options b/csharp/ql/test/query-tests/Likely Bugs/NestedLoopsSameVariable/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/NestedLoopsSameVariable/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/ObjectComparison/options b/csharp/ql/test/query-tests/Likely Bugs/ObjectComparison/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/ObjectComparison/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/RandomUsedOnce/options b/csharp/ql/test/query-tests/Likely Bugs/RandomUsedOnce/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/RandomUsedOnce/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/RecursiveEquals/options b/csharp/ql/test/query-tests/Likely Bugs/RecursiveEquals/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/RecursiveEquals/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/SelfAssignment/options b/csharp/ql/test/query-tests/Likely Bugs/SelfAssignment/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/SelfAssignment/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/StaticFieldWrittenByInstance/options b/csharp/ql/test/query-tests/Likely Bugs/StaticFieldWrittenByInstance/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/StaticFieldWrittenByInstance/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/StringBuilderCharInit/options b/csharp/ql/test/query-tests/Likely Bugs/StringBuilderCharInit/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/StringBuilderCharInit/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/UncheckedCastInEquals/options b/csharp/ql/test/query-tests/Likely Bugs/UncheckedCastInEquals/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/UncheckedCastInEquals/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Likely Bugs/UnsafeYearConstruction/options b/csharp/ql/test/query-tests/Likely Bugs/UnsafeYearConstruction/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/UnsafeYearConstruction/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/MagicConstants/options b/csharp/ql/test/query-tests/MagicConstants/options index 2d3e53846e4..77b22963f5c 100644 --- a/csharp/ql/test/query-tests/MagicConstants/options +++ b/csharp/ql/test/query-tests/MagicConstants/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.ComponentModel.Primitives.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Metrics/Files/FLinesOfCommentedCode/options b/csharp/ql/test/query-tests/Metrics/Files/FLinesOfCommentedCode/options new file mode 100644 index 00000000000..a5ea8b797c5 --- /dev/null +++ b/csharp/ql/test/query-tests/Metrics/Files/FLinesOfCommentedCode/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Metrics/RefTypes/TNumberOfFields/options b/csharp/ql/test/query-tests/Metrics/RefTypes/TNumberOfFields/options new file mode 100644 index 00000000000..a5ea8b797c5 --- /dev/null +++ b/csharp/ql/test/query-tests/Metrics/RefTypes/TNumberOfFields/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Metrics/Summaries/options b/csharp/ql/test/query-tests/Metrics/Summaries/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Metrics/Summaries/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Nullness/Implications.ql b/csharp/ql/test/query-tests/Nullness/Implications.ql index 0c185b1a2dc..8f265616646 100644 --- a/csharp/ql/test/query-tests/Nullness/Implications.ql +++ b/csharp/ql/test/query-tests/Nullness/Implications.ql @@ -2,5 +2,7 @@ import csharp import semmle.code.csharp.controlflow.Guards query predicate impliesStep(Expr e1, AbstractValue v1, Expr e2, AbstractValue v2) { + e1.fromSource() and + e2.fromSource() and Internal::impliesStep(e1, v1, e2, v2) } diff --git a/csharp/ql/test/query-tests/Nullness/options b/csharp/ql/test/query-tests/Nullness/options index ef26c0ec2cf..ca78c431249 100644 --- a/csharp/ql/test/query-tests/Nullness/options +++ b/csharp/ql/test/query-tests/Nullness/options @@ -1,2 +1,3 @@ -semmle-extractor-options: /r:System.Linq.dll /r:System.Drawing.Primitives.dll -semmle-extractor-options: ${testdir}/../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: ${testdir}/../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Performance/StringBuilderInLoop/options b/csharp/ql/test/query-tests/Performance/StringBuilderInLoop/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Performance/StringBuilderInLoop/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Performance/StringConcatenationInLoop/options b/csharp/ql/test/query-tests/Performance/StringConcatenationInLoop/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Performance/StringConcatenationInLoop/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Performance/UseTryGetValue/options b/csharp/ql/test/query-tests/Performance/UseTryGetValue/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Performance/UseTryGetValue/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/ReadOnlyContainer/options b/csharp/ql/test/query-tests/ReadOnlyContainer/options index 9ba0ece44ca..77b22963f5c 100644 --- a/csharp/ql/test/query-tests/ReadOnlyContainer/options +++ b/csharp/ql/test/query-tests/ReadOnlyContainer/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Collections.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/UseBraces/options b/csharp/ql/test/query-tests/UseBraces/options index dc973fda28a..77b22963f5c 100644 --- a/csharp/ql/test/query-tests/UseBraces/options +++ b/csharp/ql/test/query-tests/UseBraces/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Runtime.Extensions.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Useless Code/DefaultToString/DefaultToString.ql b/csharp/ql/test/query-tests/Useless Code/DefaultToString/DefaultToString.ql index 2787d7e860d..bc6401c6eb6 100644 --- a/csharp/ql/test/query-tests/Useless Code/DefaultToString/DefaultToString.ql +++ b/csharp/ql/test/query-tests/Useless Code/DefaultToString/DefaultToString.ql @@ -8,7 +8,7 @@ class MyDefaultToStringType extends DefaultToStringType { string filepath, int startline, int startcolumn, int endline, int endcolumn ) { exists(Location l | l = this.getLocation() | - if l instanceof SourceLocation + if this.fromSource() then l.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) else any(EmptyLocation el).hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) diff --git a/csharp/ql/test/query-tests/Useless Code/DefaultToString/options b/csharp/ql/test/query-tests/Useless Code/DefaultToString/options index dc973fda28a..75c39b4541b 100644 --- a/csharp/ql/test/query-tests/Useless Code/DefaultToString/options +++ b/csharp/ql/test/query-tests/Useless Code/DefaultToString/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Runtime.Extensions.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Useless Code/IntGetHashCode/options b/csharp/ql/test/query-tests/Useless Code/IntGetHashCode/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Useless Code/IntGetHashCode/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Useless Code/PointlessForwardingMethod/options b/csharp/ql/test/query-tests/Useless Code/PointlessForwardingMethod/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Useless Code/PointlessForwardingMethod/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/options b/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/Useless Code/UnusedLabel/options b/csharp/ql/test/query-tests/Useless Code/UnusedLabel/options new file mode 100644 index 00000000000..75c39b4541b --- /dev/null +++ b/csharp/ql/test/query-tests/Useless Code/UnusedLabel/options @@ -0,0 +1,2 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/csharp/ql/test/query-tests/WriteOnlyContainer/options b/csharp/ql/test/query-tests/WriteOnlyContainer/options index b4cc406c93d..77b22963f5c 100644 --- a/csharp/ql/test/query-tests/WriteOnlyContainer/options +++ b/csharp/ql/test/query-tests/WriteOnlyContainer/options @@ -1 +1,2 @@ -semmle-extractor-options: /r:System.Collections.dll /r:System.Runtime.Extensions.dll /r:System.Linq.Expressions.dll /r:System.Collections.NonGeneric.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index b96686a9307..d3765da2f89 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 0.6.3 +version: 0.6.4-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index 4ad430895b2..a625c40a9c8 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 0.6.3 +version: 0.6.4-dev groups: - go - queries diff --git a/go/ql/test/TestUtilities/InlineExpectationsTest.qll b/go/ql/test/TestUtilities/InlineExpectationsTest.qll index 808b95832ec..60b2b49da49 100644 --- a/go/ql/test/TestUtilities/InlineExpectationsTest.qll +++ b/go/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -3,20 +3,6 @@ * See `shared/util/codeql/util/test/InlineExpectationsTest.qll` */ -private import go as G private import codeql.util.test.InlineExpectationsTest - -private module Impl implements InlineExpectationsTestSig { - /** - * A class representing line comments in the Go style, including the - * preceding comment marker (`//`). - */ - class ExpectationComment extends G::Comment { - /** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */ - string getContents() { result = this.getText() } - } - - class Location = G::Location; -} - +private import internal.InlineExpectationsTestImpl import Make diff --git a/go/ql/test/TestUtilities/InlineFlowTest.qll b/go/ql/test/TestUtilities/InlineFlowTest.qll index 4f3cfc7599a..3ec43911b76 100644 --- a/go/ql/test/TestUtilities/InlineFlowTest.qll +++ b/go/ql/test/TestUtilities/InlineFlowTest.qll @@ -1,112 +1,29 @@ /** - * Provides a simple base test for flow-related tests using inline expectations. - * - * Example for a test.ql: - * ```ql - * import go - * import TestUtilities.InlineFlowTest - * import DefaultFlowTest - * import PathGraph - * - * from PathNode source, PathNode sink - * where flowPath(source, sink) - * select sink, source, sink, "$@", source, source.toString() - * ``` - * - * To declare expectations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files. - * Example of the corresponding test file, e.g. Test.go - * ```go - * func source() string { return ""; } - * func taint() string { return ""; } - * func sink(s string) { } - * - * func test() { - * s := source() - * sink(s) // $ hasValueFlow="s" - * t := "foo" + taint() - * sink(t) // $ hasTaintFlow="t" - * } - * ``` - * - * If you are only interested in value flow, then instead of importing `DefaultFlowTest`, you can import - * `ValueFlowTest`. Similarly, if you are only interested in taint flow, then instead of - * importing `DefaultFlowTest`, you can import `TaintFlowTest`. In both cases - * `DefaultFlowConfig` can be replaced by another implementation of `DataFlow::ConfigSig`. - * - * If you need more fine-grained tuning, consider implementing a test using `InlineExpectationsTest`. + * Inline flow tests for Go. + * See `shared/util/codeql/dataflow/test/InlineFlowTest.qll` */ import go -import TestUtilities.InlineExpectationsTest +private import codeql.dataflow.test.InlineFlowTest +private import semmle.go.dataflow.internal.DataFlowImplSpecific +private import semmle.go.dataflow.internal.TaintTrackingImplSpecific +private import internal.InlineExpectationsTestImpl -private predicate defaultSource(DataFlow::Node source) { - exists(Function fn | fn.hasQualifiedName(_, ["source", "taint"]) | - source = fn.getACall().getResult() - ) -} - -private predicate defaultSink(DataFlow::Node sink) { - exists(Function fn | fn.hasQualifiedName(_, "sink") | sink = fn.getACall().getAnArgument()) -} - -module DefaultFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { defaultSource(source) } - - predicate isSink(DataFlow::Node sink) { defaultSink(sink) } - - int fieldFlowBranchLimit() { result = 1000 } -} - -private module NoFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { none() } - - predicate isSink(DataFlow::Node sink) { none() } -} - -module FlowTest { - module ValueFlow = DataFlow::Global; - - module TaintFlow = TaintTracking::Global; - - private module InlineTest implements TestSig { - string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } - - predicate hasActualResult(Location location, string element, string tag, string value) { - tag = "hasValueFlow" and - exists(DataFlow::Node sink | ValueFlow::flowTo(sink) | - sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), - location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and - element = sink.toString() and - value = "\"" + sink.toString() + "\"" - ) - or - tag = "hasTaintFlow" and - exists(DataFlow::Node src, DataFlow::Node sink | - TaintFlow::flow(src, sink) and not ValueFlow::flow(src, sink) - | - sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), - location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and - element = sink.toString() and - value = "\"" + sink.toString() + "\"" - ) - } +private module FlowTestImpl implements InputSig { + predicate defaultSource(DataFlow::Node source) { + exists(Function fn | fn.hasQualifiedName(_, ["source", "taint"]) | + source = fn.getACall().getResult() + ) } - import MakeTest - import DataFlow::MergePathGraph + predicate defaultSink(DataFlow::Node sink) { + exists(Function fn | fn.hasQualifiedName(_, "sink") | sink = fn.getACall().getAnArgument()) + } - predicate flowPath(PathNode source, PathNode sink) { - ValueFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) or - TaintFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) + string getArgString(DataFlow::Node src, DataFlow::Node sink) { + exists(src) and + result = "\"" + sink.toString() + "\"" } } -module DefaultFlowTest = FlowTest; - -module ValueFlowTest { - import FlowTest -} - -module TaintFlowTest { - import FlowTest -} +import InlineFlowTestMake diff --git a/go/ql/test/TestUtilities/internal/InlineExpectationsTestImpl.qll b/go/ql/test/TestUtilities/internal/InlineExpectationsTestImpl.qll new file mode 100644 index 00000000000..a544aed8fee --- /dev/null +++ b/go/ql/test/TestUtilities/internal/InlineExpectationsTestImpl.qll @@ -0,0 +1,15 @@ +private import go as G +private import codeql.util.test.InlineExpectationsTest + +module Impl implements InlineExpectationsTestSig { + /** + * A class representing line comments in the Go style, including the + * preceding comment marker (`//`). + */ + class ExpectationComment extends G::Comment { + /** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */ + string getContents() { result = this.getText() } + } + + class Location = G::Location; +} diff --git a/go/ql/test/experimental/frameworks/CleverGo/TaintTracking.expected b/go/ql/test/experimental/frameworks/CleverGo/TaintTracking.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/experimental/frameworks/CleverGo/TaintTracking.expected +++ b/go/ql/test/experimental/frameworks/CleverGo/TaintTracking.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/experimental/frameworks/Fiber/TaintTracking.expected b/go/ql/test/experimental/frameworks/Fiber/TaintTracking.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/experimental/frameworks/Fiber/TaintTracking.expected +++ b/go/ql/test/experimental/frameworks/Fiber/TaintTracking.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/Flows.expected b/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/Flows.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/Flows.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/Flows.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ChannelField/test.expected b/go/ql/test/library-tests/semmle/go/dataflow/ChannelField/test.expected index 860170d67de..523d27be250 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ChannelField/test.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ChannelField/test.expected @@ -1,4 +1,3 @@ -failures edges | test.go:9:9:9:11 | selection of c [collection] | test.go:9:7:9:11 | <-... | | test.go:13:16:13:16 | definition of s [pointer, c, collection] | test.go:16:2:16:2 | s [pointer, c, collection] | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/completetest.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/completetest.expected index 105b7026d0c..42831abaf15 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/completetest.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/completetest.expected @@ -1,3 +1,2 @@ -failures invalidModelRow testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.expected index 105b7026d0c..42831abaf15 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.expected @@ -1,3 +1,2 @@ -failures invalidModelRow testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/GenericFunctionsAndTypes/Flows.expected b/go/ql/test/library-tests/semmle/go/dataflow/GenericFunctionsAndTypes/Flows.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/GenericFunctionsAndTypes/Flows.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/GenericFunctionsAndTypes/Flows.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/GuardingFunctions/test.expected b/go/ql/test/library-tests/semmle/go/dataflow/GuardingFunctions/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/GuardingFunctions/test.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/GuardingFunctions/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/HiddenNodes/test.expected b/go/ql/test/library-tests/semmle/go/dataflow/HiddenNodes/test.expected index b87c37b6972..2c7583cacb4 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/HiddenNodes/test.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/HiddenNodes/test.expected @@ -1,4 +1,3 @@ -failures edges | test.go:14:8:14:15 | call to source | test.go:15:34:15:35 | fi | | test.go:15:2:15:44 | ... := ...[0] | test.go:16:7:16:12 | header | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ListOfConstantsSanitizerGuards/test.expected b/go/ql/test/library-tests/semmle/go/dataflow/ListOfConstantsSanitizerGuards/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ListOfConstantsSanitizerGuards/test.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ListOfConstantsSanitizerGuards/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/PromotedFields/DataFlowConfig.expected b/go/ql/test/library-tests/semmle/go/dataflow/PromotedFields/DataFlowConfig.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/PromotedFields/DataFlowConfig.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/PromotedFields/DataFlowConfig.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/PromotedMethods/DataFlowConfig.ql b/go/ql/test/library-tests/semmle/go/dataflow/PromotedMethods/DataFlowConfig.ql index a4db3dc304d..64724e284d0 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/PromotedMethods/DataFlowConfig.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/PromotedMethods/DataFlowConfig.ql @@ -1,4 +1,5 @@ import go +import TestUtilities.InlineExpectationsTest import TestUtilities.InlineFlowTest module ValueFlow = DataFlow::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/TypeAssertions/DataFlow.expected b/go/ql/test/library-tests/semmle/go/dataflow/TypeAssertions/DataFlow.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/TypeAssertions/DataFlow.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/TypeAssertions/DataFlow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/VarArgs/Flows.expected b/go/ql/test/library-tests/semmle/go/dataflow/VarArgs/Flows.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/VarArgs/Flows.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/VarArgs/Flows.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.expected b/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/EvanphxJsonPatch/TaintFlows.expected b/go/ql/test/library-tests/semmle/go/frameworks/EvanphxJsonPatch/TaintFlows.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/EvanphxJsonPatch/TaintFlows.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/EvanphxJsonPatch/TaintFlows.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/TaintFlowsInline.expected b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/TaintFlowsInline.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/TaintFlowsInline.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/TaintFlowsInline.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/TaintFlowsInline.expected b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/TaintFlowsInline.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/TaintFlowsInline.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/TaintFlowsInline.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Protobuf/TaintFlows.expected b/go/ql/test/library-tests/semmle/go/frameworks/Protobuf/TaintFlows.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Protobuf/TaintFlows.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Protobuf/TaintFlows.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Spew/TaintFlows.expected b/go/ql/test/library-tests/semmle/go/frameworks/Spew/TaintFlows.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Spew/TaintFlows.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Spew/TaintFlows.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Zap/TaintFlows.expected b/go/ql/test/library-tests/semmle/go/frameworks/Zap/TaintFlows.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Zap/TaintFlows.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Zap/TaintFlows.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/go/ql/test/query-tests/Security/CWE-117/LogInjectionTest.expected b/go/ql/test/query-tests/Security/CWE-117/LogInjectionTest.expected index 48de9172b36..e69de29bb2d 100644 --- a/go/ql/test/query-tests/Security/CWE-117/LogInjectionTest.expected +++ b/go/ql/test/query-tests/Security/CWE-117/LogInjectionTest.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/automodel/publish.sh b/java/ql/automodel/publish.sh new file mode 100755 index 00000000000..b13570c950f --- /dev/null +++ b/java/ql/automodel/publish.sh @@ -0,0 +1,28 @@ +#!/bin/sh +set -e + +AUTOMODEL_ROOT="$(readlink -f "$(dirname $0)")" +WORKSPACE_ROOT="$AUTOMODEL_ROOT/../../.." +GRPS="automodel,-test" + +if [ -z "$CODEQL_DIST" ]; then + echo "CODEQL_DIST not set" + exit -1 +fi + +cd "$AUTOMODEL_ROOT" +echo Testing automodel queries +"${CODEQL_DIST}/codeql" test run test + +cd "$WORKSPACE_ROOT" + +echo Preparing release +"${CODEQL_DIST}/codeql" pack release --groups $GRPS + +echo Publishing automodel +"${CODEQL_DIST}/codeql" pack publish --groups $GRPS + +echo Bumping versions +"${CODEQL_DIST}/codeql" pack post-release --groups $GRPS + +echo Automodel packs successfully published. Please commit and push the version changes. diff --git a/java/ql/src/Telemetry/AutomodelAlertSinkUtil.qll b/java/ql/automodel/src/AutomodelAlertSinkUtil.qll similarity index 100% rename from java/ql/src/Telemetry/AutomodelAlertSinkUtil.qll rename to java/ql/automodel/src/AutomodelAlertSinkUtil.qll diff --git a/java/ql/src/Telemetry/AutomodelAlertSinks.ql b/java/ql/automodel/src/AutomodelAlertSinks.ql similarity index 100% rename from java/ql/src/Telemetry/AutomodelAlertSinks.ql rename to java/ql/automodel/src/AutomodelAlertSinks.ql diff --git a/java/ql/src/Telemetry/AutomodelAlertSinksPerQuery.ql b/java/ql/automodel/src/AutomodelAlertSinksPerQuery.ql similarity index 100% rename from java/ql/src/Telemetry/AutomodelAlertSinksPerQuery.ql rename to java/ql/automodel/src/AutomodelAlertSinksPerQuery.ql diff --git a/java/ql/src/Telemetry/AutomodelApplicationModeCharacteristics.qll b/java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll similarity index 100% rename from java/ql/src/Telemetry/AutomodelApplicationModeCharacteristics.qll rename to java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll diff --git a/java/ql/src/Telemetry/AutomodelApplicationModeExtractCandidates.ql b/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql similarity index 89% rename from java/ql/src/Telemetry/AutomodelApplicationModeExtractCandidates.ql rename to java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql index d58af008d87..b46a25b088d 100644 --- a/java/ql/src/Telemetry/AutomodelApplicationModeExtractCandidates.ql +++ b/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql @@ -55,7 +55,7 @@ private Endpoint getSampleForSignature( from Endpoint endpoint, string message, ApplicationModeMetadataExtractor meta, DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature, - DollarAtString input, DollarAtString isVarargsArray + DollarAtString input, DollarAtString isVarargsArray, DollarAtString alreadyAiModeled where not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u | u.appliesToEndpoint(endpoint) @@ -67,20 +67,25 @@ where // label it as a sink for one of the sink types of query B, for which it's already a known sink. This would result in // overlap between our detected sinks and the pre-existing modeling. We assume that, if a sink has already been // modeled in a MaD model, then it doesn't belong to any additional sink types, and we don't need to reexamine it. - not CharacteristicsImpl::isSink(endpoint, _, _) and + ( + not CharacteristicsImpl::isSink(endpoint, _, _) and alreadyAiModeled = "" + or + alreadyAiModeled.matches("%ai-%") and + CharacteristicsImpl::isSink(endpoint, _, alreadyAiModeled) + ) and meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, isVarargsArray) and includeAutomodelCandidate(package, type, name, signature) and // The message is the concatenation of all sink types for which this endpoint is known neither to be a sink nor to be // a non-sink, and we surface only endpoints that have at least one such sink type. message = strictconcat(AutomodelEndpointTypes::SinkType sinkType | - not CharacteristicsImpl::isKnownSink(endpoint, sinkType) and + not CharacteristicsImpl::isKnownSink(endpoint, sinkType, _) and CharacteristicsImpl::isSinkCandidate(endpoint, sinkType) | sinkType, ", " ) select endpoint.asNode(), - message + "\nrelated locations: $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", // + message + "\nrelated locations: $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", // package, "package", // type, "type", // @@ -88,4 +93,5 @@ select endpoint.asNode(), name, "name", // method name signature, "signature", // input, "input", // - isVarargsArray, "isVarargsArray" + isVarargsArray, "isVarargsArray", // + alreadyAiModeled, "alreadyAiModeled" diff --git a/java/ql/src/Telemetry/AutomodelApplicationModeExtractNegativeExamples.ql b/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql similarity index 100% rename from java/ql/src/Telemetry/AutomodelApplicationModeExtractNegativeExamples.ql rename to java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql diff --git a/java/ql/src/Telemetry/AutomodelApplicationModeExtractPositiveExamples.ql b/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql similarity index 96% rename from java/ql/src/Telemetry/AutomodelApplicationModeExtractPositiveExamples.ql rename to java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql index dac9bef0728..7341f512702 100644 --- a/java/ql/src/Telemetry/AutomodelApplicationModeExtractPositiveExamples.ql +++ b/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql @@ -22,7 +22,7 @@ where not erroneousEndpoints(endpoint, _, _, _, _, false) and meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, isVarargsArray) and // Extract positive examples of sinks belonging to the existing ATM query configurations. - CharacteristicsImpl::isKnownSink(endpoint, sinkType) and + CharacteristicsImpl::isKnownSink(endpoint, sinkType, _) and exists(CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext())) select endpoint.asNode(), sinkType + "\nrelated locations: $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", // diff --git a/java/ql/src/Telemetry/AutomodelCandidateFilter.yml b/java/ql/automodel/src/AutomodelCandidateFilter.yml similarity index 65% rename from java/ql/src/Telemetry/AutomodelCandidateFilter.yml rename to java/ql/automodel/src/AutomodelCandidateFilter.yml index 52e64d54446..c945ae3206f 100644 --- a/java/ql/src/Telemetry/AutomodelCandidateFilter.yml +++ b/java/ql/automodel/src/AutomodelCandidateFilter.yml @@ -1,5 +1,5 @@ extensions: - addsTo: - pack: codeql/java-queries + pack: codeql/java-automodel-queries extensible: automodelCandidateFilter data: [] diff --git a/java/ql/src/Telemetry/AutomodelCountGeneratedSinks.ql b/java/ql/automodel/src/AutomodelCountGeneratedSinks.ql similarity index 100% rename from java/ql/src/Telemetry/AutomodelCountGeneratedSinks.ql rename to java/ql/automodel/src/AutomodelCountGeneratedSinks.ql diff --git a/java/ql/src/Telemetry/AutomodelEndpointTypes.qll b/java/ql/automodel/src/AutomodelEndpointTypes.qll similarity index 100% rename from java/ql/src/Telemetry/AutomodelEndpointTypes.qll rename to java/ql/automodel/src/AutomodelEndpointTypes.qll diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll b/java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll similarity index 100% rename from java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll rename to java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql b/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql similarity index 84% rename from java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql rename to java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql index 028a27a9bdc..c3de8a208d5 100644 --- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql +++ b/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql @@ -18,7 +18,7 @@ private import AutomodelJavaUtil from Endpoint endpoint, string message, FrameworkModeMetadataExtractor meta, DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature, - DollarAtString input, DollarAtString parameterName + DollarAtString input, DollarAtString parameterName, DollarAtString alreadyAiModeled where not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u | u.appliesToEndpoint(endpoint) @@ -28,20 +28,25 @@ where // label it as a sink for one of the sink types of query B, for which it's already a known sink. This would result in // overlap between our detected sinks and the pre-existing modeling. We assume that, if a sink has already been // modeled in a MaD model, then it doesn't belong to any additional sink types, and we don't need to reexamine it. - not CharacteristicsImpl::isSink(endpoint, _, _) and + ( + not CharacteristicsImpl::isSink(endpoint, _, _) and alreadyAiModeled = "" + or + alreadyAiModeled.matches("%ai-%") and + CharacteristicsImpl::isSink(endpoint, _, alreadyAiModeled) + ) and meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and includeAutomodelCandidate(package, type, name, signature) and // The message is the concatenation of all sink types for which this endpoint is known neither to be a sink nor to be // a non-sink, and we surface only endpoints that have at least one such sink type. message = strictconcat(AutomodelEndpointTypes::SinkType sinkType | - not CharacteristicsImpl::isKnownSink(endpoint, sinkType) and + not CharacteristicsImpl::isKnownSink(endpoint, sinkType, _) and CharacteristicsImpl::isSinkCandidate(endpoint, sinkType) | sinkType, ", " ) select endpoint, - message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", // + message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // package, "package", // @@ -50,4 +55,5 @@ select endpoint, name, "name", // signature, "signature", // input, "input", // - parameterName, "parameterName" // + parameterName, "parameterName", // + alreadyAiModeled, "alreadyAiModeled" diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql b/java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql similarity index 100% rename from java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql rename to java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql b/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql similarity index 96% rename from java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql rename to java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql index 2547239ee91..3807de45c5a 100644 --- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql +++ b/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql @@ -22,7 +22,7 @@ where not erroneousEndpoints(endpoint, _, _, _, _, false) and meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and // Extract positive examples of sinks belonging to the existing ATM query configurations. - CharacteristicsImpl::isKnownSink(endpoint, sinkType) + CharacteristicsImpl::isKnownSink(endpoint, sinkType, _) select endpoint, sinkType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // diff --git a/java/ql/src/Telemetry/AutomodelJavaUtil.qll b/java/ql/automodel/src/AutomodelJavaUtil.qll similarity index 100% rename from java/ql/src/Telemetry/AutomodelJavaUtil.qll rename to java/ql/automodel/src/AutomodelJavaUtil.qll diff --git a/java/ql/src/Telemetry/AutomodelSharedCharacteristics.qll b/java/ql/automodel/src/AutomodelSharedCharacteristics.qll similarity index 96% rename from java/ql/src/Telemetry/AutomodelSharedCharacteristics.qll rename to java/ql/automodel/src/AutomodelSharedCharacteristics.qll index c1a9a14a10a..845f8385e5b 100644 --- a/java/ql/src/Telemetry/AutomodelSharedCharacteristics.qll +++ b/java/ql/automodel/src/AutomodelSharedCharacteristics.qll @@ -94,14 +94,15 @@ module SharedCharacteristics { /** * Holds if `sink` is a known sink of type `endpointType`. */ - predicate isKnownSink(Candidate::Endpoint sink, Candidate::EndpointType endpointType) { + predicate isKnownSink( + Candidate::Endpoint sink, Candidate::EndpointType endpointType, + EndpointCharacteristic characteristic + ) { // If the list of characteristics includes positive indicators with maximal confidence for this class, then it's a // known sink for the class. not endpointType instanceof Candidate::NegativeEndpointType and - exists(EndpointCharacteristic characteristic | - characteristic.appliesToEndpoint(sink) and - characteristic.hasImplications(endpointType, true, maximalConfidence()) - ) + characteristic.appliesToEndpoint(sink) and + characteristic.hasImplications(endpointType, true, maximalConfidence()) } /** @@ -275,15 +276,17 @@ module SharedCharacteristics { private class KnownSinkCharacteristic extends SinkCharacteristic { string madKind; Candidate::EndpointType endpointType; + string provenance; KnownSinkCharacteristic() { Candidate::isKnownKind(madKind, endpointType) and // bind "this" to a unique string differing from that of the SinkType classes - this = madKind + "-characteristic" + this = madKind + "_" + provenance + "_characteristic" and + Candidate::isSink(_, madKind, provenance) } override predicate appliesToEndpoint(Candidate::Endpoint e) { - Candidate::isSink(e, madKind, _) + Candidate::isSink(e, madKind, provenance) } override Candidate::EndpointType getSinkType() { result = endpointType } diff --git a/java/ql/src/Telemetry/AutomodelSharedGetCallable.qll b/java/ql/automodel/src/AutomodelSharedGetCallable.qll similarity index 100% rename from java/ql/src/Telemetry/AutomodelSharedGetCallable.qll rename to java/ql/automodel/src/AutomodelSharedGetCallable.qll diff --git a/java/ql/src/Telemetry/AutomodelSinkModelMrvaQueries.ql b/java/ql/automodel/src/AutomodelSinkModelMrvaQueries.ql similarity index 100% rename from java/ql/src/Telemetry/AutomodelSinkModelMrvaQueries.ql rename to java/ql/automodel/src/AutomodelSinkModelMrvaQueries.ql diff --git a/java/ql/automodel/src/qlpack.yml b/java/ql/automodel/src/qlpack.yml new file mode 100644 index 00000000000..851dbe69e82 --- /dev/null +++ b/java/ql/automodel/src/qlpack.yml @@ -0,0 +1,10 @@ +name: codeql/java-automodel-queries +version: 0.0.3-dev +groups: + - java + - automodel +dependencies: + codeql/java-all: ${workspace} +dataExtensions: + - AutomodelCandidateFilter.yml +warnOnImplicitThis: true \ No newline at end of file diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.expected b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.expected new file mode 100644 index 00000000000..77d51830c67 --- /dev/null +++ b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.expected @@ -0,0 +1,4 @@ +| Test.java:16:3:16:11 | reference | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:16:3:16:24 | set(...) | CallContext | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | +| Test.java:21:3:21:10 | supplier | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:21:3:21:16 | get(...) | CallContext | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | +| Test.java:34:4:34:11 | openPath | command-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:33:10:35:3 | newInputStream(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://false:1:1:1:1 | false | isVarargsArray | file://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | +| Test.java:53:4:53:4 | o | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:51:3:56:3 | walk(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://true:1:1:1:1 | true | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.qlref b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.qlref new file mode 100644 index 00000000000..5ea712b0239 --- /dev/null +++ b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.qlref @@ -0,0 +1 @@ +AutomodelApplicationModeExtractCandidates.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.expected b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.expected similarity index 100% rename from java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.expected rename to java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.expected diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref new file mode 100644 index 00000000000..ccd3827571e --- /dev/null +++ b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref @@ -0,0 +1 @@ +AutomodelApplicationModeExtractNegativeExamples.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.expected b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.expected similarity index 100% rename from java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.expected rename to java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.expected diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.qlref b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.qlref new file mode 100644 index 00000000000..5cf6baa1dba --- /dev/null +++ b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.qlref @@ -0,0 +1 @@ +AutomodelApplicationModeExtractPositiveExamples.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/Test.java b/java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java similarity index 93% rename from java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/Test.java rename to java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java index 1b5cea4b907..1a660f7752f 100644 --- a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/Test.java +++ b/java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java @@ -31,7 +31,7 @@ class Test { public static InputStream getInputStream(Path openPath) throws Exception { return Files.newInputStream( - openPath // positive example (known sink) + openPath // positive example (known sink), candidate ("only" ai-modeled, and useful as a candidate in regression testing) ); } @@ -56,4 +56,3 @@ class Test { ); } } - diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.expected b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.expected new file mode 100644 index 00000000000..ceeb1115c18 --- /dev/null +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.expected @@ -0,0 +1,9 @@ +| com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | MethodDoc | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | +| com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | +| com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://false:1:1:1:1 | false | subtypes | file://staticStuff:1:1:1:1 | staticStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | +| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | +| com/github/codeql/test/PublicInterface.java:4:23:4:32 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:23:4:32 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:4:23:4:32 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | +| com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://false:1:1:1:1 | false | subtypes | file://staticStuff:1:1:1:1 | staticStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | +| java/nio/file/Files.java:14:9:14:24 | out | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:14:9:14:24 | out | MethodDoc | java/nio/file/Files.java:14:9:14:24 | out | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,OutputStream):1:1:1:1 | (Path,OutputStream) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://out:1:1:1:1 | out | parameterName | file://:1:1:1:1 | | alreadyAiModeled | +| java/nio/file/Files.java:25:9:25:21 | openPath | command-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:25:9:25:21 | openPath | MethodDoc | java/nio/file/Files.java:25:9:25:21 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://openPath:1:1:1:1 | openPath | parameterName | file://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | +| java/nio/file/Files.java:26:9:26:29 | options | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:26:9:26:29 | options | MethodDoc | java/nio/file/Files.java:26:9:26:29 | options | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://options:1:1:1:1 | options | parameterName | file://:1:1:1:1 | | alreadyAiModeled | diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.qlref b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.qlref new file mode 100644 index 00000000000..e9b513032aa --- /dev/null +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.qlref @@ -0,0 +1 @@ +AutomodelFrameworkModeExtractCandidates.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.expected b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.expected similarity index 100% rename from java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.expected rename to java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.expected diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.qlref b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.qlref new file mode 100644 index 00000000000..69498caf899 --- /dev/null +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.qlref @@ -0,0 +1 @@ +AutomodelFrameworkModeExtractNegativeExamples.ql diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.expected b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.expected new file mode 100644 index 00000000000..7e8e2bbcad5 --- /dev/null +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.expected @@ -0,0 +1,2 @@ +| java/nio/file/Files.java:13:9:13:19 | source | path-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:13:9:13:19 | source | MethodDoc | java/nio/file/Files.java:13:9:13:19 | source | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,OutputStream):1:1:1:1 | (Path,OutputStream) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://source:1:1:1:1 | source | parameterName | +| java/nio/file/Files.java:25:9:25:21 | openPath | path-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:25:9:25:21 | openPath | MethodDoc | java/nio/file/Files.java:25:9:25:21 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://openPath:1:1:1:1 | openPath | parameterName | diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.qlref b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.qlref new file mode 100644 index 00000000000..fbda3f3dd37 --- /dev/null +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.qlref @@ -0,0 +1 @@ +AutomodelFrameworkModeExtractPositiveExamples.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/com/github/codeql/test/NonPublicClass.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/NonPublicClass.java similarity index 100% rename from java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/com/github/codeql/test/NonPublicClass.java rename to java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/NonPublicClass.java diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java similarity index 100% rename from java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java rename to java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java similarity index 100% rename from java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java rename to java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/java/io/File.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/io/File.java similarity index 100% rename from java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/java/io/File.java rename to java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/io/File.java diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/java/nio/file/Files.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java similarity index 59% rename from java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/java/nio/file/Files.java rename to java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java index 76bfdfcf418..4b0c75a175e 100644 --- a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/java/nio/file/Files.java +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java @@ -1,8 +1,12 @@ package java.nio.file; +import java.io.InputStream; +import java.io.FileInputStream; import java.nio.file.Path; +import java.nio.file.Paths; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.OpenOption; public class Files { public static void copy( @@ -16,4 +20,11 @@ public class Files { ) throws IOException { // ... } + + public static InputStream newInputStream( + Path openPath ,// positive example (known sink), candidate (ai-modeled, and useful as a candidate in regression testing) + OpenOption... options + ) throws IOException { + return new FileInputStream(openPath.toFile()); + } } diff --git a/java/ql/automodel/test/qlpack.yml b/java/ql/automodel/test/qlpack.yml new file mode 100644 index 00000000000..11f5ec8c192 --- /dev/null +++ b/java/ql/automodel/test/qlpack.yml @@ -0,0 +1,12 @@ +name: codeql/java-automodel-tests +version: 0.0.1-dev +groups: + - java + - automodel + - test +dependencies: + codeql/java-all: ${workspace} + codeql/java-automodel-queries: ${workspace} +extractor: java +tests: . +warnOnImplicitThis: true \ No newline at end of file diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index b00c5e7bcf5..e708ee160f2 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 0.7.3 +version: 0.7.4-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/ModelExclusions.qll b/java/ql/lib/semmle/code/java/dataflow/internal/ModelExclusions.qll index 745cf7934f0..5f1996989ad 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/ModelExclusions.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/ModelExclusions.qll @@ -27,7 +27,7 @@ class TestLibrary extends RefType { /** Holds if the given file is a test file. */ private predicate isInTestFile(File file) { file.getAbsolutePath().matches(["%/test/%", "%/guava-tests/%", "%/guava-testlib/%"]) and - not file.getAbsolutePath().matches("%/ql/test/%") // allows our test cases to work + not file.getAbsolutePath().matches(["%/ql/test/%", "%/ql/automodel/test/%"]) // allows our test cases to work } /** Holds if the given compilation unit's package is a JDK internal. */ diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index deeeccc3e41..b2a297894fa 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 0.7.3 +version: 0.7.4-dev groups: - java - queries @@ -12,5 +12,4 @@ dependencies: codeql/util: ${workspace} dataExtensions: - Telemetry/ExtractorInformation.yml - - Telemetry/AutomodelCandidateFilter.yml warnOnImplicitThis: true diff --git a/java/ql/test/TestUtilities/InlineExpectationsTest.qll b/java/ql/test/TestUtilities/InlineExpectationsTest.qll index 9470db34120..44306864a97 100644 --- a/java/ql/test/TestUtilities/InlineExpectationsTest.qll +++ b/java/ql/test/TestUtilities/InlineExpectationsTest.qll @@ -3,40 +3,6 @@ * See `shared/util/codeql/util/test/InlineExpectationsTest.qll` */ -private import java as J private import codeql.util.test.InlineExpectationsTest - -private module Impl implements InlineExpectationsTestSig { - /** - * A class representing line comments in Java, which is simply Javadoc restricted - * to EOL comments, with an extra accessor used by the InlineExpectations core code - */ - abstract class ExpectationComment extends J::Top { - /** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */ - abstract string getContents(); - } - - private class JavadocExpectationComment extends J::Javadoc, ExpectationComment { - JavadocExpectationComment() { isEolComment(this) } - - override string getContents() { result = this.getChild(0).toString() } - } - - private class KtExpectationComment extends J::KtComment, ExpectationComment { - KtExpectationComment() { this.isEolComment() } - - override string getContents() { result = this.getText().suffix(2).trim() } - } - - private class XmlExpectationComment extends ExpectationComment instanceof J::XmlComment { - override string getContents() { result = super.getText().trim() } - - override Location getLocation() { result = J::XmlComment.super.getLocation() } - - override string toString() { result = J::XmlComment.super.toString() } - } - - class Location = J::Location; -} - +private import internal.InlineExpectationsTestImpl import Make diff --git a/java/ql/test/TestUtilities/InlineFlowTest.qll b/java/ql/test/TestUtilities/InlineFlowTest.qll index 34d7f75ee20..168aaa5dc34 100644 --- a/java/ql/test/TestUtilities/InlineFlowTest.qll +++ b/java/ql/test/TestUtilities/InlineFlowTest.qll @@ -1,119 +1,33 @@ /** - * Provides a simple base test for flow-related tests using inline expectations. - * - * Example for a test.ql: - * ```ql - * import java - * import TestUtilities.InlineFlowTest - * import DefaultFlowTest - * import PathGraph - * - * from PathNode source, PathNode sink - * where flowPath(source, sink) - * select sink, source, sink, "$@", source, source.toString() - * ``` - * - * To declare expectations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files. - * Example of the corresponding test file, e.g. Test.java - * ```java - * public class Test { - * - * Object source() { return null; } - * String taint() { return null; } - * void sink(Object o) { } - * - * public void test() { - * Object s = source(); - * sink(s); // $ hasValueFlow - * String t = "foo" + taint(); - * sink(t); // $ hasTaintFlow - * } - * - * } - * ``` - * - * If you are only interested in value flow, then instead of importing `DefaultFlowTest`, you can import - * `ValueFlowTest`. Similarly, if you are only interested in taint flow, then instead of - * importing `DefaultFlowTest`, you can import `TaintFlowTest`. In both cases - * `DefaultFlowConfig` can be replaced by another implementation of `DataFlow::ConfigSig`. - * - * If you need more fine-grained tuning, consider implementing a test using `InlineExpectationsTest`. + * Inline flow tests for Java. + * See `shared/util/codeql/dataflow/test/InlineFlowTest.qll` */ +import java import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.ExternalFlow -import semmle.code.java.dataflow.TaintTracking -import TestUtilities.InlineExpectationsTest +private import codeql.dataflow.test.InlineFlowTest +private import semmle.code.java.dataflow.internal.DataFlowImplSpecific +private import semmle.code.java.dataflow.internal.TaintTrackingImplSpecific +private import internal.InlineExpectationsTestImpl -private predicate defaultSource(DataFlow::Node source) { - source.asExpr().(MethodAccess).getMethod().getName() = ["source", "taint"] -} - -private predicate defaultSink(DataFlow::Node sink) { - exists(MethodAccess ma | ma.getMethod().hasName("sink") | sink.asExpr() = ma.getAnArgument()) -} - -module DefaultFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { defaultSource(source) } - - predicate isSink(DataFlow::Node sink) { defaultSink(sink) } - - int fieldFlowBranchLimit() { result = 1000 } -} - -private module NoFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { none() } - - predicate isSink(DataFlow::Node sink) { none() } -} - -private string getSourceArgString(DataFlow::Node src) { - defaultSource(src) and - src.asExpr().(MethodAccess).getAnArgument().(StringLiteral).getValue() = result -} - -module FlowTest { - module ValueFlow = DataFlow::Global; - - module TaintFlow = TaintTracking::Global; - - private module InlineTest implements TestSig { - string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } - - predicate hasActualResult(Location location, string element, string tag, string value) { - tag = "hasValueFlow" and - exists(DataFlow::Node src, DataFlow::Node sink | ValueFlow::flow(src, sink) | - sink.getLocation() = location and - element = sink.toString() and - if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" - ) - or - tag = "hasTaintFlow" and - exists(DataFlow::Node src, DataFlow::Node sink | - TaintFlow::flow(src, sink) and not ValueFlow::flow(src, sink) - | - sink.getLocation() = location and - element = sink.toString() and - if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" - ) - } +private module FlowTestImpl implements InputSig { + predicate defaultSource(DataFlow::Node source) { + source.asExpr().(MethodAccess).getMethod().getName() = ["source", "taint"] } - import MakeTest - import DataFlow::MergePathGraph + predicate defaultSink(DataFlow::Node sink) { + exists(MethodAccess ma | ma.getMethod().hasName("sink") | sink.asExpr() = ma.getAnArgument()) + } - predicate flowPath(PathNode source, PathNode sink) { - ValueFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) or - TaintFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) + private string getSourceArgString(DataFlow::Node src) { + defaultSource(src) and + src.asExpr().(MethodAccess).getAnArgument().(StringLiteral).getValue() = result + } + + string getArgString(DataFlow::Node src, DataFlow::Node sink) { + (if exists(getSourceArgString(src)) then result = getSourceArgString(src) else result = "") and + exists(sink) } } -module DefaultFlowTest = FlowTest; - -module ValueFlowTest { - import FlowTest -} - -module TaintFlowTest { - import FlowTest -} +import InlineFlowTestMake diff --git a/java/ql/test/TestUtilities/internal/InlineExpectationsTestImpl.qll b/java/ql/test/TestUtilities/internal/InlineExpectationsTestImpl.qll new file mode 100644 index 00000000000..cd62fdb757e --- /dev/null +++ b/java/ql/test/TestUtilities/internal/InlineExpectationsTestImpl.qll @@ -0,0 +1,35 @@ +private import java as J +private import codeql.util.test.InlineExpectationsTest + +module Impl implements InlineExpectationsTestSig { + /** + * A class representing line comments in Java, which is simply Javadoc restricted + * to EOL comments, with an extra accessor used by the InlineExpectations core code + */ + abstract class ExpectationComment extends J::Top { + /** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */ + abstract string getContents(); + } + + private class JavadocExpectationComment extends J::Javadoc, ExpectationComment { + JavadocExpectationComment() { isEolComment(this) } + + override string getContents() { result = this.getChild(0).toString() } + } + + private class KtExpectationComment extends J::KtComment, ExpectationComment { + KtExpectationComment() { this.isEolComment() } + + override string getContents() { result = this.getText().suffix(2).trim() } + } + + private class XmlExpectationComment extends ExpectationComment instanceof J::XmlComment { + override string getContents() { result = super.getText().trim() } + + override Location getLocation() { result = J::XmlComment.super.getLocation() } + + override string toString() { result = J::XmlComment.super.toString() } + } + + class Location = J::Location; +} diff --git a/java/ql/test/ext/TestModels/test.expected b/java/ql/test/ext/TestModels/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/ext/TestModels/test.expected +++ b/java/ql/test/ext/TestModels/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/kotlin/library-tests/dataflow/summaries/test.expected b/java/ql/test/kotlin/library-tests/dataflow/summaries/test.expected index f72956fded3..f566914ba89 100644 --- a/java/ql/test/kotlin/library-tests/dataflow/summaries/test.expected +++ b/java/ql/test/kotlin/library-tests/dataflow/summaries/test.expected @@ -1,5 +1,3 @@ -failures -testFailures | test.kt:28:14:28:21 | getSecond(...) | Unexpected result: hasTaintFlow=a | | test.kt:35:14:35:27 | component1(...) | Unexpected result: hasTaintFlow=d | | test.kt:41:14:41:22 | getSecond(...) | Unexpected result: hasTaintFlow=e | diff --git a/java/ql/test/library-tests/dataflow/callctx/test.expected b/java/ql/test/library-tests/dataflow/callctx/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/callctx/test.expected +++ b/java/ql/test/library-tests/dataflow/callctx/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/dataflow/capture/inlinetest.expected b/java/ql/test/library-tests/dataflow/capture/inlinetest.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/capture/inlinetest.expected +++ b/java/ql/test/library-tests/dataflow/capture/inlinetest.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/dataflow/collections/containerflow.expected b/java/ql/test/library-tests/dataflow/collections/containerflow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/collections/containerflow.expected +++ b/java/ql/test/library-tests/dataflow/collections/containerflow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/dataflow/field-value/test.expected b/java/ql/test/library-tests/dataflow/field-value/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/field-value/test.expected +++ b/java/ql/test/library-tests/dataflow/field-value/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/dataflow/fluent-methods/flow.expected b/java/ql/test/library-tests/dataflow/fluent-methods/flow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/fluent-methods/flow.expected +++ b/java/ql/test/library-tests/dataflow/fluent-methods/flow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/dataflow/stream-collect/test.expected b/java/ql/test/library-tests/dataflow/stream-collect/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/stream-collect/test.expected +++ b/java/ql/test/library-tests/dataflow/stream-collect/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/dataflow/stream-read/test.expected b/java/ql/test/library-tests/dataflow/stream-read/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/stream-read/test.expected +++ b/java/ql/test/library-tests/dataflow/stream-read/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/dataflow/synth-global/test.expected b/java/ql/test/library-tests/dataflow/synth-global/test.expected index ae4c33edb3d..55e9aed2e93 100644 --- a/java/ql/test/library-tests/dataflow/synth-global/test.expected +++ b/java/ql/test/library-tests/dataflow/synth-global/test.expected @@ -1,3 +1,2 @@ -failures testFailures invalidModelRow diff --git a/java/ql/test/library-tests/dataflow/synth-global/test.ql b/java/ql/test/library-tests/dataflow/synth-global/test.ql index 53f8aa6a6f6..130169fff35 100644 --- a/java/ql/test/library-tests/dataflow/synth-global/test.ql +++ b/java/ql/test/library-tests/dataflow/synth-global/test.ql @@ -1,4 +1,5 @@ import java +import semmle.code.java.dataflow.ExternalFlow import TestUtilities.InlineFlowTest import DefaultFlowTest import ModelValidation diff --git a/java/ql/test/library-tests/dataflow/taint-format/test.expected b/java/ql/test/library-tests/dataflow/taint-format/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/taint-format/test.expected +++ b/java/ql/test/library-tests/dataflow/taint-format/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/dataflow/taint-gson/dataFlow.expected b/java/ql/test/library-tests/dataflow/taint-gson/dataFlow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/taint-gson/dataFlow.expected +++ b/java/ql/test/library-tests/dataflow/taint-gson/dataFlow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.expected b/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.expected +++ b/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/JaxWs/JaxRsFlow.expected b/java/ql/test/library-tests/frameworks/JaxWs/JaxRsFlow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/JaxWs/JaxRsFlow.expected +++ b/java/ql/test/library-tests/frameworks/JaxWs/JaxRsFlow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/asynctask/test.expected b/java/ql/test/library-tests/frameworks/android/asynctask/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/asynctask/test.expected +++ b/java/ql/test/library-tests/frameworks/android/asynctask/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/content-provider-summaries/test.expected b/java/ql/test/library-tests/frameworks/android/content-provider-summaries/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/content-provider-summaries/test.expected +++ b/java/ql/test/library-tests/frameworks/android/content-provider-summaries/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/content-provider/test.expected b/java/ql/test/library-tests/frameworks/android/content-provider/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/content-provider/test.expected +++ b/java/ql/test/library-tests/frameworks/android/content-provider/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/external-storage/test.expected b/java/ql/test/library-tests/frameworks/android/external-storage/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/external-storage/test.expected +++ b/java/ql/test/library-tests/frameworks/android/external-storage/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/flow-steps/test.expected b/java/ql/test/library-tests/frameworks/android/flow-steps/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/flow-steps/test.expected +++ b/java/ql/test/library-tests/frameworks/android/flow-steps/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/intent/test.expected b/java/ql/test/library-tests/frameworks/android/intent/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/test.expected +++ b/java/ql/test/library-tests/frameworks/android/intent/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/notification/test.expected b/java/ql/test/library-tests/frameworks/android/notification/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/notification/test.expected +++ b/java/ql/test/library-tests/frameworks/android/notification/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/slice/test.expected b/java/ql/test/library-tests/frameworks/android/slice/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/slice/test.expected +++ b/java/ql/test/library-tests/frameworks/android/slice/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.expected b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.expected +++ b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/uri/test.expected b/java/ql/test/library-tests/frameworks/android/uri/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/android/uri/test.expected +++ b/java/ql/test/library-tests/frameworks/android/uri/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/android/widget/test.expected b/java/ql/test/library-tests/frameworks/android/widget/test.expected index 5390495c737..edd61a10e55 100644 --- a/java/ql/test/library-tests/frameworks/android/widget/test.expected +++ b/java/ql/test/library-tests/frameworks/android/widget/test.expected @@ -1,3 +1,2 @@ -failures testFailures valueOf diff --git a/java/ql/test/library-tests/frameworks/apache-ant/test.expected b/java/ql/test/library-tests/frameworks/apache-ant/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/apache-ant/test.expected +++ b/java/ql/test/library-tests/frameworks/apache-ant/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/apache-collections/test.expected b/java/ql/test/library-tests/frameworks/apache-collections/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/test.expected +++ b/java/ql/test/library-tests/frameworks/apache-collections/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/apache-commons-compress/test.expected b/java/ql/test/library-tests/frameworks/apache-commons-compress/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-compress/test.expected +++ b/java/ql/test/library-tests/frameworks/apache-commons-compress/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/flow.expected b/java/ql/test/library-tests/frameworks/apache-commons-lang3/flow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/flow.expected +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/flow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/apache-http/flow.expected b/java/ql/test/library-tests/frameworks/apache-http/flow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/apache-http/flow.expected +++ b/java/ql/test/library-tests/frameworks/apache-http/flow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/gson/test.expected b/java/ql/test/library-tests/frameworks/gson/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/gson/test.expected +++ b/java/ql/test/library-tests/frameworks/gson/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/guava/generated/cache/test.expected b/java/ql/test/library-tests/frameworks/guava/generated/cache/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/guava/generated/cache/test.expected +++ b/java/ql/test/library-tests/frameworks/guava/generated/cache/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/guava/generated/collect/test.expected b/java/ql/test/library-tests/frameworks/guava/generated/collect/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/guava/generated/collect/test.expected +++ b/java/ql/test/library-tests/frameworks/guava/generated/collect/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/hudson/test.expected b/java/ql/test/library-tests/frameworks/hudson/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/hudson/test.expected +++ b/java/ql/test/library-tests/frameworks/hudson/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/jackson/test.expected b/java/ql/test/library-tests/frameworks/jackson/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/jackson/test.expected +++ b/java/ql/test/library-tests/frameworks/jackson/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/javax-json/test.expected b/java/ql/test/library-tests/frameworks/javax-json/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/javax-json/test.expected +++ b/java/ql/test/library-tests/frameworks/javax-json/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/jdk/java.io/test.expected b/java/ql/test/library-tests/frameworks/jdk/java.io/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/jdk/java.io/test.expected +++ b/java/ql/test/library-tests/frameworks/jdk/java.io/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/jdk/java.net/test.expected b/java/ql/test/library-tests/frameworks/jdk/java.net/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/jdk/java.net/test.expected +++ b/java/ql/test/library-tests/frameworks/jdk/java.net/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/jdk/java.nio.file/test.expected b/java/ql/test/library-tests/frameworks/jdk/java.nio.file/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/jdk/java.nio.file/test.expected +++ b/java/ql/test/library-tests/frameworks/jdk/java.nio.file/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/json-java/test.expected b/java/ql/test/library-tests/frameworks/json-java/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/json-java/test.expected +++ b/java/ql/test/library-tests/frameworks/json-java/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/netty/generated/test.expected b/java/ql/test/library-tests/frameworks/netty/generated/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/netty/generated/test.expected +++ b/java/ql/test/library-tests/frameworks/netty/generated/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/netty/manual/test.expected b/java/ql/test/library-tests/frameworks/netty/manual/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/netty/manual/test.expected +++ b/java/ql/test/library-tests/frameworks/netty/manual/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/okhttp/test.expected b/java/ql/test/library-tests/frameworks/okhttp/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/okhttp/test.expected +++ b/java/ql/test/library-tests/frameworks/okhttp/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/okhttp/test.ql b/java/ql/test/library-tests/frameworks/okhttp/test.ql index 04cb3e7f7ac..8c988c1f0da 100644 --- a/java/ql/test/library-tests/frameworks/okhttp/test.ql +++ b/java/ql/test/library-tests/frameworks/okhttp/test.ql @@ -1,5 +1,6 @@ import java import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.ExternalFlow import TestUtilities.InlineFlowTest module OkHttpFlowConfig implements DataFlow::ConfigSig { diff --git a/java/ql/test/library-tests/frameworks/play/test.expected b/java/ql/test/library-tests/frameworks/play/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/play/test.expected +++ b/java/ql/test/library-tests/frameworks/play/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/rabbitmq/FlowTest.expected b/java/ql/test/library-tests/frameworks/rabbitmq/FlowTest.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/rabbitmq/FlowTest.expected +++ b/java/ql/test/library-tests/frameworks/rabbitmq/FlowTest.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/ratpack/flow.expected b/java/ql/test/library-tests/frameworks/ratpack/flow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/ratpack/flow.expected +++ b/java/ql/test/library-tests/frameworks/ratpack/flow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/retrofit/test.expected b/java/ql/test/library-tests/frameworks/retrofit/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/retrofit/test.expected +++ b/java/ql/test/library-tests/frameworks/retrofit/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/retrofit/test.ql b/java/ql/test/library-tests/frameworks/retrofit/test.ql index 0abbff1f958..e7f90fc2c0b 100644 --- a/java/ql/test/library-tests/frameworks/retrofit/test.ql +++ b/java/ql/test/library-tests/frameworks/retrofit/test.ql @@ -1,5 +1,6 @@ import java import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.ExternalFlow import TestUtilities.InlineFlowTest module FlowConfig implements DataFlow::ConfigSig { diff --git a/java/ql/test/library-tests/frameworks/spring/beans/test.expected b/java/ql/test/library-tests/frameworks/spring/beans/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/beans/test.expected +++ b/java/ql/test/library-tests/frameworks/spring/beans/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/cache/test.expected b/java/ql/test/library-tests/frameworks/spring/cache/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/cache/test.expected +++ b/java/ql/test/library-tests/frameworks/spring/cache/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/context/flow.expected b/java/ql/test/library-tests/frameworks/spring/context/flow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/context/flow.expected +++ b/java/ql/test/library-tests/frameworks/spring/context/flow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/controller/test.expected b/java/ql/test/library-tests/frameworks/spring/controller/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/controller/test.expected +++ b/java/ql/test/library-tests/frameworks/spring/controller/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/data/test.expected b/java/ql/test/library-tests/frameworks/spring/data/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/data/test.expected +++ b/java/ql/test/library-tests/frameworks/spring/data/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/http/flow.expected b/java/ql/test/library-tests/frameworks/spring/http/flow.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/http/flow.expected +++ b/java/ql/test/library-tests/frameworks/spring/http/flow.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/ui/test.expected b/java/ql/test/library-tests/frameworks/spring/ui/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/ui/test.expected +++ b/java/ql/test/library-tests/frameworks/spring/ui/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/util/test.expected b/java/ql/test/library-tests/frameworks/spring/util/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/util/test.expected +++ b/java/ql/test/library-tests/frameworks/spring/util/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/validation/test.expected b/java/ql/test/library-tests/frameworks/spring/validation/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/validation/test.expected +++ b/java/ql/test/library-tests/frameworks/spring/validation/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/webmultipart/test.expected b/java/ql/test/library-tests/frameworks/spring/webmultipart/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/webmultipart/test.expected +++ b/java/ql/test/library-tests/frameworks/spring/webmultipart/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/spring/webutil/test.expected b/java/ql/test/library-tests/frameworks/spring/webutil/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/spring/webutil/test.expected +++ b/java/ql/test/library-tests/frameworks/spring/webutil/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/stapler/test.expected b/java/ql/test/library-tests/frameworks/stapler/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/stapler/test.expected +++ b/java/ql/test/library-tests/frameworks/stapler/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/stream/test.expected b/java/ql/test/library-tests/frameworks/stream/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/stream/test.expected +++ b/java/ql/test/library-tests/frameworks/stream/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/frameworks/thymeleaf/test.expected b/java/ql/test/library-tests/frameworks/thymeleaf/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/frameworks/thymeleaf/test.expected +++ b/java/ql/test/library-tests/frameworks/thymeleaf/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/logging/test.expected b/java/ql/test/library-tests/logging/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/logging/test.expected +++ b/java/ql/test/library-tests/logging/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/optional/test.expected b/java/ql/test/library-tests/optional/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/optional/test.expected +++ b/java/ql/test/library-tests/optional/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/paths/test.expected b/java/ql/test/library-tests/paths/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/paths/test.expected +++ b/java/ql/test/library-tests/paths/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/pathsanitizer/test.expected b/java/ql/test/library-tests/pathsanitizer/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/pathsanitizer/test.expected +++ b/java/ql/test/library-tests/pathsanitizer/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/regex/test.expected b/java/ql/test/library-tests/regex/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/regex/test.expected +++ b/java/ql/test/library-tests/regex/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/library-tests/scanner/test.expected b/java/ql/test/library-tests/scanner/test.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/library-tests/scanner/test.expected +++ b/java/ql/test/library-tests/scanner/test.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.expected b/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.expected deleted file mode 100644 index 5f946f49d19..00000000000 --- a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.expected +++ /dev/null @@ -1,3 +0,0 @@ -| Test.java:16:3:16:11 | reference | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | Test.java:16:3:16:24 | set(...) | CallContext | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://false:1:1:1:1 | false | isVarargsArray | -| Test.java:21:3:21:10 | supplier | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | Test.java:21:3:21:16 | get(...) | CallContext | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://false:1:1:1:1 | false | isVarargsArray | -| Test.java:53:4:53:4 | o | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | Test.java:51:3:56:3 | walk(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://true:1:1:1:1 | true | isVarargsArray | diff --git a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.qlref b/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.qlref deleted file mode 100644 index b97c87be55f..00000000000 --- a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/AutomodelApplicationModeExtractCandidates.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref b/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref deleted file mode 100644 index 43610d3cc1a..00000000000 --- a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/AutomodelApplicationModeExtractNegativeExamples.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.qlref b/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.qlref deleted file mode 100644 index 585a78f94f9..00000000000 --- a/java/ql/test/query-tests/Telemetry/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/AutomodelApplicationModeExtractPositiveExamples.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.expected b/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.expected deleted file mode 100644 index 6fc82461869..00000000000 --- a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.expected +++ /dev/null @@ -1,7 +0,0 @@ -| com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | MethodDoc | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://this:1:1:1:1 | this | parameterName | -| com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName | -| com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://false:1:1:1:1 | false | subtypes | file://staticStuff:1:1:1:1 | staticStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName | -| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://this:1:1:1:1 | this | parameterName | -| com/github/codeql/test/PublicInterface.java:4:23:4:32 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:23:4:32 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:4:23:4:32 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName | -| com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://false:1:1:1:1 | false | subtypes | file://staticStuff:1:1:1:1 | staticStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName | -| java/nio/file/Files.java:10:9:10:24 | out | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:10:9:10:24 | out | MethodDoc | java/nio/file/Files.java:10:9:10:24 | out | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,OutputStream):1:1:1:1 | (Path,OutputStream) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://out:1:1:1:1 | out | parameterName | diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.qlref b/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.qlref deleted file mode 100644 index e68551eb3ec..00000000000 --- a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/AutomodelFrameworkModeExtractCandidates.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.qlref b/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.qlref deleted file mode 100644 index d58a0997fdc..00000000000 --- a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.expected b/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.expected deleted file mode 100644 index b3326654de1..00000000000 --- a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.expected +++ /dev/null @@ -1 +0,0 @@ -| java/nio/file/Files.java:9:9:9:19 | source | path-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:9:9:9:19 | source | MethodDoc | java/nio/file/Files.java:9:9:9:19 | source | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,OutputStream):1:1:1:1 | (Path,OutputStream) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://source:1:1:1:1 | source | parameterName | diff --git a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.qlref b/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.qlref deleted file mode 100644 index ae52dc66496..00000000000 --- a/java/ql/test/query-tests/Telemetry/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql diff --git a/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.expected b/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.expected +++ b/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.expected b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.expected +++ b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.expected b/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.expected +++ b/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.expected b/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.expected +++ b/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.expected b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.expected +++ b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.expected b/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.expected +++ b/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.expected b/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.expected +++ b/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-611/XXE.expected b/java/ql/test/query-tests/security/CWE-611/XXE.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-611/XXE.expected +++ b/java/ql/test/query-tests/security/CWE-611/XXE.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.expected b/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.expected +++ b/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql b/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql index c1bc2049c76..16e5c219aa9 100644 --- a/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql +++ b/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql @@ -1,5 +1,4 @@ import java -import TestUtilities.InlineExpectationsTest import TestUtilities.InlineFlowTest import semmle.code.java.security.RsaWithoutOaepQuery import TaintFlowTest diff --git a/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.expected b/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.expected index 48de9172b36..e69de29bb2d 100644 --- a/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.expected +++ b/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.expected @@ -1,2 +0,0 @@ -failures -testFailures diff --git a/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql b/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql index cf7e46b6e8e..87d685d1da9 100644 --- a/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql +++ b/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql @@ -1,5 +1,4 @@ import java import semmle.code.java.security.AndroidSensitiveCommunicationQuery -import TestUtilities.InlineExpectationsTest import TestUtilities.InlineFlowTest import TaintFlowTest diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index a9ec4943f64..d65eefd366c 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 0.7.3 +version: 0.7.4-dev groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index ba039f530a5..04ee9ae6135 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 0.7.3 +version: 0.7.4-dev groups: - javascript - queries diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index 6775f70b462..0c423deb64d 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/suite-helpers -version: 0.6.3 +version: 0.6.4-dev groups: shared warnOnImplicitThis: true diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index d62a5633439..cac5d51e2e4 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 0.10.3 +version: 0.10.4-dev groups: python dbscheme: semmlecode.python.dbscheme extractor: python @@ -13,5 +13,5 @@ dependencies: codeql/util: ${workspace} codeql/yaml: ${workspace} dataExtensions: - - semmle/python/frameworks/**/model.yml + - semmle/python/frameworks/**/*.model.yml warnOnImplicitThis: true diff --git a/python/ql/lib/semmle/python/frameworks/Flask.qll b/python/ql/lib/semmle/python/frameworks/Flask.qll index fd611e146f4..9c2e6cf08ed 100644 --- a/python/ql/lib/semmle/python/frameworks/Flask.qll +++ b/python/ql/lib/semmle/python/frameworks/Flask.qll @@ -179,7 +179,13 @@ module Flask { * - https://flask.palletsprojects.com/en/2.2.x/api/#flask.json.jsonify */ private class FlaskJsonifyCall extends InstanceSource, DataFlow::CallCfgNode { - FlaskJsonifyCall() { this = API::moduleImport("flask").getMember("jsonify").getACall() } + FlaskJsonifyCall() { + this = API::moduleImport("flask").getMember("jsonify").getACall() + or + this = API::moduleImport("flask").getMember("json").getMember("jsonify").getACall() + or + this = FlaskApp::instance().getMember("json").getMember("response").getACall() + } override DataFlow::Node getBody() { result in [this.getArg(_), this.getArgByName(_)] } @@ -453,7 +459,8 @@ module Flask { FlaskRouteHandlerReturn() { exists(Function routeHandler | routeHandler = any(FlaskRouteSetup rs).getARequestHandler() and - node = routeHandler.getAReturnValueFlowNode() + node = routeHandler.getAReturnValueFlowNode() and + not this instanceof Flask::Response::InstanceSource ) } diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/model.yml b/python/ql/lib/semmle/python/frameworks/data/internal/empty.model.yml similarity index 100% rename from python/ql/lib/semmle/python/frameworks/data/internal/model.yml rename to python/ql/lib/semmle/python/frameworks/data/internal/empty.model.yml diff --git a/python/ql/lib/semmle/python/regexp/internal/ParseRegExp.qll b/python/ql/lib/semmle/python/regexp/internal/ParseRegExp.qll index 52fa85ded56..81eff018aff 100644 --- a/python/ql/lib/semmle/python/regexp/internal/ParseRegExp.qll +++ b/python/ql/lib/semmle/python/regexp/internal/ParseRegExp.qll @@ -683,6 +683,15 @@ class RegExp extends Expr instanceof StrConst { * Holds if a parse mode starts between `start` and `end`. */ private predicate flag_group_start(int start, int end) { + this.flag_group_start_no_modes(start, _) and + end = max(int i | this.mode_character(start, i) | i + 1) + } + + /** + * Holds if the initial part of a parse mode, not containing any + * mode characters is between `start` and `end`. + */ + private predicate flag_group_start_no_modes(int start, int end) { this.isGroupStart(start) and this.getChar(start + 1) = "?" and this.getChar(start + 2) in ["i", "L", "m", "s", "u", "x"] and @@ -690,17 +699,27 @@ class RegExp extends Expr instanceof StrConst { } /** - * Holds if a parse mode group is between `start` and `end`, and includes the - * mode flag `c`. For example the following span, with mode flag `i`: + * Holds if `pos` contains a mo character from the + * flag group starting at `start`. + */ + private predicate mode_character(int start, int pos) { + this.flag_group_start_no_modes(start, pos) + or + this.mode_character(start, pos - 1) and + this.getChar(pos) in ["i", "L", "m", "s", "u", "x"] + } + + /** + * Holds if a parse mode group includes the mode flag `c`. + * For example the following parse mode group, with mode flag `i`: * ``` * (?i) * ``` */ - private predicate flag_group(int start, int end, string c) { - exists(int inStart, int inEnd | - this.flag_group_start(start, inStart) and - this.groupContents(start, end, inStart, inEnd) and - this.getChar([inStart .. inEnd - 1]) = c + private predicate flag(string c) { + exists(int pos | + this.mode_character(_, pos) and + this.getChar(pos) = c ) } @@ -709,7 +728,7 @@ class RegExp extends Expr instanceof StrConst { * it is defined by a prefix. */ string getModeFromPrefix() { - exists(string c | this.flag_group(_, _, c) | + exists(string c | this.flag(c) | c = "i" and result = "IGNORECASE" or c = "L" and result = "LOCALE" diff --git a/python/ql/lib/semmle/python/security/dataflow/LogInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/LogInjectionCustomizations.qll index 037ffbd0949..b90dedb899f 100644 --- a/python/ql/lib/semmle/python/security/dataflow/LogInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/LogInjectionCustomizations.qll @@ -47,7 +47,35 @@ module LogInjection { * A logging operation, considered as a flow sink. */ class LoggingAsSink extends Sink { - LoggingAsSink() { this = any(Logging write).getAnInput() } + LoggingAsSink() { + this = any(Logging write).getAnInput() and + // since the inner implementation of the `logging.Logger.warn` function is + // ```py + // class Logger: + // def warn(self, msg, *args, **kwargs): + // warnings.warn("The 'warn' method is deprecated, " + // "use 'warning' instead", DeprecationWarning, 2) + // self.warning(msg, *args, **kwargs) + // ``` + // any time we would report flow to such a logging sink, we can ALSO report + // the flow to the `self.warning` sink -- obviously we don't want that. + // + // However, simply removing taint edges out of a sink is not a good enough solution, + // since we would only flag one of the `logging.info` calls in the following example + // due to use-use flow + // ```py + // logger.warn(user_controlled) + // logger.warn(user_controlled) + // ``` + // + // The same approach is used in the command injection query. + not exists(Module loggingInit | + loggingInit.getName() = "logging.__init__" and + this.getScope().getEnclosingModule() = loggingInit and + // do allow this call if we're analyzing logging/__init__.py as part of CPython though + not exists(loggingInit.getFile().getRelativePath()) + ) + } } /** diff --git a/python/ql/src/change-notes/2023-08-29-fixed-jsonify-xss-fp.md b/python/ql/src/change-notes/2023-08-29-fixed-jsonify-xss-fp.md new file mode 100644 index 00000000000..8268f296606 --- /dev/null +++ b/python/ql/src/change-notes/2023-08-29-fixed-jsonify-xss-fp.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Improved _Reflected server-side cross-site scripting_ (`py/reflective-xss`) query to not alert on data passed to `flask.jsonify`. Since these HTTP responses are returned with mime-type `application/json`, they do not pose a security risk for XSS. diff --git a/python/ql/src/experimental/Security/CWE-074/TemplateConstructionConcept.qll b/python/ql/src/experimental/Security/CWE-074/TemplateConstructionConcept.qll new file mode 100644 index 00000000000..a20babf15eb --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-074/TemplateConstructionConcept.qll @@ -0,0 +1,159 @@ +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.ApiGraphs + +/** + * A data-flow node that constructs a template. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `TemplateConstruction::Range` instead. + */ +class TemplateConstruction extends DataFlow::Node instanceof TemplateConstruction::Range { + /** Gets the argument that specifies the template source. */ + DataFlow::Node getSourceArg() { result = super.getSourceArg() } +} + +/** Provides a class for modeling new system-command execution APIs. */ +module TemplateConstruction { + /** + * A data-flow node that constructs a template. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `TemplateConstruction` instead. + */ + abstract class Range extends DataFlow::Node { + /** Gets the argument that specifies the template source. */ + abstract DataFlow::Node getSourceArg(); + } +} + +// ----------------------------------------------------------------------------- +/** A call to `airspeed.Template`. */ +class AirspeedTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + AirspeedTemplateConstruction() { + this = API::moduleImport("airspeed").getMember("Template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `bottle.SimpleTemplate`. */ +class BottleSimpleTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + BottleSimpleTemplateConstruction() { + this = API::moduleImport("bottle").getMember("SimpleTemplate").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `bottle.template`. */ +class BottleTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + BottleTemplateConstruction() { + this = API::moduleImport("bottle").getMember("template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `chameleon.PageTemplate`. */ +class ChameleonTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + ChameleonTemplateConstruction() { + this = API::moduleImport("chameleon").getMember("PageTemplate").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `Cheetah.Template.Template`. */ +class CheetahTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + CheetahTemplateConstruction() { + this = + API::moduleImport("Cheetah") + .getMember("Template") + .getMember("Template") + .getASubclass*() + .getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `chevron.render`. */ +class ChevronRenderConstruction extends TemplateConstruction::Range, API::CallNode { + ChevronRenderConstruction() { this = API::moduleImport("chevron").getMember("render").getACall() } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `django.template.Template` */ +class DjangoTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + DjangoTemplateConstruction() { + this = API::moduleImport("django").getMember("template").getMember("Template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +// TODO: support django.template.engines["django"]].from_string +/** A call to `flask.render_template_string`. */ +class FlaskTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + FlaskTemplateConstruction() { + this = API::moduleImport("flask").getMember("render_template_string").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `genshi.template.TextTemplate`. */ +class GenshiTextTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + GenshiTextTemplateConstruction() { + this = API::moduleImport("genshi").getMember("template").getMember("TextTemplate").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `genshi.template.MarkupTemplate` */ +class GenshiMarkupTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + GenshiMarkupTemplateConstruction() { + this = API::moduleImport("genshi").getMember("template").getMember("MarkupTemplate").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `jinja2.Template`. */ +class Jinja2TemplateConstruction extends TemplateConstruction::Range, API::CallNode { + Jinja2TemplateConstruction() { + this = API::moduleImport("jinja2").getMember("Template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `jinja2.from_string`. */ +class Jinja2FromStringConstruction extends TemplateConstruction::Range, API::CallNode { + Jinja2FromStringConstruction() { + this = API::moduleImport("jinja2").getMember("from_string").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `mako.template.Template`. */ +class MakoTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + MakoTemplateConstruction() { + this = API::moduleImport("mako").getMember("template").getMember("Template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `trender.TRender`. */ +class TRenderTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + TRenderTemplateConstruction() { + this = API::moduleImport("trender").getMember("TRender").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} diff --git a/python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql b/python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql index cbc3536ad7d..a10ad09a6ac 100644 --- a/python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql +++ b/python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql @@ -11,25 +11,10 @@ */ import python -import semmle.python.security.Paths -/* Sources */ -import semmle.python.web.HttpRequest -/* Sinks */ -import experimental.semmle.python.templates.Ssti -/* Flow */ -import semmle.python.security.strings.Untrusted +import TemplateInjectionQuery +import TemplateInjectionFlow::PathGraph -class TemplateInjectionConfiguration extends TaintTracking::Configuration { - TemplateInjectionConfiguration() { this = "Template injection configuration" } - - deprecated override predicate isSource(TaintTracking::Source source) { - source instanceof HttpRequestTaintSource - } - - deprecated override predicate isSink(TaintTracking::Sink sink) { sink instanceof SSTISink } -} - -from TemplateInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink -where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "This Template depends on $@.", src.getSource(), - "a user-provided value" +from TemplateInjectionFlow::PathNode source, TemplateInjectionFlow::PathNode sink +where TemplateInjectionFlow::flowPath(source, sink) +select sink.getNode(), source, sink, "This Template depends on $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/experimental/Security/CWE-074/TemplateInjectionCustomizations.qll b/python/ql/src/experimental/Security/CWE-074/TemplateInjectionCustomizations.qll new file mode 100644 index 00000000000..dcd6c184861 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-074/TemplateInjectionCustomizations.qll @@ -0,0 +1,51 @@ +/** + * Provides default sources, sinks and sanitizers for detecting + * "template injection" + * vulnerabilities, as well as extension points for adding your own. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.Concepts +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.BarrierGuards +private import TemplateConstructionConcept + +/** + * Provides default sources, sinks and sanitizers for detecting + * "template injection" + * vulnerabilities, as well as extension points for adding your own. + */ +module TemplateInjection { + /** + * A data flow source for "template injection" vulnerabilities. + */ + abstract class Source extends DataFlow::Node { } + + /** + * A data flow sink for "template injection" vulnerabilities. + */ + abstract class Sink extends DataFlow::Node { } + + /** + * A sanitizer for "template injection" vulnerabilities. + */ + abstract class Sanitizer extends DataFlow::Node { } + + /** + * A source of remote user input, considered as a flow source. + */ + class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { } + + /** + * A SQL statement of a SQL construction, considered as a flow sink. + */ + class TemplateConstructionAsSink extends Sink { + TemplateConstructionAsSink() { this = any(TemplateConstruction c).getSourceArg() } + } + + /** + * A comparison with a constant string, considered as a sanitizer-guard. + */ + class StringConstCompareAsSanitizerGuard extends Sanitizer, StringConstCompareBarrier { } +} diff --git a/python/ql/src/experimental/Security/CWE-074/TemplateInjectionQuery.qll b/python/ql/src/experimental/Security/CWE-074/TemplateInjectionQuery.qll new file mode 100644 index 00000000000..111485e2602 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-074/TemplateInjectionQuery.qll @@ -0,0 +1,18 @@ +/** + * Provides a taint-tracking configuration for detecting "template injection" vulnerabilities. + */ + +private import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import TemplateInjectionCustomizations::TemplateInjection + +module TemplateInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof Source } + + predicate isSink(DataFlow::Node node) { node instanceof Sink } + + predicate isBarrierIn(DataFlow::Node node) { node instanceof Sanitizer } +} + +module TemplateInjectionFlow = TaintTracking::Global; diff --git a/python/ql/src/experimental/Security/CWE-091/Xslt.ql b/python/ql/src/experimental/Security/CWE-091/Xslt.ql deleted file mode 100644 index 77f405f5f5a..00000000000 --- a/python/ql/src/experimental/Security/CWE-091/Xslt.ql +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @name XSLT query built from user-controlled sources - * @description Building a XSLT query from user-controlled sources is vulnerable to insertion of - * malicious XSLT code by the user. - * @kind path-problem - * @problem.severity error - * @precision high - * @id py/xslt-injection - * @tags security - * experimental - * external/cwe/cwe-643 - */ - -import python -import semmle.python.security.Paths -/* Sources */ -import semmle.python.web.HttpRequest -/* Sinks */ -import experimental.semmle.python.security.injection.XSLT - -class XsltInjectionConfiguration extends TaintTracking::Configuration { - XsltInjectionConfiguration() { this = "XSLT injection configuration" } - - deprecated override predicate isSource(TaintTracking::Source source) { - source instanceof HttpRequestTaintSource - } - - deprecated override predicate isSink(TaintTracking::Sink sink) { - sink instanceof XSLTInjection::XSLTInjectionSink - } -} - -from XsltInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink -where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "This XSLT query depends on $@.", src.getSource(), - "a user-provided value" diff --git a/python/ql/src/experimental/Security/CWE-091/XsltConcept.qll b/python/ql/src/experimental/Security/CWE-091/XsltConcept.qll new file mode 100644 index 00000000000..e1d5188a5cb --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-091/XsltConcept.qll @@ -0,0 +1,110 @@ +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.ApiGraphs + +/** + * A data-flow node that constructs a XSLT transformer. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `TemplateConstruction::Range` instead. + */ +class XsltConstruction extends DataFlow::Node instanceof XsltConstruction::Range { + /** Gets the argument that specifies the XSLT transformer. */ + DataFlow::Node getXsltArg() { result = super.getXsltArg() } +} + +/** Provides a class for modeling new system-command execution APIs. */ +module XsltConstruction { + /** + * A data-flow node that constructs a XSLT transformer. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `XsltConstruction` instead. + */ + abstract class Range extends DataFlow::Node { + /** Gets the argument that specifies the XSLT transformer. */ + abstract DataFlow::Node getXsltArg(); + } +} + +/** + * A data-flow node that executes a XSLT transformer. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `TemplateConstruction::Range` instead. + */ +class XsltExecution extends DataFlow::Node instanceof XsltExecution::Range { + /** Gets the argument that specifies the XSLT transformer. */ + DataFlow::Node getXsltArg() { result = super.getXsltArg() } +} + +/** Provides a class for modeling new system-command execution APIs. */ +module XsltExecution { + /** + * A data-flow node that executes a XSLT transformer. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `XsltExecution` instead. + */ + abstract class Range extends DataFlow::Node { + /** Gets the argument that specifies the XSLT transformer. */ + abstract DataFlow::Node getXsltArg(); + } +} + +// ----------------------------------------------------------------------------- +/** + * A call to `lxml.etree.XSLT`. + * + * ```py + * from lxml import etree + * xslt_tree = etree.parse(...) + * doc = etree.parse(...) + * transform = etree.XSLT(xslt_tree) + * result = transform(doc) + * ``` + */ +class LxmlEtreeXsltCall extends XsltConstruction::Range, API::CallNode { + LxmlEtreeXsltCall() { + this = API::moduleImport("lxml").getMember("etree").getMember("XSLT").getACall() + } + + override DataFlow::Node getXsltArg() { result = this.getParameter(0, "xslt_input").asSink() } +} + +/** + * A call to `.xslt` on an lxml ElementTree object. + * + * ```py + * from lxml import etree + * xslt_tree = etree.parse(...) + * doc = etree.parse(...) + * result = doc.xslt(xslt_tree) + * ``` + */ +class XsltAttributeCall extends XsltExecution::Range, API::CallNode { + XsltAttributeCall() { this = elementTreeConstruction(_).getReturn().getMember("xslt").getACall() } + + override DataFlow::Node getXsltArg() { result = this.getParameter(0, "_xslt").asSink() } +} + +// ----------------------------------------------------------------------------- +API::CallNode elementTreeConstruction(DataFlow::Node inputArg) { + // TODO: If we could, would be nice to model this as flow-summaries. But I'm not sure if we actually can :thinking: + // see https://lxml.de/api/lxml.etree-module.html#fromstring + result = API::moduleImport("lxml").getMember("etree").getMember("fromstring").getACall() and + inputArg = result.getParameter(0, "text").asSink() + or + // see https://lxml.de/api/lxml.etree-module.html#fromstringlist + result = API::moduleImport("lxml").getMember("etree").getMember("fromstringlist").getACall() and + inputArg = result.getParameter(0, "strings").asSink() + or + // TODO: technically we should treat parse differently, since it takes a file as argument + // see https://lxml.de/api/lxml.etree-module.html#parse + result = API::moduleImport("lxml").getMember("etree").getMember("parse").getACall() and + inputArg = result.getParameter(0, "source").asSink() + or + // see https://lxml.de/api/lxml.etree-module.html#XML + result = API::moduleImport("lxml").getMember("etree").getMember("XML").getACall() and + inputArg = result.getParameter(0, "text").asSink() +} diff --git a/python/ql/src/experimental/Security/CWE-091/Xslt.qhelp b/python/ql/src/experimental/Security/CWE-091/XsltInjection.qhelp similarity index 100% rename from python/ql/src/experimental/Security/CWE-091/Xslt.qhelp rename to python/ql/src/experimental/Security/CWE-091/XsltInjection.qhelp diff --git a/python/ql/src/experimental/Security/CWE-091/XsltInjection.ql b/python/ql/src/experimental/Security/CWE-091/XsltInjection.ql new file mode 100644 index 00000000000..ca6892269e5 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-091/XsltInjection.ql @@ -0,0 +1,21 @@ +/** + * @name XSLT query built from user-controlled sources + * @description Building a XSLT query from user-controlled sources is vulnerable to insertion of + * malicious XSLT code by the user. + * @kind path-problem + * @problem.severity error + * @precision high + * @id py/xslt-injection + * @tags security + * experimental + * external/cwe/cwe-643 + */ + +import python +import XsltInjectionQuery +import XsltInjectionFlow::PathGraph + +from XsltInjectionFlow::PathNode source, XsltInjectionFlow::PathNode sink +where XsltInjectionFlow::flowPath(source, sink) +select sink.getNode(), source, sink, "This XSLT query depends on $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/experimental/Security/CWE-091/XsltInjectionCustomizations.qll b/python/ql/src/experimental/Security/CWE-091/XsltInjectionCustomizations.qll new file mode 100644 index 00000000000..bda2fe646c9 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-091/XsltInjectionCustomizations.qll @@ -0,0 +1,58 @@ +/** + * Provides default sources, sinks and sanitizers for detecting + * "XSLT injection" + * vulnerabilities, as well as extension points for adding your own. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.Concepts +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.BarrierGuards +private import XsltConcept + +/** + * Provides default sources, sinks and sanitizers for detecting + * "XSLT injection" + * vulnerabilities, as well as extension points for adding your own. + */ +module XsltInjection { + /** + * A data flow source for "XSLT injection" vulnerabilities. + */ + abstract class Source extends DataFlow::Node { } + + /** + * A data flow sink for "XSLT injection" vulnerabilities. + */ + abstract class Sink extends DataFlow::Node { } + + /** + * A sanitizer for "XSLT injection" vulnerabilities. + */ + abstract class Sanitizer extends DataFlow::Node { } + + /** + * A source of remote user input, considered as a flow source. + */ + class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { } + + /** + * An XSLT construction, considered as a flow sink. + */ + class XsltConstructionAsSink extends Sink { + XsltConstructionAsSink() { this = any(XsltConstruction c).getXsltArg() } + } + + /** + * An XSLT execution, considered as a flow sink. + */ + class XsltExecutionAsSink extends Sink { + XsltExecutionAsSink() { this = any(XsltExecution c).getXsltArg() } + } + + /** + * A comparison with a constant string, considered as a sanitizer-guard. + */ + class StringConstCompareAsSanitizerGuard extends Sanitizer, StringConstCompareBarrier { } +} diff --git a/python/ql/src/experimental/Security/CWE-091/XsltInjectionQuery.qll b/python/ql/src/experimental/Security/CWE-091/XsltInjectionQuery.qll new file mode 100644 index 00000000000..4ecae424ed1 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-091/XsltInjectionQuery.qll @@ -0,0 +1,24 @@ +/** + * Provides a taint-tracking configuration for detecting "XSLT injection" vulnerabilities. + */ + +private import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import XsltInjectionCustomizations::XsltInjection +import XsltConcept + +module XsltInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof Source } + + predicate isSink(DataFlow::Node node) { node instanceof Sink } + + predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // I considered using a FlowState of (raw-string, ElementTree), but in all honesty + // valid code would never have direct flow from a string to a sink anyway... so I + // opted for the more simple approach. + nodeTo = elementTreeConstruction(nodeFrom) + } +} + +module XsltInjectionFlow = TaintTracking::Global; diff --git a/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll b/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll deleted file mode 100644 index 4d0057f8dc1..00000000000 --- a/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Provides class and predicates to track external data that - * may represent malicious XSLT query objects. - * - * This module is intended to be imported into a taint-tracking query - * to extend `TaintKind` and `TaintSink`. - */ - -import python -import semmle.python.dataflow.TaintTracking -import semmle.python.web.HttpRequest - -/** Models XSLT Injection related classes and functions */ -module XsltInjection { - /** Returns a class value which refers to `lxml.etree` */ - Value etree() { result = Value::named("lxml.etree") } - - /** A generic taint sink that is vulnerable to XSLT injection. */ - abstract class XsltInjectionSink extends TaintSink { } - - /** DEPRECATED: Alias for XsltInjectionSink */ - deprecated class XSLTInjectionSink = XsltInjectionSink; - - /** - * A kind of "taint", representing an untrusted XML string - */ - deprecated private class ExternalXmlStringKind extends ExternalStringKind { - ExternalXmlStringKind() { this = "etree.XML string" } - - override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { - etreeXml(fromnode, tonode) and result instanceof ExternalXmlKind - or - etreeFromStringList(fromnode, tonode) and result instanceof ExternalXmlKind - or - etreeFromString(fromnode, tonode) and result instanceof ExternalXmlKind - } - } - - /** - * A kind of "taint", representing a XML encoded string - */ - class ExternalXmlKind extends TaintKind { - ExternalXmlKind() { this = "lxml etree xml" } - } - - private predicate etreeXml(ControlFlowNode fromnode, CallNode tonode) { - // etree.XML("") - exists(CallNode call | call.getFunction().(AttrNode).getObject("XML").pointsTo(etree()) | - call.getArg(0) = fromnode and - call = tonode - ) - } - - private predicate etreeFromString(ControlFlowNode fromnode, CallNode tonode) { - // etree.fromstring(text, parser=None) - exists(CallNode call | call.getFunction().(AttrNode).getObject("fromstring").pointsTo(etree()) | - call.getArg(0) = fromnode and - call = tonode - ) - } - - private predicate etreeFromStringList(ControlFlowNode fromnode, CallNode tonode) { - // etree.fromstringlist(strings, parser=None) - exists(CallNode call | - call.getFunction().(AttrNode).getObject("fromstringlist").pointsTo(etree()) - | - call.getArg(0) = fromnode and - call = tonode - ) - } - - /** - * A Sink representing an argument to the `etree.XSLT` call. - * - * from lxml import etree - * root = etree.XML("") - * find_text = etree.XSLT("`sink`") - */ - private class EtreeXsltArgument extends XsltInjectionSink { - override string toString() { result = "lxml.etree.XSLT" } - - EtreeXsltArgument() { - exists(CallNode call | call.getFunction().(AttrNode).getObject("XSLT").pointsTo(etree()) | - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalXmlKind } - } - - /** - * A Sink representing an argument to the `XSLT` call to a parsed xml document. - * - * from lxml import etree - * from io import StringIO - * `sink` = etree.XML(xsltQuery) - * tree = etree.parse(f) - * result_tree = tree.xslt(`sink`) - */ - private class ParseXsltArgument extends XsltInjectionSink { - override string toString() { result = "lxml.etree.parse.xslt" } - - ParseXsltArgument() { - exists( - CallNode parseCall, CallNode xsltCall, ControlFlowNode obj, Variable var, AssignStmt assign - | - parseCall.getFunction().(AttrNode).getObject("parse").pointsTo(etree()) and - assign.getValue().(Call).getAFlowNode() = parseCall and - xsltCall.getFunction().(AttrNode).getObject("xslt") = obj and - var.getAUse() = obj and - assign.getATarget() = var.getAStore() and - xsltCall.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalXmlKind } - } -} - -/** DEPRECATED: Alias for XsltInjection */ -deprecated module XSLTInjection = XsltInjection; diff --git a/python/ql/src/experimental/semmle/python/templates/Airspeed.qll b/python/ql/src/experimental/semmle/python/templates/Airspeed.qll deleted file mode 100644 index dc266ac0f82..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Airspeed.qll +++ /dev/null @@ -1,27 +0,0 @@ -/** Provides classes which model the `airspeed` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `airspeed.Template` */ -deprecated ClassValue theAirspeedTemplateClass() { result = Value::named("airspeed.Template") } - -/** - * A sink representing the `airspeed.Template` class instantiation argument. - * - * import airspeed - * temp = airspeed.Template(`"sink"`) - */ -deprecated class AirspeedTemplateSink extends SSTISink { - override string toString() { result = "argument to airspeed.Template()" } - - AirspeedTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theAirspeedTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Bottle.qll b/python/ql/src/experimental/semmle/python/templates/Bottle.qll deleted file mode 100644 index 1f5bd2bba85..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Bottle.qll +++ /dev/null @@ -1,48 +0,0 @@ -/** Provides classes which model the `bottle` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `bottle.SimpleTemplate` */ -deprecated ClassValue theBottleSimpleTemplateClass() { - result = Value::named("bottle.SimpleTemplate") -} - -/** - * A sink representing the `bottle.SimpleTemplate` class instantiation argument. - * - * from bottle import SimpleTemplate - * template = SimpleTemplate(`sink`) - */ -deprecated class BottleSimpleTemplateSink extends SSTISink { - override string toString() { result = "argument to bottle.SimpleTemplate()" } - - BottleSimpleTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theBottleSimpleTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} - -/** - * A sink representing the `bottle.template` function call argument. - * - * from bottle import template - * tmp = template(`sink`) - */ -deprecated class BottleTemplateSink extends SSTISink { - override string toString() { result = "argument to bottle.template()" } - - BottleTemplateSink() { - exists(CallNode call | - call.getFunction() = theBottleModule().attr("template").getAReference() and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Chameleon.qll b/python/ql/src/experimental/semmle/python/templates/Chameleon.qll deleted file mode 100644 index f094dda97b5..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Chameleon.qll +++ /dev/null @@ -1,29 +0,0 @@ -/** Provides classes which model the `Chameleon` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `chameleon.PageTemplate` */ -deprecated ClassValue theChameleonPageTemplateClass() { - result = Value::named("chameleon.PageTemplate") -} - -/** - * A sink representing the `chameleon.PageTemplate` class instantiation argument. - * - * from chameleon import PageTemplate - * template = PageTemplate(`sink`) - */ -deprecated class ChameleonTemplateSink extends SSTISink { - override string toString() { result = "argument to Chameleon.PageTemplate()" } - - ChameleonTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theChameleonPageTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Cheetah.qll b/python/ql/src/experimental/semmle/python/templates/Cheetah.qll deleted file mode 100644 index 9812fdb7c88..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Cheetah.qll +++ /dev/null @@ -1,39 +0,0 @@ -/** Provides classes which model the `Cheetah3` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `Cheetah.Template.Template` */ -deprecated ClassValue theCheetahTemplateClass() { - result = Value::named("Cheetah.Template.Template") -} - -/** - * A sink representing the instantiation argument of any class which derives from - * the `Cheetah.Template.Template` class . - * - * from Cheetah.Template import Template - * class Template3(Template): - * title = 'Hello World Example!' - * contents = 'Hello World!' - * t3 = Template3("sink") - * - * This will also detect cases of the following type : - * - * from Cheetah.Template import Template - * t3 = Template("sink") - */ -deprecated class CheetahTemplateInstantiationSink extends SSTISink { - override string toString() { result = "argument to Cheetah.Template.Template()" } - - CheetahTemplateInstantiationSink() { - exists(CallNode call, ClassValue cv | - cv.getASuperType() = theCheetahTemplateClass() and - call.getFunction().pointsTo(cv) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Chevron.qll b/python/ql/src/experimental/semmle/python/templates/Chevron.qll deleted file mode 100644 index cc93016891c..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Chevron.qll +++ /dev/null @@ -1,36 +0,0 @@ -/** Provides classes which model the `chevron` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the Value representing `chevron.render` function */ -deprecated Value theChevronRenderFunc() { result = Value::named("chevron.render") } - -/** - * A sink representing the `chevron.render` function call argument. - * - * import chevron - * tmp = chevron.render(`sink`,{ 'key' : 'value' }) - */ -deprecated class ChevronRenderSink extends SSTISink { - override string toString() { result = "argument to chevron.render()" } - - ChevronRenderSink() { - exists(CallNode call | - call.getFunction() = theChevronRenderFunc().getAReference() and - call.getArg(0) = this - ) - // TODO: this should also detect : - // import chevron - // args = { - // 'template': 'sink', - // 'data': { - // 'mustache': 'World' - // } - // } - // chevron.render(**args) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/DjangoTemplate.qll b/python/ql/src/experimental/semmle/python/templates/DjangoTemplate.qll deleted file mode 100644 index 1089ab872ec..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/DjangoTemplate.qll +++ /dev/null @@ -1,35 +0,0 @@ -/** Provides classes which model the `DjangoTemplate` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -deprecated ClassValue theDjangoTemplateClass() { result = Value::named("django.template.Template") } - -/** - * A sink representing `django.template.Template` class instantiation argument. - * - * from django.template import Template - * template = Template(`sink`) - */ -deprecated class DjangoTemplateTemplateSink extends SSTISink { - override string toString() { result = "argument to Django.template()" } - - DjangoTemplateTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theDjangoTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} -// TODO (intentionally commented out QLDoc, since qlformat will delete those lines otherwise) -// /** -// * Sinks representing the django.template.Template class instantiation. -// * -// * from django.template import engines -// * -// * django_engine = engines["django"] -// * template = django_engine.from_string(`sink`) -// */ diff --git a/python/ql/src/experimental/semmle/python/templates/FlaskTemplate.qll b/python/ql/src/experimental/semmle/python/templates/FlaskTemplate.qll deleted file mode 100644 index c0f3c90235d..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/FlaskTemplate.qll +++ /dev/null @@ -1,28 +0,0 @@ -/** Provides classes which model templates in the`flask` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -deprecated Value theFlaskRenderTemplateClass() { - result = Value::named("flask.render_template_string") -} - -/** - * A sink representing `flask.render_template_string` function call argument. - * - * from flask import render_template_string - * render_template_string(`sink`) - */ -deprecated class FlaskTemplateSink extends SSTISink { - override string toString() { result = "argument to flask.render_template_string()" } - - FlaskTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theFlaskRenderTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Genshi.qll b/python/ql/src/experimental/semmle/python/templates/Genshi.qll deleted file mode 100644 index c808d7c60f8..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Genshi.qll +++ /dev/null @@ -1,53 +0,0 @@ -/** Provides classes which model the `Genshi` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `Genshi.template.TextTemplate` */ -deprecated ClassValue theGenshiTextTemplateClass() { - result = Value::named("genshi.template.TextTemplate") -} - -/** returns the ClassValue representing `Genshi.template.MarkupTemplate` */ -deprecated ClassValue theGenshiMarkupTemplateClass() { - result = Value::named("genshi.template.MarkupTemplate") -} - -/** - * A sink representing the `genshi.template.TextTemplate` class instantiation argument. - * - * from genshi.template import TextTemplate - * tmpl = TextTemplate('sink') - */ -deprecated class GenshiTextTemplateSink extends SSTISink { - override string toString() { result = "argument to genshi.template.TextTemplate()" } - - GenshiTextTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theGenshiTextTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} - -/** - * A sink representing the `genshi.template.MarkupTemplate` class instantiation argument. - * - * from genshi.template import MarkupTemplate - * tmpl = MarkupTemplate('sink') - */ -deprecated class GenshiMarkupTemplateSink extends SSTISink { - override string toString() { result = "argument to genshi.template.MarkupTemplate()" } - - GenshiMarkupTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theGenshiMarkupTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Jinja.qll b/python/ql/src/experimental/semmle/python/templates/Jinja.qll deleted file mode 100644 index 44bc103cf04..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Jinja.qll +++ /dev/null @@ -1,49 +0,0 @@ -/** Provides classes which model the `Jinja2` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `jinja2.Template` */ -deprecated ClassValue theJinja2TemplateClass() { result = Value::named("jinja2.Template") } - -/** returns the ClassValue representing `jinja2.Template` */ -deprecated Value theJinja2FromStringValue() { result = Value::named("jinja2.from_string") } - -/** - * A sink representing the `jinja2.Template` class instantiation argument. - * - * from jinja2 import Template - * template = Template(`sink`) - */ -deprecated class Jinja2TemplateSink extends SSTISink { - override string toString() { result = "argument to jinja2.Template()" } - - Jinja2TemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theJinja2TemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} - -/** - * A sink representing the `jinja2.from_string` function call argument. - * - * from jinja2 import from_string - * template = from_string(`sink`) - */ -deprecated class Jinja2FromStringSink extends SSTISink { - override string toString() { result = "argument to jinja2.from_string()" } - - Jinja2FromStringSink() { - exists(CallNode call | - call.getFunction().pointsTo(theJinja2FromStringValue()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Mako.qll b/python/ql/src/experimental/semmle/python/templates/Mako.qll deleted file mode 100644 index b8634b3001a..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Mako.qll +++ /dev/null @@ -1,27 +0,0 @@ -/** Provides classes which model the `Mako` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `mako.template.Template` */ -deprecated ClassValue theMakoTemplateClass() { result = Value::named("mako.template.Template") } - -/** - * A sink representing the `mako.template.Template` class instantiation argument. - * - * from mako.template import Template - * mytemplate = Template("hello world!") - */ -deprecated class MakoTemplateSink extends SSTISink { - override string toString() { result = "argument to mako.template.Template()" } - - MakoTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theMakoTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/SSTISink.qll b/python/ql/src/experimental/semmle/python/templates/SSTISink.qll deleted file mode 100644 index 1a68fe17b68..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/SSTISink.qll +++ /dev/null @@ -1,7 +0,0 @@ -import semmle.python.dataflow.TaintTracking - -/** - * A generic taint sink that is vulnerable to template inclusions. - * The `temp` in `jinja2.Template(temp)` and similar. - */ -abstract deprecated class SSTISink extends TaintSink { } diff --git a/python/ql/src/experimental/semmle/python/templates/Ssti.qll b/python/ql/src/experimental/semmle/python/templates/Ssti.qll deleted file mode 100644 index eb4f8d0ec2f..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Ssti.qll +++ /dev/null @@ -1,13 +0,0 @@ -/** Imports all files which model potential SSTI sinks */ - -import experimental.semmle.python.templates.Airspeed -import experimental.semmle.python.templates.Bottle -import experimental.semmle.python.templates.Chameleon -import experimental.semmle.python.templates.Cheetah -import experimental.semmle.python.templates.Chevron -import experimental.semmle.python.templates.DjangoTemplate -import experimental.semmle.python.templates.FlaskTemplate -import experimental.semmle.python.templates.Genshi -import experimental.semmle.python.templates.Jinja -import experimental.semmle.python.templates.Mako -import experimental.semmle.python.templates.TRender diff --git a/python/ql/src/experimental/semmle/python/templates/TRender.qll b/python/ql/src/experimental/semmle/python/templates/TRender.qll deleted file mode 100644 index 8d5431ad9e0..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/TRender.qll +++ /dev/null @@ -1,27 +0,0 @@ -/** Provides classes which model the `TRender` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `trender.TRender` */ -deprecated ClassValue theTRenderTemplateClass() { result = Value::named("trender.TRender") } - -/** - * A sink representing the `trender.TRender` class instantiation argument. - * - * from trender import TRender - * template = TRender(`sink`) - */ -deprecated class TRenderTemplateSink extends SSTISink { - override string toString() { result = "argument to trender.TRender()" } - - TRenderTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theTRenderTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 3010d994ca4..f7ff3ff2348 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 0.8.3 +version: 0.8.4-dev groups: - python - queries diff --git a/python/ql/test/experimental/dataflow/TestUtil/DataflowQueryTest.qll b/python/ql/test/experimental/dataflow/TestUtil/DataflowQueryTest.qll index 74a43bb4cc4..6b5b980ed14 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/DataflowQueryTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/DataflowQueryTest.qll @@ -1,58 +1,117 @@ import python import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking import TestUtilities.InlineExpectationsTest private import semmle.python.dataflow.new.internal.PrintNode -module DataFlowQueryTest implements TestSig { - string getARelevantTag() { result = "result" } +signature module QueryTestSig { + predicate isSink(DataFlow::Node sink); - predicate hasActualResult(Location location, string element, string tag, string value) { - exists(DataFlow::Configuration cfg, DataFlow::Node sink | cfg.hasFlowTo(sink) | - location = sink.getLocation() and - tag = "result" and - value = "BAD" and - element = sink.toString() - ) + predicate flowTo(DataFlow::Node sink); +} + +module MakeQueryTest { + module DataFlowQueryTest implements TestSig { + string getARelevantTag() { result = "result" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + exists(DataFlow::Node sink | Impl::flowTo(sink) | + location = sink.getLocation() and + tag = "result" and + value = "BAD" and + element = sink.toString() + ) + } + + // We allow annotating any sink with `result=OK` to signal + // safe sinks. + // Sometimes a line contains both an alert and a safe sink. + // In this situation, the annotation form `OK(safe sink)` + // can be useful. + predicate hasOptionalResult(Location location, string element, string tag, string value) { + exists(DataFlow::Node sink | Impl::isSink(sink) | + location = sink.getLocation() and + tag = "result" and + value in ["OK", "OK(" + prettyNode(sink) + ")"] and + element = sink.toString() + ) + } } - // We allow annotating any sink with `result=OK` to signal - // safe sinks. - // Sometimes a line contains both an alert and a safe sink. - // In this situation, the annotation form `OK(safe sink)` - // can be useful. - predicate hasOptionalResult(Location location, string element, string tag, string value) { - exists(DataFlow::Configuration cfg, DataFlow::Node sink | - cfg.isSink(sink) or cfg.isSink(sink, _) - | + import MakeTest + + query predicate missingAnnotationOnSink(Location location, string error, string element) { + error = "ERROR, you should add `# $ MISSING: result=BAD` or `result=OK` annotation" and + exists(DataFlow::Node sink | + exists(sink.getLocation().getFile().getRelativePath()) and + Impl::isSink(sink) and location = sink.getLocation() and - tag = "result" and - value in ["OK", "OK(" + prettyNode(sink) + ")"] and - element = sink.toString() + element = prettyExpr(sink.asExpr()) and + not Impl::flowTo(sink) and + not exists(FalseNegativeTestExpectation missingResult | + missingResult.getTag() = "result" and + missingResult.getValue() = "BAD" and + missingResult.getLocation().getFile() = location.getFile() and + missingResult.getLocation().getStartLine() = location.getStartLine() + ) and + not exists(GoodTestExpectation okResult | + okResult.getTag() = "result" and + okResult.getValue() in ["OK", "OK(" + prettyNode(sink) + ")"] and + okResult.getLocation().getFile() = location.getFile() and + okResult.getLocation().getStartLine() = location.getStartLine() + ) ) } } -import MakeTest +module FromDataFlowConfig { + module Impl implements QueryTestSig { + predicate isSink(DataFlow::Node sink) { C::isSink(sink) } -query predicate missingAnnotationOnSink(Location location, string error, string element) { - error = "ERROR, you should add `# $ MISSING: result=BAD` or `result=OK` annotation" and - exists(DataFlow::Node sink | - exists(sink.getLocation().getFile().getRelativePath()) and - exists(DataFlow::Configuration cfg | cfg.isSink(sink) or cfg.isSink(sink, _)) and - location = sink.getLocation() and - element = prettyExpr(sink.asExpr()) and - not exists(DataFlow::Configuration cfg | cfg.hasFlowTo(sink)) and - not exists(FalseNegativeTestExpectation missingResult | - missingResult.getTag() = "result" and - missingResult.getValue() = "BAD" and - missingResult.getLocation().getFile() = location.getFile() and - missingResult.getLocation().getStartLine() = location.getStartLine() - ) and - not exists(GoodTestExpectation okResult | - okResult.getTag() = "result" and - okResult.getValue() in ["OK", "OK(" + prettyNode(sink) + ")"] and - okResult.getLocation().getFile() = location.getFile() and - okResult.getLocation().getStartLine() = location.getStartLine() - ) - ) + predicate flowTo(DataFlow::Node sink) { DataFlow::Global::flowTo(sink) } + } + + import MakeQueryTest +} + +module FromDataFlowStateConfig { + module Impl implements QueryTestSig { + predicate isSink(DataFlow::Node sink) { C::isSink(sink) or C::isSink(sink, _) } + + predicate flowTo(DataFlow::Node sink) { DataFlow::GlobalWithState::flowTo(sink) } + } + + import MakeQueryTest +} + +module FromTaintTrackingConfig { + module Impl implements QueryTestSig { + predicate isSink(DataFlow::Node sink) { C::isSink(sink) } + + predicate flowTo(DataFlow::Node sink) { TaintTracking::Global::flowTo(sink) } + } + + import MakeQueryTest +} + +module FromTaintTrackingStateConfig { + module Impl implements QueryTestSig { + predicate isSink(DataFlow::Node sink) { C::isSink(sink) or C::isSink(sink, _) } + + predicate flowTo(DataFlow::Node sink) { TaintTracking::GlobalWithState::flowTo(sink) } + } + + import MakeQueryTest +} + +signature class LegacyConfiguration extends DataFlow::Configuration; + +module FromLegacyConfiguration { + module Impl implements QueryTestSig { + predicate isSink(DataFlow::Node sink) { any(C c).isSink(sink) or any(C c).isSink(sink, _) } + + predicate flowTo(DataFlow::Node sink) { any(C c).hasFlowTo(sink) } + } + + import MakeQueryTest } diff --git a/python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml b/python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml new file mode 100644 index 00000000000..3e14c56d735 --- /dev/null +++ b/python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml @@ -0,0 +1,18 @@ +extensions: + - addsTo: + pack: codeql/python-all + extensible: summaryModel + data: + - ["foo", "Member[MS_identity]", "Argument[0]", "ReturnValue", "value"] + - ["foo", "Member[MS_apply_lambda]", "Argument[1]", "Argument[0].Parameter[0]", "value"] + - ["foo", "Member[MS_apply_lambda]", "Argument[0].ReturnValue", "ReturnValue", "value"] + - ["foo", "Member[MS_reversed]", "Argument[0].ListElement", "ReturnValue.ListElement", "value"] + - ["foo", "Member[MS_reversed]", "Argument[0]", "ReturnValue", "taint"] + - ["foo", "Member[MS_list_map]", "Argument[1].ListElement", "Argument[0].Parameter[0]", "value"] + - ["foo", "Member[MS_list_map]", "Argument[0].ReturnValue", "ReturnValue.ListElement", "value"] + - ["foo", "Member[MS_list_map]", "Argument[1]", "ReturnValue", "taint"] + - ["foo", "Member[MS_append_to_list]", "Argument[0].ListElement", "ReturnValue.ListElement", "value"] + - ["foo", "Member[MS_append_to_list]", "Argument[1]", "ReturnValue.ListElement", "value"] + - ["foo", "Member[MS_append_to_list]", "Argument[0]", "ReturnValue", "taint"] + - ["foo", "Member[MS_append_to_list]", "Argument[1]", "ReturnValue", "taint"] + - ["json", "Member[MS_loads]", "Argument[0]", "ReturnValue", "taint"] diff --git a/python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ql b/python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ql index 551266d7455..dd01b5d3e34 100644 --- a/python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ql +++ b/python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ql @@ -1,4 +1,3 @@ import python -private import TestSummaries import experimental.meta.InlineTaintTest import MakeInlineTaintTest diff --git a/python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml b/python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml new file mode 100644 index 00000000000..3e14c56d735 --- /dev/null +++ b/python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml @@ -0,0 +1,18 @@ +extensions: + - addsTo: + pack: codeql/python-all + extensible: summaryModel + data: + - ["foo", "Member[MS_identity]", "Argument[0]", "ReturnValue", "value"] + - ["foo", "Member[MS_apply_lambda]", "Argument[1]", "Argument[0].Parameter[0]", "value"] + - ["foo", "Member[MS_apply_lambda]", "Argument[0].ReturnValue", "ReturnValue", "value"] + - ["foo", "Member[MS_reversed]", "Argument[0].ListElement", "ReturnValue.ListElement", "value"] + - ["foo", "Member[MS_reversed]", "Argument[0]", "ReturnValue", "taint"] + - ["foo", "Member[MS_list_map]", "Argument[1].ListElement", "Argument[0].Parameter[0]", "value"] + - ["foo", "Member[MS_list_map]", "Argument[0].ReturnValue", "ReturnValue.ListElement", "value"] + - ["foo", "Member[MS_list_map]", "Argument[1]", "ReturnValue", "taint"] + - ["foo", "Member[MS_append_to_list]", "Argument[0].ListElement", "ReturnValue.ListElement", "value"] + - ["foo", "Member[MS_append_to_list]", "Argument[1]", "ReturnValue.ListElement", "value"] + - ["foo", "Member[MS_append_to_list]", "Argument[0]", "ReturnValue", "taint"] + - ["foo", "Member[MS_append_to_list]", "Argument[1]", "ReturnValue", "taint"] + - ["json", "Member[MS_loads]", "Argument[0]", "ReturnValue", "taint"] diff --git a/python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ql b/python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ql index 3e311335e14..3ee344d0b87 100644 --- a/python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ql +++ b/python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ql @@ -1,3 +1,2 @@ import python -private import TestSummaries import experimental.dataflow.TestUtil.NormalDataflowTest diff --git a/python/ql/test/experimental/dataflow/model-summaries/TestSummaries.qll b/python/ql/test/experimental/dataflow/model-summaries/TestSummaries.qll deleted file mode 100644 index 5f1e0a1f90b..00000000000 --- a/python/ql/test/experimental/dataflow/model-summaries/TestSummaries.qll +++ /dev/null @@ -1,25 +0,0 @@ -private import python -private import semmle.python.dataflow.new.FlowSummary -private import semmle.python.frameworks.data.ModelsAsData -private import semmle.python.ApiGraphs - -private class StepsFromModel extends ModelInput::SummaryModelCsv { - override predicate row(string row) { - row = - [ - "foo;Member[MS_identity];Argument[0];ReturnValue;value", - "foo;Member[MS_apply_lambda];Argument[1];Argument[0].Parameter[0];value", - "foo;Member[MS_apply_lambda];Argument[0].ReturnValue;ReturnValue;value", - "foo;Member[MS_reversed];Argument[0].ListElement;ReturnValue.ListElement;value", - "foo;Member[MS_reversed];Argument[0];ReturnValue;taint", - "foo;Member[MS_list_map];Argument[1].ListElement;Argument[0].Parameter[0];value", - "foo;Member[MS_list_map];Argument[0].ReturnValue;ReturnValue.ListElement;value", - "foo;Member[MS_list_map];Argument[1];ReturnValue;taint", - "foo;Member[MS_append_to_list];Argument[0].ListElement;ReturnValue.ListElement;value", - "foo;Member[MS_append_to_list];Argument[1];ReturnValue.ListElement;value", - "foo;Member[MS_append_to_list];Argument[0];ReturnValue;taint", - "foo;Member[MS_append_to_list];Argument[1];ReturnValue;taint", - "json;Member[MS_loads];Argument[0];ReturnValue;taint" - ] - } -} diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql index f02f8529c96..91a6cdaa14a 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql +++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql @@ -1,3 +1,4 @@ import python import experimental.dataflow.TestUtil.DataflowQueryTest import experimental.Security.UnsafeUnpackQuery +import FromLegacyConfiguration diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/AirspeedSsti.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/AirspeedSsti.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/AirspeedSsti.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/AirspeedSsti.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/BottleSsti.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/BottleSsti.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/BottleSsti.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/BottleSsti.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/Chameleon.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/Chameleon.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/Chameleon.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/Chameleon.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/CheetahSinks.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/CheetahSinks.py new file mode 100644 index 00000000000..7f9fed4decf --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/CheetahSinks.py @@ -0,0 +1,22 @@ +from flask import Flask, request +from Cheetah.Template import Template + + +app = Flask(__name__) + + +@app.route('/other') +def a(): + template = request.args.get('template') + return Template(template) + + +class Template3(Template): + title = 'Hello World Example!' + contents = 'Hello World!' + + +@app.route('/other2') +def b(): + template = request.args.get('template') + t3 = Template3(template) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/ChevronSsti.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/ChevronSsti.py similarity index 89% rename from python/ql/test/experimental/query-tests/Security/CWE-074/ChevronSsti.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/ChevronSsti.py index f2430e437ae..f3b0e57fc8f 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-074/ChevronSsti.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/ChevronSsti.py @@ -5,13 +5,13 @@ import chevron app = Flask(__name__) -@route('/other') +@app.route('/other') def a(): template = request.args.get('template') return chevron.render(template, {"key": "value"}) -@route('/other2') +@app.route('/other2') def b(): template = request.args.get('template') args = { diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/DjangoTemplates.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/DjangoTemplates.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/DjangoTemplates.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/DjangoTemplates.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/FlaskTemplate.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/FlaskTemplate.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/FlaskTemplate.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/FlaskTemplate.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/Genshi.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/Genshi.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/Genshi.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/Genshi.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/JinjaSsti.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/JinjaSsti.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/JinjaSsti.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/JinjaSsti.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/MakoSsti.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/MakoSsti.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/MakoSsti.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/MakoSsti.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/TRender.py b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/TRender.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/TRender.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/TRender.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.expected new file mode 100644 index 00000000000..34bb9d7e66c --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.expected @@ -0,0 +1,107 @@ +edges +| AirspeedSsti.py:2:26:2:32 | ControlFlowNode for ImportMember | AirspeedSsti.py:2:26:2:32 | GSSA Variable request | +| AirspeedSsti.py:2:26:2:32 | GSSA Variable request | AirspeedSsti.py:10:16:10:22 | ControlFlowNode for request | +| AirspeedSsti.py:10:5:10:12 | SSA variable template | AirspeedSsti.py:11:30:11:37 | ControlFlowNode for template | +| AirspeedSsti.py:10:16:10:22 | ControlFlowNode for request | AirspeedSsti.py:10:16:10:27 | ControlFlowNode for Attribute | +| AirspeedSsti.py:10:16:10:27 | ControlFlowNode for Attribute | AirspeedSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | +| AirspeedSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | AirspeedSsti.py:10:5:10:12 | SSA variable template | +| CheetahSinks.py:1:26:1:32 | ControlFlowNode for ImportMember | CheetahSinks.py:1:26:1:32 | GSSA Variable request | +| CheetahSinks.py:1:26:1:32 | GSSA Variable request | CheetahSinks.py:10:16:10:22 | ControlFlowNode for request | +| CheetahSinks.py:1:26:1:32 | GSSA Variable request | CheetahSinks.py:21:16:21:22 | ControlFlowNode for request | +| CheetahSinks.py:10:5:10:12 | SSA variable template | CheetahSinks.py:11:21:11:28 | ControlFlowNode for template | +| CheetahSinks.py:10:16:10:22 | ControlFlowNode for request | CheetahSinks.py:10:16:10:27 | ControlFlowNode for Attribute | +| CheetahSinks.py:10:16:10:27 | ControlFlowNode for Attribute | CheetahSinks.py:10:16:10:43 | ControlFlowNode for Attribute() | +| CheetahSinks.py:10:16:10:43 | ControlFlowNode for Attribute() | CheetahSinks.py:10:5:10:12 | SSA variable template | +| CheetahSinks.py:21:5:21:12 | SSA variable template | CheetahSinks.py:22:20:22:27 | ControlFlowNode for template | +| CheetahSinks.py:21:16:21:22 | ControlFlowNode for request | CheetahSinks.py:21:16:21:27 | ControlFlowNode for Attribute | +| CheetahSinks.py:21:16:21:27 | ControlFlowNode for Attribute | CheetahSinks.py:21:16:21:43 | ControlFlowNode for Attribute() | +| CheetahSinks.py:21:16:21:43 | ControlFlowNode for Attribute() | CheetahSinks.py:21:5:21:12 | SSA variable template | +| ChevronSsti.py:1:26:1:32 | ControlFlowNode for ImportMember | ChevronSsti.py:1:26:1:32 | GSSA Variable request | +| ChevronSsti.py:1:26:1:32 | GSSA Variable request | ChevronSsti.py:10:16:10:22 | ControlFlowNode for request | +| ChevronSsti.py:10:5:10:12 | SSA variable template | ChevronSsti.py:11:27:11:34 | ControlFlowNode for template | +| ChevronSsti.py:10:16:10:22 | ControlFlowNode for request | ChevronSsti.py:10:16:10:27 | ControlFlowNode for Attribute | +| ChevronSsti.py:10:16:10:27 | ControlFlowNode for Attribute | ChevronSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | +| ChevronSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | ChevronSsti.py:10:5:10:12 | SSA variable template | +| DjangoTemplates.py:6:8:6:14 | ControlFlowNode for request | DjangoTemplates.py:8:5:8:12 | SSA variable template | +| DjangoTemplates.py:8:5:8:12 | SSA variable template | DjangoTemplates.py:9:18:9:25 | ControlFlowNode for template | +| FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | FlaskTemplate.py:1:26:1:32 | GSSA Variable request | +| FlaskTemplate.py:1:26:1:32 | GSSA Variable request | FlaskTemplate.py:10:8:10:14 | ControlFlowNode for request | +| FlaskTemplate.py:1:26:1:32 | GSSA Variable request | FlaskTemplate.py:11:39:11:45 | ControlFlowNode for request | +| FlaskTemplate.py:1:26:1:32 | GSSA Variable request | FlaskTemplate.py:17:41:17:47 | ControlFlowNode for request | +| FlaskTemplate.py:10:8:10:14 | ControlFlowNode for request | FlaskTemplate.py:11:39:11:50 | ControlFlowNode for Attribute | +| FlaskTemplate.py:11:39:11:45 | ControlFlowNode for request | FlaskTemplate.py:11:39:11:50 | ControlFlowNode for Attribute | +| FlaskTemplate.py:11:39:11:50 | ControlFlowNode for Attribute | FlaskTemplate.py:11:39:11:66 | ControlFlowNode for Attribute() | +| FlaskTemplate.py:17:41:17:47 | ControlFlowNode for request | FlaskTemplate.py:17:41:17:52 | ControlFlowNode for Attribute | +| FlaskTemplate.py:17:41:17:52 | ControlFlowNode for Attribute | FlaskTemplate.py:17:41:17:68 | ControlFlowNode for Attribute() | +| JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | JinjaSsti.py:9:5:9:12 | SSA variable template | +| JinjaSsti.py:9:5:9:12 | SSA variable template | JinjaSsti.py:10:25:10:32 | ControlFlowNode for template | +| JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | JinjaSsti.py:19:5:19:12 | SSA variable template | +| JinjaSsti.py:19:5:19:12 | SSA variable template | JinjaSsti.py:20:28:20:35 | ControlFlowNode for template | +| MakoSsti.py:6:10:6:16 | ControlFlowNode for request | MakoSsti.py:8:5:8:12 | SSA variable template | +| MakoSsti.py:8:5:8:12 | SSA variable template | MakoSsti.py:9:27:9:34 | ControlFlowNode for template | +| TRender.py:5:13:5:19 | ControlFlowNode for request | TRender.py:6:5:6:12 | SSA variable template | +| TRender.py:6:5:6:12 | SSA variable template | TRender.py:7:24:7:31 | ControlFlowNode for template | +nodes +| AirspeedSsti.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| AirspeedSsti.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| AirspeedSsti.py:10:5:10:12 | SSA variable template | semmle.label | SSA variable template | +| AirspeedSsti.py:10:16:10:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| AirspeedSsti.py:10:16:10:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| AirspeedSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| AirspeedSsti.py:11:30:11:37 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| CheetahSinks.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| CheetahSinks.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| CheetahSinks.py:10:5:10:12 | SSA variable template | semmle.label | SSA variable template | +| CheetahSinks.py:10:16:10:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| CheetahSinks.py:10:16:10:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| CheetahSinks.py:10:16:10:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| CheetahSinks.py:11:21:11:28 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| CheetahSinks.py:21:5:21:12 | SSA variable template | semmle.label | SSA variable template | +| CheetahSinks.py:21:16:21:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| CheetahSinks.py:21:16:21:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| CheetahSinks.py:21:16:21:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| CheetahSinks.py:22:20:22:27 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| ChevronSsti.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ChevronSsti.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| ChevronSsti.py:10:5:10:12 | SSA variable template | semmle.label | SSA variable template | +| ChevronSsti.py:10:16:10:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| ChevronSsti.py:10:16:10:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| ChevronSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| ChevronSsti.py:11:27:11:34 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| DjangoTemplates.py:6:8:6:14 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| DjangoTemplates.py:8:5:8:12 | SSA variable template | semmle.label | SSA variable template | +| DjangoTemplates.py:9:18:9:25 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| FlaskTemplate.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| FlaskTemplate.py:10:8:10:14 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| FlaskTemplate.py:11:39:11:45 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| FlaskTemplate.py:11:39:11:50 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| FlaskTemplate.py:11:39:11:66 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| FlaskTemplate.py:17:41:17:47 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| FlaskTemplate.py:17:41:17:52 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| FlaskTemplate.py:17:41:17:68 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| JinjaSsti.py:9:5:9:12 | SSA variable template | semmle.label | SSA variable template | +| JinjaSsti.py:10:25:10:32 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| JinjaSsti.py:19:5:19:12 | SSA variable template | semmle.label | SSA variable template | +| JinjaSsti.py:20:28:20:35 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| MakoSsti.py:6:10:6:16 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| MakoSsti.py:8:5:8:12 | SSA variable template | semmle.label | SSA variable template | +| MakoSsti.py:9:27:9:34 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| TRender.py:5:13:5:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| TRender.py:6:5:6:12 | SSA variable template | semmle.label | SSA variable template | +| TRender.py:7:24:7:31 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +subpaths +#select +| AirspeedSsti.py:11:30:11:37 | ControlFlowNode for template | AirspeedSsti.py:2:26:2:32 | ControlFlowNode for ImportMember | AirspeedSsti.py:11:30:11:37 | ControlFlowNode for template | This Template depends on $@. | AirspeedSsti.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| CheetahSinks.py:11:21:11:28 | ControlFlowNode for template | CheetahSinks.py:1:26:1:32 | ControlFlowNode for ImportMember | CheetahSinks.py:11:21:11:28 | ControlFlowNode for template | This Template depends on $@. | CheetahSinks.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| CheetahSinks.py:22:20:22:27 | ControlFlowNode for template | CheetahSinks.py:1:26:1:32 | ControlFlowNode for ImportMember | CheetahSinks.py:22:20:22:27 | ControlFlowNode for template | This Template depends on $@. | CheetahSinks.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| ChevronSsti.py:11:27:11:34 | ControlFlowNode for template | ChevronSsti.py:1:26:1:32 | ControlFlowNode for ImportMember | ChevronSsti.py:11:27:11:34 | ControlFlowNode for template | This Template depends on $@. | ChevronSsti.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| DjangoTemplates.py:9:18:9:25 | ControlFlowNode for template | DjangoTemplates.py:6:8:6:14 | ControlFlowNode for request | DjangoTemplates.py:9:18:9:25 | ControlFlowNode for template | This Template depends on $@. | DjangoTemplates.py:6:8:6:14 | ControlFlowNode for request | user-provided value | +| FlaskTemplate.py:11:39:11:66 | ControlFlowNode for Attribute() | FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | FlaskTemplate.py:11:39:11:66 | ControlFlowNode for Attribute() | This Template depends on $@. | FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| FlaskTemplate.py:17:41:17:68 | ControlFlowNode for Attribute() | FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | FlaskTemplate.py:17:41:17:68 | ControlFlowNode for Attribute() | This Template depends on $@. | FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| JinjaSsti.py:10:25:10:32 | ControlFlowNode for template | JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | JinjaSsti.py:10:25:10:32 | ControlFlowNode for template | This Template depends on $@. | JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | user-provided value | +| JinjaSsti.py:20:28:20:35 | ControlFlowNode for template | JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | JinjaSsti.py:20:28:20:35 | ControlFlowNode for template | This Template depends on $@. | JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | user-provided value | +| MakoSsti.py:9:27:9:34 | ControlFlowNode for template | MakoSsti.py:6:10:6:16 | ControlFlowNode for request | MakoSsti.py:9:27:9:34 | ControlFlowNode for template | This Template depends on $@. | MakoSsti.py:6:10:6:16 | ControlFlowNode for request | user-provided value | +| TRender.py:7:24:7:31 | ControlFlowNode for template | TRender.py:5:13:5:19 | ControlFlowNode for request | TRender.py:7:24:7:31 | ControlFlowNode for template | This Template depends on $@. | TRender.py:5:13:5:19 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/TemplateInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.qlref similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/TemplateInjection.qlref rename to python/ql/test/experimental/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.qlref diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.expected b/python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.expected similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.expected rename to python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.expected diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.py b/python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.py rename to python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.qlref b/python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.qlref similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.qlref rename to python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.qlref diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/TemplateInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-074/TemplateInjection.expected deleted file mode 100644 index 058a53bdf91..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-074/TemplateInjection.expected +++ /dev/null @@ -1,60 +0,0 @@ -edges -| AirspeedSsti.py:10:16:10:27 | dict of externally controlled string | AirspeedSsti.py:10:16:10:43 | externally controlled string | -| AirspeedSsti.py:10:16:10:27 | dict of externally controlled string | AirspeedSsti.py:10:16:10:43 | externally controlled string | -| AirspeedSsti.py:10:16:10:43 | externally controlled string | AirspeedSsti.py:11:30:11:37 | externally controlled string | -| AirspeedSsti.py:10:16:10:43 | externally controlled string | AirspeedSsti.py:11:30:11:37 | externally controlled string | -| ChevronSsti.py:10:16:10:27 | dict of externally controlled string | ChevronSsti.py:10:16:10:43 | externally controlled string | -| ChevronSsti.py:10:16:10:27 | dict of externally controlled string | ChevronSsti.py:10:16:10:43 | externally controlled string | -| ChevronSsti.py:10:16:10:43 | externally controlled string | ChevronSsti.py:11:27:11:34 | externally controlled string | -| ChevronSsti.py:10:16:10:43 | externally controlled string | ChevronSsti.py:11:27:11:34 | externally controlled string | -| DjangoTemplates.py:6:8:6:14 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | -| DjangoTemplates.py:6:8:6:14 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | -| DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | -| DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | -| DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | DjangoTemplates.py:8:16:8:38 | externally controlled string | -| DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | DjangoTemplates.py:8:16:8:38 | externally controlled string | -| DjangoTemplates.py:8:16:8:38 | externally controlled string | DjangoTemplates.py:9:18:9:25 | externally controlled string | -| DjangoTemplates.py:8:16:8:38 | externally controlled string | DjangoTemplates.py:9:18:9:25 | externally controlled string | -| FlaskTemplate.py:17:41:17:52 | dict of externally controlled string | FlaskTemplate.py:17:41:17:68 | externally controlled string | -| FlaskTemplate.py:17:41:17:52 | dict of externally controlled string | FlaskTemplate.py:17:41:17:68 | externally controlled string | -| JinjaSsti.py:7:7:7:13 | django.request.HttpRequest | JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | -| JinjaSsti.py:7:7:7:13 | django.request.HttpRequest | JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | -| JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | -| JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | -| JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | JinjaSsti.py:9:16:9:38 | externally controlled string | -| JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | JinjaSsti.py:9:16:9:38 | externally controlled string | -| JinjaSsti.py:9:16:9:38 | externally controlled string | JinjaSsti.py:10:25:10:32 | externally controlled string | -| JinjaSsti.py:9:16:9:38 | externally controlled string | JinjaSsti.py:10:25:10:32 | externally controlled string | -| JinjaSsti.py:16:7:16:13 | django.request.HttpRequest | JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | -| JinjaSsti.py:16:7:16:13 | django.request.HttpRequest | JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | -| JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | -| JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | -| JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | JinjaSsti.py:19:16:19:38 | externally controlled string | -| JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | JinjaSsti.py:19:16:19:38 | externally controlled string | -| JinjaSsti.py:19:16:19:38 | externally controlled string | JinjaSsti.py:20:28:20:35 | externally controlled string | -| JinjaSsti.py:19:16:19:38 | externally controlled string | JinjaSsti.py:20:28:20:35 | externally controlled string | -| MakoSsti.py:6:10:6:16 | django.request.HttpRequest | MakoSsti.py:8:16:8:22 | django.request.HttpRequest | -| MakoSsti.py:6:10:6:16 | django.request.HttpRequest | MakoSsti.py:8:16:8:22 | django.request.HttpRequest | -| MakoSsti.py:8:16:8:22 | django.request.HttpRequest | MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | -| MakoSsti.py:8:16:8:22 | django.request.HttpRequest | MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | -| MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | MakoSsti.py:8:16:8:38 | externally controlled string | -| MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | MakoSsti.py:8:16:8:38 | externally controlled string | -| MakoSsti.py:8:16:8:38 | externally controlled string | MakoSsti.py:9:27:9:34 | externally controlled string | -| MakoSsti.py:8:16:8:38 | externally controlled string | MakoSsti.py:9:27:9:34 | externally controlled string | -| TRender.py:5:13:5:19 | django.request.HttpRequest | TRender.py:6:16:6:22 | django.request.HttpRequest | -| TRender.py:5:13:5:19 | django.request.HttpRequest | TRender.py:6:16:6:22 | django.request.HttpRequest | -| TRender.py:6:16:6:22 | django.request.HttpRequest | TRender.py:6:16:6:26 | django.http.request.QueryDict | -| TRender.py:6:16:6:22 | django.request.HttpRequest | TRender.py:6:16:6:26 | django.http.request.QueryDict | -| TRender.py:6:16:6:26 | django.http.request.QueryDict | TRender.py:6:16:6:38 | externally controlled string | -| TRender.py:6:16:6:26 | django.http.request.QueryDict | TRender.py:6:16:6:38 | externally controlled string | -| TRender.py:6:16:6:38 | externally controlled string | TRender.py:7:24:7:31 | externally controlled string | -| TRender.py:6:16:6:38 | externally controlled string | TRender.py:7:24:7:31 | externally controlled string | -#select -| AirspeedSsti.py:11:30:11:37 | template | AirspeedSsti.py:10:16:10:27 | dict of externally controlled string | AirspeedSsti.py:11:30:11:37 | externally controlled string | This Template depends on $@. | AirspeedSsti.py:10:16:10:27 | Attribute | a user-provided value | -| ChevronSsti.py:11:27:11:34 | template | ChevronSsti.py:10:16:10:27 | dict of externally controlled string | ChevronSsti.py:11:27:11:34 | externally controlled string | This Template depends on $@. | ChevronSsti.py:10:16:10:27 | Attribute | a user-provided value | -| DjangoTemplates.py:9:18:9:25 | template | DjangoTemplates.py:6:8:6:14 | django.request.HttpRequest | DjangoTemplates.py:9:18:9:25 | externally controlled string | This Template depends on $@. | DjangoTemplates.py:6:8:6:14 | request | a user-provided value | -| FlaskTemplate.py:17:41:17:68 | Attribute() | FlaskTemplate.py:17:41:17:52 | dict of externally controlled string | FlaskTemplate.py:17:41:17:68 | externally controlled string | This Template depends on $@. | FlaskTemplate.py:17:41:17:52 | Attribute | a user-provided value | -| JinjaSsti.py:10:25:10:32 | template | JinjaSsti.py:7:7:7:13 | django.request.HttpRequest | JinjaSsti.py:10:25:10:32 | externally controlled string | This Template depends on $@. | JinjaSsti.py:7:7:7:13 | request | a user-provided value | -| JinjaSsti.py:20:28:20:35 | template | JinjaSsti.py:16:7:16:13 | django.request.HttpRequest | JinjaSsti.py:20:28:20:35 | externally controlled string | This Template depends on $@. | JinjaSsti.py:16:7:16:13 | request | a user-provided value | -| MakoSsti.py:9:27:9:34 | template | MakoSsti.py:6:10:6:16 | django.request.HttpRequest | MakoSsti.py:9:27:9:34 | externally controlled string | This Template depends on $@. | MakoSsti.py:6:10:6:16 | request | a user-provided value | -| TRender.py:7:24:7:31 | template | TRender.py:5:13:5:19 | django.request.HttpRequest | TRender.py:7:24:7:31 | externally controlled string | This Template depends on $@. | TRender.py:5:13:5:19 | request | a user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/options b/python/ql/test/experimental/query-tests/Security/CWE-074/options deleted file mode 100644 index 2f457593f2e..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-074/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --max-import-depth=3 -p ../../../../query-tests/Security/lib/ diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.expected new file mode 100644 index 00000000000..92ea83f4cdd --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.expected @@ -0,0 +1,114 @@ +edges +| xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | xslt.py:3:26:3:32 | GSSA Variable request | +| xslt.py:3:26:3:32 | GSSA Variable request | xslt.py:10:17:10:23 | ControlFlowNode for request | +| xslt.py:10:5:10:13 | SSA variable xsltQuery | xslt.py:11:27:11:35 | ControlFlowNode for xsltQuery | +| xslt.py:10:17:10:23 | ControlFlowNode for request | xslt.py:10:17:10:28 | ControlFlowNode for Attribute | +| xslt.py:10:17:10:28 | ControlFlowNode for Attribute | xslt.py:10:17:10:43 | ControlFlowNode for Attribute() | +| xslt.py:10:17:10:43 | ControlFlowNode for Attribute() | xslt.py:10:5:10:13 | SSA variable xsltQuery | +| xslt.py:11:5:11:13 | SSA variable xslt_root | xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | +| xslt.py:11:17:11:36 | ControlFlowNode for Attribute() | xslt.py:11:5:11:13 | SSA variable xslt_root | +| xslt.py:11:27:11:35 | ControlFlowNode for xsltQuery | xslt.py:11:17:11:36 | ControlFlowNode for Attribute() | +| xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:3:26:3:32 | GSSA Variable request | +| xsltInjection.py:3:26:3:32 | GSSA Variable request | xsltInjection.py:10:17:10:23 | ControlFlowNode for request | +| xsltInjection.py:3:26:3:32 | GSSA Variable request | xsltInjection.py:17:17:17:23 | ControlFlowNode for request | +| xsltInjection.py:3:26:3:32 | GSSA Variable request | xsltInjection.py:26:17:26:23 | ControlFlowNode for request | +| xsltInjection.py:3:26:3:32 | GSSA Variable request | xsltInjection.py:35:17:35:23 | ControlFlowNode for request | +| xsltInjection.py:3:26:3:32 | GSSA Variable request | xsltInjection.py:44:17:44:23 | ControlFlowNode for request | +| xsltInjection.py:10:5:10:13 | SSA variable xsltQuery | xsltInjection.py:11:27:11:35 | ControlFlowNode for xsltQuery | +| xsltInjection.py:10:17:10:23 | ControlFlowNode for request | xsltInjection.py:10:17:10:28 | ControlFlowNode for Attribute | +| xsltInjection.py:10:17:10:28 | ControlFlowNode for Attribute | xsltInjection.py:10:17:10:43 | ControlFlowNode for Attribute() | +| xsltInjection.py:10:17:10:43 | ControlFlowNode for Attribute() | xsltInjection.py:10:5:10:13 | SSA variable xsltQuery | +| xsltInjection.py:11:5:11:13 | SSA variable xslt_root | xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | +| xsltInjection.py:11:17:11:36 | ControlFlowNode for Attribute() | xsltInjection.py:11:5:11:13 | SSA variable xslt_root | +| xsltInjection.py:11:27:11:35 | ControlFlowNode for xsltQuery | xsltInjection.py:11:17:11:36 | ControlFlowNode for Attribute() | +| xsltInjection.py:17:5:17:13 | SSA variable xsltQuery | xsltInjection.py:18:27:18:35 | ControlFlowNode for xsltQuery | +| xsltInjection.py:17:17:17:23 | ControlFlowNode for request | xsltInjection.py:17:17:17:28 | ControlFlowNode for Attribute | +| xsltInjection.py:17:17:17:28 | ControlFlowNode for Attribute | xsltInjection.py:17:17:17:43 | ControlFlowNode for Attribute() | +| xsltInjection.py:17:17:17:43 | ControlFlowNode for Attribute() | xsltInjection.py:17:5:17:13 | SSA variable xsltQuery | +| xsltInjection.py:18:5:18:13 | SSA variable xslt_root | xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | +| xsltInjection.py:18:17:18:36 | ControlFlowNode for Attribute() | xsltInjection.py:18:5:18:13 | SSA variable xslt_root | +| xsltInjection.py:18:27:18:35 | ControlFlowNode for xsltQuery | xsltInjection.py:18:17:18:36 | ControlFlowNode for Attribute() | +| xsltInjection.py:26:5:26:13 | SSA variable xsltQuery | xsltInjection.py:27:27:27:35 | ControlFlowNode for xsltQuery | +| xsltInjection.py:26:17:26:23 | ControlFlowNode for request | xsltInjection.py:26:17:26:28 | ControlFlowNode for Attribute | +| xsltInjection.py:26:17:26:28 | ControlFlowNode for Attribute | xsltInjection.py:26:17:26:43 | ControlFlowNode for Attribute() | +| xsltInjection.py:26:17:26:43 | ControlFlowNode for Attribute() | xsltInjection.py:26:5:26:13 | SSA variable xsltQuery | +| xsltInjection.py:27:5:27:13 | SSA variable xslt_root | xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | +| xsltInjection.py:27:17:27:36 | ControlFlowNode for Attribute() | xsltInjection.py:27:5:27:13 | SSA variable xslt_root | +| xsltInjection.py:27:27:27:35 | ControlFlowNode for xsltQuery | xsltInjection.py:27:17:27:36 | ControlFlowNode for Attribute() | +| xsltInjection.py:35:5:35:13 | SSA variable xsltQuery | xsltInjection.py:36:34:36:42 | ControlFlowNode for xsltQuery | +| xsltInjection.py:35:17:35:23 | ControlFlowNode for request | xsltInjection.py:35:17:35:28 | ControlFlowNode for Attribute | +| xsltInjection.py:35:17:35:28 | ControlFlowNode for Attribute | xsltInjection.py:35:17:35:43 | ControlFlowNode for Attribute() | +| xsltInjection.py:35:17:35:43 | ControlFlowNode for Attribute() | xsltInjection.py:35:5:35:13 | SSA variable xsltQuery | +| xsltInjection.py:36:5:36:13 | SSA variable xslt_root | xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | +| xsltInjection.py:36:17:36:43 | ControlFlowNode for Attribute() | xsltInjection.py:36:5:36:13 | SSA variable xslt_root | +| xsltInjection.py:36:34:36:42 | ControlFlowNode for xsltQuery | xsltInjection.py:36:17:36:43 | ControlFlowNode for Attribute() | +| xsltInjection.py:44:5:44:13 | SSA variable xsltQuery | xsltInjection.py:45:5:45:15 | SSA variable xsltStrings | +| xsltInjection.py:44:17:44:23 | ControlFlowNode for request | xsltInjection.py:44:17:44:28 | ControlFlowNode for Attribute | +| xsltInjection.py:44:17:44:28 | ControlFlowNode for Attribute | xsltInjection.py:44:17:44:43 | ControlFlowNode for Attribute() | +| xsltInjection.py:44:17:44:43 | ControlFlowNode for Attribute() | xsltInjection.py:44:5:44:13 | SSA variable xsltQuery | +| xsltInjection.py:45:5:45:15 | SSA variable xsltStrings | xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings | +| xsltInjection.py:46:5:46:13 | SSA variable xslt_root | xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | +| xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | xsltInjection.py:46:5:46:13 | SSA variable xslt_root | +| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | +nodes +| xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| xslt.py:3:26:3:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| xslt.py:10:5:10:13 | SSA variable xsltQuery | semmle.label | SSA variable xsltQuery | +| xslt.py:10:17:10:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| xslt.py:10:17:10:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| xslt.py:10:17:10:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xslt.py:11:5:11:13 | SSA variable xslt_root | semmle.label | SSA variable xslt_root | +| xslt.py:11:17:11:36 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xslt.py:11:27:11:35 | ControlFlowNode for xsltQuery | semmle.label | ControlFlowNode for xsltQuery | +| xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root | +| xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| xsltInjection.py:3:26:3:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| xsltInjection.py:10:5:10:13 | SSA variable xsltQuery | semmle.label | SSA variable xsltQuery | +| xsltInjection.py:10:17:10:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| xsltInjection.py:10:17:10:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| xsltInjection.py:10:17:10:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:11:5:11:13 | SSA variable xslt_root | semmle.label | SSA variable xslt_root | +| xsltInjection.py:11:17:11:36 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:11:27:11:35 | ControlFlowNode for xsltQuery | semmle.label | ControlFlowNode for xsltQuery | +| xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root | +| xsltInjection.py:17:5:17:13 | SSA variable xsltQuery | semmle.label | SSA variable xsltQuery | +| xsltInjection.py:17:17:17:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| xsltInjection.py:17:17:17:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| xsltInjection.py:17:17:17:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:18:5:18:13 | SSA variable xslt_root | semmle.label | SSA variable xslt_root | +| xsltInjection.py:18:17:18:36 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:18:27:18:35 | ControlFlowNode for xsltQuery | semmle.label | ControlFlowNode for xsltQuery | +| xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root | +| xsltInjection.py:26:5:26:13 | SSA variable xsltQuery | semmle.label | SSA variable xsltQuery | +| xsltInjection.py:26:17:26:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| xsltInjection.py:26:17:26:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| xsltInjection.py:26:17:26:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:27:5:27:13 | SSA variable xslt_root | semmle.label | SSA variable xslt_root | +| xsltInjection.py:27:17:27:36 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:27:27:27:35 | ControlFlowNode for xsltQuery | semmle.label | ControlFlowNode for xsltQuery | +| xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root | +| xsltInjection.py:35:5:35:13 | SSA variable xsltQuery | semmle.label | SSA variable xsltQuery | +| xsltInjection.py:35:17:35:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| xsltInjection.py:35:17:35:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| xsltInjection.py:35:17:35:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:36:5:36:13 | SSA variable xslt_root | semmle.label | SSA variable xslt_root | +| xsltInjection.py:36:17:36:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:36:34:36:42 | ControlFlowNode for xsltQuery | semmle.label | ControlFlowNode for xsltQuery | +| xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root | +| xsltInjection.py:44:5:44:13 | SSA variable xsltQuery | semmle.label | SSA variable xsltQuery | +| xsltInjection.py:44:17:44:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| xsltInjection.py:44:17:44:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| xsltInjection.py:44:17:44:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:45:5:45:15 | SSA variable xsltStrings | semmle.label | SSA variable xsltStrings | +| xsltInjection.py:46:5:46:13 | SSA variable xslt_root | semmle.label | SSA variable xslt_root | +| xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings | semmle.label | ControlFlowNode for xsltStrings | +| xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root | +subpaths +#select +| xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.qlref new file mode 100644 index 00000000000..4d432d461ca --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-091/XsltInjection.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091/xslt.py b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xslt.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-091/xslt.py rename to python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xslt.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091/xsltInjection.py b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xsltInjection.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-091/xsltInjection.py rename to python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xsltInjection.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091/Xslt.expected b/python/ql/test/experimental/query-tests/Security/CWE-091/Xslt.expected deleted file mode 100644 index 89f19160f69..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-091/Xslt.expected +++ /dev/null @@ -1,47 +0,0 @@ -edges -| xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:10:17:10:43 | etree.XML string | -| xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:10:17:10:43 | etree.XML string | -| xslt.py:10:17:10:43 | etree.XML string | xslt.py:11:27:11:35 | etree.XML string | -| xslt.py:10:17:10:43 | etree.XML string | xslt.py:11:27:11:35 | etree.XML string | -| xslt.py:11:17:11:36 | lxml etree xml | xslt.py:14:29:14:37 | lxml etree xml | -| xslt.py:11:17:11:36 | lxml etree xml | xslt.py:14:29:14:37 | lxml etree xml | -| xslt.py:11:27:11:35 | etree.XML string | xslt.py:11:17:11:36 | lxml etree xml | -| xslt.py:11:27:11:35 | etree.XML string | xslt.py:11:17:11:36 | lxml etree xml | -| xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:10:17:10:43 | etree.XML string | -| xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:10:17:10:43 | etree.XML string | -| xsltInjection.py:10:17:10:43 | etree.XML string | xsltInjection.py:11:27:11:35 | etree.XML string | -| xsltInjection.py:10:17:10:43 | etree.XML string | xsltInjection.py:11:27:11:35 | etree.XML string | -| xsltInjection.py:11:17:11:36 | lxml etree xml | xsltInjection.py:12:28:12:36 | lxml etree xml | -| xsltInjection.py:11:17:11:36 | lxml etree xml | xsltInjection.py:12:28:12:36 | lxml etree xml | -| xsltInjection.py:11:27:11:35 | etree.XML string | xsltInjection.py:11:17:11:36 | lxml etree xml | -| xsltInjection.py:11:27:11:35 | etree.XML string | xsltInjection.py:11:17:11:36 | lxml etree xml | -| xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:17:17:17:43 | etree.XML string | -| xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:17:17:17:43 | etree.XML string | -| xsltInjection.py:17:17:17:43 | etree.XML string | xsltInjection.py:18:27:18:35 | etree.XML string | -| xsltInjection.py:17:17:17:43 | etree.XML string | xsltInjection.py:18:27:18:35 | etree.XML string | -| xsltInjection.py:18:17:18:36 | lxml etree xml | xsltInjection.py:21:29:21:37 | lxml etree xml | -| xsltInjection.py:18:17:18:36 | lxml etree xml | xsltInjection.py:21:29:21:37 | lxml etree xml | -| xsltInjection.py:18:27:18:35 | etree.XML string | xsltInjection.py:18:17:18:36 | lxml etree xml | -| xsltInjection.py:18:27:18:35 | etree.XML string | xsltInjection.py:18:17:18:36 | lxml etree xml | -| xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:26:17:26:43 | etree.XML string | -| xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:26:17:26:43 | etree.XML string | -| xsltInjection.py:26:17:26:43 | etree.XML string | xsltInjection.py:27:27:27:35 | etree.XML string | -| xsltInjection.py:26:17:26:43 | etree.XML string | xsltInjection.py:27:27:27:35 | etree.XML string | -| xsltInjection.py:27:17:27:36 | lxml etree xml | xsltInjection.py:31:24:31:32 | lxml etree xml | -| xsltInjection.py:27:17:27:36 | lxml etree xml | xsltInjection.py:31:24:31:32 | lxml etree xml | -| xsltInjection.py:27:27:27:35 | etree.XML string | xsltInjection.py:27:17:27:36 | lxml etree xml | -| xsltInjection.py:27:27:27:35 | etree.XML string | xsltInjection.py:27:17:27:36 | lxml etree xml | -| xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:35:17:35:43 | etree.XML string | -| xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:35:17:35:43 | etree.XML string | -| xsltInjection.py:35:17:35:43 | etree.XML string | xsltInjection.py:36:34:36:42 | etree.XML string | -| xsltInjection.py:35:17:35:43 | etree.XML string | xsltInjection.py:36:34:36:42 | etree.XML string | -| xsltInjection.py:36:17:36:43 | lxml etree xml | xsltInjection.py:40:24:40:32 | lxml etree xml | -| xsltInjection.py:36:17:36:43 | lxml etree xml | xsltInjection.py:40:24:40:32 | lxml etree xml | -| xsltInjection.py:36:34:36:42 | etree.XML string | xsltInjection.py:36:17:36:43 | lxml etree xml | -| xsltInjection.py:36:34:36:42 | etree.XML string | xsltInjection.py:36:17:36:43 | lxml etree xml | -#select -| xslt.py:14:29:14:37 | xslt_root | xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:14:29:14:37 | lxml etree xml | This XSLT query depends on $@. | xslt.py:10:17:10:28 | Attribute | a user-provided value | -| xsltInjection.py:12:28:12:36 | xslt_root | xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:12:28:12:36 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:10:17:10:28 | Attribute | a user-provided value | -| xsltInjection.py:21:29:21:37 | xslt_root | xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:21:29:21:37 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:17:17:17:28 | Attribute | a user-provided value | -| xsltInjection.py:31:24:31:32 | xslt_root | xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:31:24:31:32 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:26:17:26:28 | Attribute | a user-provided value | -| xsltInjection.py:40:24:40:32 | xslt_root | xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:40:24:40:32 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:35:17:35:28 | Attribute | a user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091/Xslt.qlref b/python/ql/test/experimental/query-tests/Security/CWE-091/Xslt.qlref deleted file mode 100644 index 988d13e98a6..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-091/Xslt.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE-091/Xslt.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091/XsltSinks.expected b/python/ql/test/experimental/query-tests/Security/CWE-091/XsltSinks.expected deleted file mode 100644 index 7150b3046e2..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-091/XsltSinks.expected +++ /dev/null @@ -1,12 +0,0 @@ -| xslt.py:14:29:14:37 | lxml.etree.parse.xslt | lxml etree xml | -| xsltInjection.py:12:28:12:36 | lxml.etree.XSLT | lxml etree xml | -| xsltInjection.py:21:29:21:37 | lxml.etree.parse.xslt | lxml etree xml | -| xsltInjection.py:31:24:31:32 | lxml.etree.parse.xslt | lxml etree xml | -| xsltInjection.py:40:24:40:32 | lxml.etree.parse.xslt | lxml etree xml | -| xsltInjection.py:50:24:50:32 | lxml.etree.parse.xslt | lxml etree xml | -| xsltInjection.py:60:24:60:32 | lxml.etree.parse.xslt | lxml etree xml | -| xsltInjection.py:69:24:69:32 | lxml.etree.parse.xslt | lxml etree xml | -| xsltInjection.py:79:24:79:32 | lxml.etree.parse.xslt | lxml etree xml | -| xsltSinks.py:17:28:17:36 | lxml.etree.XSLT | lxml etree xml | -| xsltSinks.py:30:29:30:37 | lxml.etree.parse.xslt | lxml etree xml | -| xsltSinks.py:44:24:44:32 | lxml.etree.parse.xslt | lxml etree xml | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091/XsltSinks.ql b/python/ql/test/experimental/query-tests/Security/CWE-091/XsltSinks.ql deleted file mode 100644 index 6ce8fdc4fb5..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-091/XsltSinks.ql +++ /dev/null @@ -1,6 +0,0 @@ -import python -import experimental.semmle.python.security.injection.XSLT - -from XsltInjection::XsltInjectionSink sink, TaintKind kind -where sink.sinks(kind) -select sink, kind diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091/options b/python/ql/test/experimental/query-tests/Security/CWE-091/options deleted file mode 100644 index 2f457593f2e..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-091/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --max-import-depth=3 -p ../../../../query-tests/Security/lib/ diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091/xsltSinks.py b/python/ql/test/experimental/query-tests/Security/CWE-091/xsltSinks.py deleted file mode 100644 index a82fc0c6c5f..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-091/xsltSinks.py +++ /dev/null @@ -1,56 +0,0 @@ -from lxml import etree -from io import StringIO - -from django.urls import path -from django.http import HttpResponse -from django.template import Template, Context, Engine, engines - - -def a(request): - xslt_root = etree.XML('''\ - - - - - ''') - transform = etree.XSLT(xslt_root) - - -def b(request): - xslt_root = etree.XML('''\ - - - - - ''') - f = StringIO('') - tree = etree.parse(f) - result_tree = tree.xslt(xslt_root) - - -def c(request): - xslt_root = etree.XML('''\ - - - - - ''') - - f = StringIO('') - tree = etree.parse(f) - result = tree.xslt(xslt_root, a="'A'") - - -urlpatterns = [ - path('a', a), - path('b', b), - path('c', c) -] - -if __name__ == "__main__": - a(None) - b(None) - c(None) diff --git a/python/ql/test/experimental/semmle/python/templates/Airspeed.py b/python/ql/test/experimental/semmle/python/templates/Airspeed.py deleted file mode 100644 index a41d70432a0..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/Airspeed.py +++ /dev/null @@ -1,10 +0,0 @@ -from bottle import Bottle, route, request, redirect, response -import airspeed - - -app = Bottle() - - -@route('/other') -def a(): - return airspeed.Template("sink") diff --git a/python/ql/test/experimental/semmle/python/templates/AirspeedSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/AirspeedSSTISinks.expected deleted file mode 100644 index e938211434c..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/AirspeedSSTISinks.expected +++ /dev/null @@ -1,2 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (AirspeedSSTISinks.ql:4,6-14) -| Airspeed.py:10:30:10:35 | argument to airspeed.Template() | diff --git a/python/ql/test/experimental/semmle/python/templates/AirspeedSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/AirspeedSSTISinks.ql deleted file mode 100644 index e9c51ef11ad..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/AirspeedSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.Airspeed - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/Bottle.py b/python/ql/test/experimental/semmle/python/templates/Bottle.py deleted file mode 100644 index f6b2fec090e..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/Bottle.py +++ /dev/null @@ -1,17 +0,0 @@ -from bottle import Bottle, route, request, redirect, response, SimpleTemplate -from bottle import template as temp - - -app = Bottle() - - -@route('/other') -def a(): - template = "test" - tpl = SimpleTemplate(template) - - -@route('/other2') -def b(): - template = "test" - return temp(template, name='World') diff --git a/python/ql/test/experimental/semmle/python/templates/BottleSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/BottleSSTISinks.expected deleted file mode 100644 index 1802708c2de..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/BottleSSTISinks.expected +++ /dev/null @@ -1,3 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (BottleSSTISinks.ql:4,6-14) -| Bottle.py:11:26:11:33 | argument to bottle.SimpleTemplate() | -| Bottle.py:17:17:17:24 | argument to bottle.template() | diff --git a/python/ql/test/experimental/semmle/python/templates/BottleSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/BottleSSTISinks.ql deleted file mode 100644 index c0ba59ef957..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/BottleSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.Bottle - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/Chameleon.py b/python/ql/test/experimental/semmle/python/templates/Chameleon.py deleted file mode 100644 index 6d96f0752a9..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/Chameleon.py +++ /dev/null @@ -1,5 +0,0 @@ -from chameleon import PageTemplate - - -def chameleon(): - template = PageTemplate("sink") diff --git a/python/ql/test/experimental/semmle/python/templates/ChameleonSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/ChameleonSSTISinks.expected deleted file mode 100644 index d6a46986f11..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/ChameleonSSTISinks.expected +++ /dev/null @@ -1,2 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (ChameleonSSTISinks.ql:4,6-14) -| Chameleon.py:5:29:5:34 | argument to Chameleon.PageTemplate() | diff --git a/python/ql/test/experimental/semmle/python/templates/ChameleonSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/ChameleonSSTISinks.ql deleted file mode 100644 index ee9d41434af..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/ChameleonSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.Chameleon - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/CheetahSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/CheetahSSTISinks.expected deleted file mode 100644 index 3971b25e356..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/CheetahSSTISinks.expected +++ /dev/null @@ -1,3 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (CheetahSSTISinks.ql:4,6-14) -| CheetahSinks.py:10:21:10:26 | argument to Cheetah.Template.Template() | -| CheetahSinks.py:20:20:20:25 | argument to Cheetah.Template.Template() | diff --git a/python/ql/test/experimental/semmle/python/templates/CheetahSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/CheetahSSTISinks.ql deleted file mode 100644 index 10c6c79a4d5..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/CheetahSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.Cheetah - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/CheetahSinks.py b/python/ql/test/experimental/semmle/python/templates/CheetahSinks.py deleted file mode 100644 index 0bb3364a178..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/CheetahSinks.py +++ /dev/null @@ -1,20 +0,0 @@ -from bottle import Bottle, route, request, redirect, response, SimpleTemplate -from Cheetah.Template import Template - - -app = Bottle() - - -@route('/other') -def a(): - return Template("sink") - - -class Template3(Template): - title = 'Hello World Example!' - contents = 'Hello World!' - - -@route('/other2') -def b(): - t3 = Template3("sink") diff --git a/python/ql/test/experimental/semmle/python/templates/ChevronSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/ChevronSSTISinks.expected deleted file mode 100644 index 50ebb008209..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/ChevronSSTISinks.expected +++ /dev/null @@ -1,2 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (ChevronSSTISinks.ql:4,6-14) -| ChevronSinks.py:10:27:10:32 | argument to chevron.render() | diff --git a/python/ql/test/experimental/semmle/python/templates/ChevronSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/ChevronSSTISinks.ql deleted file mode 100644 index 545c1f8f79a..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/ChevronSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.Chevron - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/ChevronSinks.py b/python/ql/test/experimental/semmle/python/templates/ChevronSinks.py deleted file mode 100644 index 26d35708bb6..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/ChevronSinks.py +++ /dev/null @@ -1,22 +0,0 @@ -from bottle import Bottle, route, request, redirect, response, SimpleTemplate -import chevron - - -app = Bottle() - - -@route('/other') -def a(): - return chevron.render("sink", {"key": "value"}) - - -@route('/other2') -def b(): - sink = { - 'template': "template", - - 'data': { - 'key': 'value' - } - } - return chevron.render(**sink) diff --git a/python/ql/test/experimental/semmle/python/templates/DjangoSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/DjangoSSTISinks.expected deleted file mode 100644 index a38fdbc323f..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/DjangoSSTISinks.expected +++ /dev/null @@ -1,2 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (DjangoSSTISinks.ql:4,6-14) -| DjangoTemplates.py:9:18:9:25 | argument to Django.template() | diff --git a/python/ql/test/experimental/semmle/python/templates/DjangoSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/DjangoSSTISinks.ql deleted file mode 100644 index eecd31aeb87..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/DjangoSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.DjangoTemplate - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/DjangoTemplates.py b/python/ql/test/experimental/semmle/python/templates/DjangoTemplates.py deleted file mode 100644 index 981109bf7dc..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/DjangoTemplates.py +++ /dev/null @@ -1,39 +0,0 @@ -from django.urls import path -from django.http import HttpResponse -from django.template import Template, Context, Engine, engines - - -def dj(request): - # Load the template - template = request.GET['template'] - t = Template(template) - ctx = Context(locals()) - html = t.render(ctx) - return HttpResponse(html) - - -def djEngine(request): - # Load the template - template = request.GET['template'] - - django_engine = engines['django'] - t = django_engine.from_string(template) - ctx = Context(locals()) - html = t.render(ctx) - return HttpResponse(html) - - -def djEngineJinja(request): - # Load the template - template = request.GET['template'] - - django_engine = engines['jinja'] - t = django_engine.from_string(template) - ctx = Context(locals()) - html = t.render(ctx) - return HttpResponse(html) - - -urlpatterns = [ - path('', dj) -] diff --git a/python/ql/test/experimental/semmle/python/templates/Genshi.py b/python/ql/test/experimental/semmle/python/templates/Genshi.py deleted file mode 100644 index 7c46a2b31dc..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/Genshi.py +++ /dev/null @@ -1,10 +0,0 @@ - - -def genshi1(): - from genshi.template import MarkupTemplate - tmpl = MarkupTemplate('sink') - - -def genshi2(): - from genshi.template import TextTemplate - tmpl = TextTemplate('sink') \ No newline at end of file diff --git a/python/ql/test/experimental/semmle/python/templates/GenshiSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/GenshiSSTISinks.expected deleted file mode 100644 index cfc22364413..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/GenshiSSTISinks.expected +++ /dev/null @@ -1,3 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (GenshiSSTISinks.ql:4,6-14) -| Genshi.py:5:27:5:32 | argument to genshi.template.MarkupTemplate() | -| Genshi.py:10:25:10:30 | argument to genshi.template.TextTemplate() | diff --git a/python/ql/test/experimental/semmle/python/templates/GenshiSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/GenshiSSTISinks.ql deleted file mode 100644 index f0d87e97ec1..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/GenshiSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.Genshi - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/Jinja2Templates.py b/python/ql/test/experimental/semmle/python/templates/Jinja2Templates.py deleted file mode 100644 index e52538d4946..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/Jinja2Templates.py +++ /dev/null @@ -1,17 +0,0 @@ -from jinja2 import Template as Jinja2_Template -from jinja2 import Environment, DictLoader, escape - - -def jinja(): - t = Jinja2_Template("sink") - - -def jinja2(): - random = "esdad" + "asdad" - t = Jinja2_Template(random) - - -def jinja3(): - random = 1234 - t = Jinja2_Template("sink"+random) - diff --git a/python/ql/test/experimental/semmle/python/templates/JinjaSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/JinjaSSTISinks.expected deleted file mode 100644 index 7b91c934947..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/JinjaSSTISinks.expected +++ /dev/null @@ -1,4 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (JinjaSSTISinks.ql:4,6-14) -| Jinja2Templates.py:6:25:6:30 | argument to jinja2.Template() | -| Jinja2Templates.py:11:25:11:30 | argument to jinja2.Template() | -| Jinja2Templates.py:16:25:16:37 | argument to jinja2.Template() | diff --git a/python/ql/test/experimental/semmle/python/templates/JinjaSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/JinjaSSTISinks.ql deleted file mode 100644 index ca80d8bc570..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/JinjaSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.Jinja - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/Mako.py b/python/ql/test/experimental/semmle/python/templates/Mako.py deleted file mode 100644 index 3af60b164ea..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/Mako.py +++ /dev/null @@ -1,5 +0,0 @@ - - -def mako(): - from mako.template import Template - mytemplate = Template("sink") diff --git a/python/ql/test/experimental/semmle/python/templates/MakoSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/MakoSSTISinks.expected deleted file mode 100644 index 005e14f218a..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/MakoSSTISinks.expected +++ /dev/null @@ -1,2 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (MakoSSTISinks.ql:4,6-14) -| Mako.py:5:27:5:32 | argument to mako.template.Template() | diff --git a/python/ql/test/experimental/semmle/python/templates/MakoSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/MakoSSTISinks.ql deleted file mode 100644 index eed89420c54..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/MakoSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.Mako - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/TRender.py b/python/ql/test/experimental/semmle/python/templates/TRender.py deleted file mode 100644 index 6ed5a799942..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/TRender.py +++ /dev/null @@ -1,6 +0,0 @@ - - -def trender(): - from trender import TRender - template = '@greet world!' - compiled = TRender(template) diff --git a/python/ql/test/experimental/semmle/python/templates/TRenderSSTISinks.expected b/python/ql/test/experimental/semmle/python/templates/TRenderSSTISinks.expected deleted file mode 100644 index 26dea55a6c8..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/TRenderSSTISinks.expected +++ /dev/null @@ -1,2 +0,0 @@ -WARNING: Type SSTISink has been deprecated and may be removed in future (TRenderSSTISinks.ql:4,6-14) -| TRender.py:6:24:6:31 | argument to trender.TRender() | diff --git a/python/ql/test/experimental/semmle/python/templates/TRenderSSTISinks.ql b/python/ql/test/experimental/semmle/python/templates/TRenderSSTISinks.ql deleted file mode 100644 index ec3a1bba57f..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/TRenderSSTISinks.ql +++ /dev/null @@ -1,5 +0,0 @@ -import python -import experimental.semmle.python.templates.TRender - -from SSTISink s -select s diff --git a/python/ql/test/experimental/semmle/python/templates/options b/python/ql/test/experimental/semmle/python/templates/options deleted file mode 100644 index c3bc9413072..00000000000 --- a/python/ql/test/experimental/semmle/python/templates/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --lang=3 --max-import-depth=3 -p ../../../../../query-tests/Security/lib/ diff --git a/python/ql/test/library-tests/frameworks/data/test.ext.yml b/python/ql/test/library-tests/frameworks/data/test.ext.yml new file mode 100644 index 00000000000..f3606ebd49f --- /dev/null +++ b/python/ql/test/library-tests/frameworks/data/test.ext.yml @@ -0,0 +1,76 @@ +extensions: + # Contribute empty data sets to avoid errors about an undefined extensionals + - addsTo: + pack: codeql/python-all + extensible: sourceModel + data: + - ["testlib", "Member[getSource].ReturnValue", "test-source"] + - ["testlib.Alias", "", "test-source"] + # testing parameter syntax + - ["testlib", "Member[Callbacks].Member[first].Argument[0].Parameter[0]", "test-source"] + - ["testlib", "Member[Callbacks].Member[param1to3].Argument[0].Parameter[1..3]", "test-source"] + - ["testlib", "Member[Callbacks].Member[nonFirst].Argument[0].Parameter[1..]", "test-source"] + # Common tokens. + - ["testlib", "Member[CommonTokens].Member[makePromise].ReturnValue.Awaited", "test-source"] + - ["testlib", "Member[CommonTokens].Member[Class].Instance", "test-source"] + - ["testlib", "Member[CommonTokens].Member[Super].Subclass.Instance", "test-source"] + # method + - ["testlib", "Member[CommonTokens].Member[Class].Instance.Method[foo]", "test-source"] + # testing non-positional arguments + - ["testlib", "Member[ArgPos].Member[MyClass].Subclass.Member[foo].Parameter[self]", "test-source"] + - ["testlib", "Member[ArgPos].Member[MyClass].Subclass.Member[foo].Parameter[named:]", "test-source"] + - ["testlib", "Member[ArgPos].Member[MyClass].Subclass.Member[secondAndAfter].Parameter[1..]", "test-source"] + - ["testlib", "Member[ArgPos].Member[MyClass].Subclass.Member[otherSelfTest].Parameter[0]", "test-source"] + - ["testlib", "Member[ArgPos].Member[MyClass].Subclass.Member[anyParam].Parameter[any]", "test-source"] + - ["testlib", "Member[ArgPos].Member[MyClass].Subclass.Member[anyNamed].Parameter[any-named]", "test-source"] + + - addsTo: + pack: codeql/python-all + extensible: sinkModel + data: + - ["testlib", "Member[mySink].Argument[0,sinkName:]", "test-sink"] + # testing argument syntax + - ["testlib", "Member[Args].Member[arg0].Argument[0]", "test-sink"] + - ["testlib", "Member[Args].Member[arg1to3].Argument[1..3]", "test-sink"] + - ["testlib", "Member[Args].Member[lastarg].Argument[N-1]", "test-sink"] + - ["testlib", "Member[Args].Member[nonFist].Argument[1..]", "test-sink"] + # callsite filter. + - ["testlib", "Member[CallFilter].Member[arityOne].WithArity[1].Argument[any]", "test-sink"] + - ["testlib", "Member[CallFilter].Member[twoOrMore].WithArity[2..].Argument[0..]", "test-sink"] + # testing non-positional arguments + - ["testlib", "Member[ArgPos].Instance.Member[self_thing].Argument[self]", "test-sink"] + # any argument + - ["testlib", "Member[ArgPos].Member[anyParam].Argument[any]", "test-sink"] + - ["testlib", "Member[ArgPos].Member[anyNamed].Argument[any-named]", "test-sink"] + # testing package syntax + - ["foo1.bar", "Member[baz1].Argument[any]", "test-sink"] + - ["foo2", "Member[bar].Member[baz2].Argument[any]", "test-sink"] + # testing fuzzy + - ["testlib", "Fuzzy.Member[fuzzyCall].Argument[0]", "test-sink"] + # testing syntax errors + - ["testlib", "Member[foo],Member[bar]", "test-sink"] + - ["testlib", "Member[foo] Member[bar]", "test-sink"] + - ["testlib", "Member[foo]. Member[bar]", "test-sink"] + - ["testlib", "Member[foo], Member[bar]", "test-sink"] + - ["testlib", "Member[foo]..Member[bar]", "test-sink"] + - ["testlib", "Member[foo] .Member[bar]", "test-sink"] + - ["testlib", "Member[foo]Member[bar]", "test-sink"] + - ["testlib", "Member[foo", "test-sink"] + - ["testlib", "Member[foo]]", "test-sink"] + - ["testlib", "Member[foo]].Member[bar]", "test-sink"] + + - addsTo: + pack: codeql/python-all + extensible: summaryModel + data: + - ["testlib", "Member[Steps].Member[preserveTaint].Call", "Argument[0]", "ReturnValue", "taint"] + - ["testlib", "Member[Steps].Member[taintIntoCallback]", "Argument[0]", "Argument[1..2].Parameter[0]", "taint"] + - ["testlib", "Member[Steps].Member[preserveArgZeroAndTwo]", "Argument[0,2]", "ReturnValue", "taint"] + - ["testlib", "Member[Steps].Member[preserveAllButFirstArgument].Call", "Argument[1..]", "ReturnValue", "taint"] + + - addsTo: + pack: codeql/python-all + extensible: typeModel + data: + - ["testlib.Alias", "testlib", "Member[alias].ReturnValue"] + - ["testlib.Alias", "testlib.Alias", "Member[chain].ReturnValue"] diff --git a/python/ql/test/library-tests/frameworks/data/test.ql b/python/ql/test/library-tests/frameworks/data/test.ql index d9f270e6caf..6dbda311fa7 100644 --- a/python/ql/test/library-tests/frameworks/data/test.ql +++ b/python/ql/test/library-tests/frameworks/data/test.ql @@ -5,86 +5,6 @@ import semmle.python.dataflow.new.TaintTracking import semmle.python.dataflow.new.DataFlow private import semmle.python.ApiGraphs -class Steps extends ModelInput::SummaryModelCsv { - override predicate row(string row) { - // type;path;input;output;kind - row = - [ - "testlib;Member[Steps].Member[preserveTaint].Call;Argument[0];ReturnValue;taint", - "testlib;Member[Steps].Member[taintIntoCallback];Argument[0];Argument[1..2].Parameter[0];taint", - "testlib;Member[Steps].Member[preserveArgZeroAndTwo];Argument[0,2];ReturnValue;taint", - "testlib;Member[Steps].Member[preserveAllButFirstArgument].Call;Argument[1..];ReturnValue;taint", - ] - } -} - -class Types extends ModelInput::TypeModelCsv { - override predicate row(string row) { - // type1;type2;path - row = - [ - "testlib.Alias;testlib;Member[alias].ReturnValue", - "testlib.Alias;testlib.Alias;Member[chain].ReturnValue", - ] - } -} - -class Sinks extends ModelInput::SinkModelCsv { - override predicate row(string row) { - // type;path;kind - row = - [ - "testlib;Member[mySink].Argument[0,sinkName:];test-sink", - // testing argument syntax - "testlib;Member[Args].Member[arg0].Argument[0];test-sink", // - "testlib;Member[Args].Member[arg1to3].Argument[1..3];test-sink", // - "testlib;Member[Args].Member[lastarg].Argument[N-1];test-sink", // - "testlib;Member[Args].Member[nonFist].Argument[1..];test-sink", // - // callsite filter. - "testlib;Member[CallFilter].Member[arityOne].WithArity[1].Argument[any];test-sink", // - "testlib;Member[CallFilter].Member[twoOrMore].WithArity[2..].Argument[0..];test-sink", // - // testing non-positional arguments - "testlib;Member[ArgPos].Instance.Member[self_thing].Argument[self];test-sink", // - // any argument - "testlib;Member[ArgPos].Member[anyParam].Argument[any];test-sink", // - "testlib;Member[ArgPos].Member[anyNamed].Argument[any-named];test-sink", // - // testing package syntax - "foo1.bar;Member[baz1].Argument[any];test-sink", // - "foo2;Member[bar].Member[baz2].Argument[any];test-sink", // - // testing fuzzy - "testlib;Fuzzy.Member[fuzzyCall].Argument[0];test-sink", // - ] - } -} - -class Sources extends ModelInput::SourceModelCsv { - // type;path;kind - override predicate row(string row) { - row = - [ - "testlib;Member[getSource].ReturnValue;test-source", // - "testlib.Alias;;test-source", - // testing parameter syntax - "testlib;Member[Callbacks].Member[first].Argument[0].Parameter[0];test-source", // - "testlib;Member[Callbacks].Member[param1to3].Argument[0].Parameter[1..3];test-source", // - "testlib;Member[Callbacks].Member[nonFirst].Argument[0].Parameter[1..];test-source", // - // Common tokens. - "testlib;Member[CommonTokens].Member[makePromise].ReturnValue.Awaited;test-source", // - "testlib;Member[CommonTokens].Member[Class].Instance;test-source", // - "testlib;Member[CommonTokens].Member[Super].Subclass.Instance;test-source", // - // method - "testlib;Member[CommonTokens].Member[Class].Instance.Method[foo];test-source", // - // testing non-positional arguments - "testlib;Member[ArgPos].Member[MyClass].Subclass.Member[foo].Parameter[self];test-source", // - "testlib;Member[ArgPos].Member[MyClass].Subclass.Member[foo].Parameter[named:];test-source", // - "testlib;Member[ArgPos].Member[MyClass].Subclass.Member[secondAndAfter].Parameter[1..];test-source", // - "testlib;Member[ArgPos].Member[MyClass].Subclass.Member[otherSelfTest].Parameter[0];test-source", // - "testlib;Member[ArgPos].Member[MyClass].Subclass.Member[anyParam].Parameter[any];test-source", // - "testlib;Member[ArgPos].Member[MyClass].Subclass.Member[anyNamed].Parameter[any-named];test-source", // - ] - } -} - class BasicTaintTracking extends TaintTracking::Configuration { BasicTaintTracking() { this = "BasicTaintTracking" } @@ -109,24 +29,6 @@ query predicate isSource(DataFlow::Node node, string kind) { node = ModelOutput::getASourceNode(kind).asSource() } -class SyntaxErrorTest extends ModelInput::SinkModelCsv { - override predicate row(string row) { - row = - [ - "testlib;Member[foo],Member[bar];test-sink", // - "testlib;Member[foo] Member[bar];test-sink", // - "testlib;Member[foo]. Member[bar];test-sink", // - "testlib;Member[foo], Member[bar];test-sink", // - "testlib;Member[foo]..Member[bar];test-sink", // - "testlib;Member[foo] .Member[bar];test-sink", // - "testlib;Member[foo]Member[bar];test-sink", // - "testlib;Member[foo;test-sink", // - "testlib;Member[foo]];test-sink", // - "testlib;Member[foo]].Member[bar];test-sink", // - ] - } -} - query predicate syntaxErrors(AccessPathSyntax::AccessPath path) { path.hasSyntaxError() } query predicate warning = ModelOutput::getAWarning/0; diff --git a/python/ql/test/library-tests/frameworks/flask/response_test.py b/python/ql/test/library-tests/frameworks/flask/response_test.py index 39373eac9fe..03c4c9054b0 100644 --- a/python/ql/test/library-tests/frameworks/flask/response_test.py +++ b/python/ql/test/library-tests/frameworks/flask/response_test.py @@ -67,6 +67,14 @@ def html8(): # $requestHandler @app.route("/jsonify") # $routeSetup="/jsonify" def jsonify_route(): # $requestHandler x = "x"; y = "y"; z = "z" + if True: + import flask.json + resp = flask.json.jsonify(x, y, z=z) # $HttpResponse mimetype=application/json responseBody=x responseBody=y responseBody=z + assert resp.mimetype == "application/json" + + resp = app.json.response(x, y, z=z) # $HttpResponse mimetype=application/json responseBody=x responseBody=y responseBody=z + assert resp.mimetype == "application/json" + resp = jsonify(x, y, z=z) # $ HttpResponse mimetype=application/json responseBody=x responseBody=y responseBody=z return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp diff --git a/python/ql/test/library-tests/regex/Characters.expected b/python/ql/test/library-tests/regex/Characters.expected index a1f036dce0d..7a1ca9c874f 100644 --- a/python/ql/test/library-tests/regex/Characters.expected +++ b/python/ql/test/library-tests/regex/Characters.expected @@ -36,7 +36,6 @@ | (?:[^%]\|^)?%\\((\\w*)\\)[a-z] | 22 | 23 | | (?:[^%]\|^)?%\\((\\w*)\\)[a-z] | 24 | 25 | | (?P[\\w]+)\| | 10 | 12 | -| (?m)^(?!$) | 2 | 3 | | (?m)^(?!$) | 4 | 5 | | (?m)^(?!$) | 8 | 9 | | (\\033\|~{) | 1 | 5 | diff --git a/python/ql/test/library-tests/regex/FirstLast.expected b/python/ql/test/library-tests/regex/FirstLast.expected index eff70714449..e388e0d1fdf 100644 --- a/python/ql/test/library-tests/regex/FirstLast.expected +++ b/python/ql/test/library-tests/regex/FirstLast.expected @@ -22,7 +22,8 @@ | (?P[\\w]+)\| | first | 9 | 14 | | (?P[\\w]+)\| | last | 9 | 13 | | (?P[\\w]+)\| | last | 9 | 14 | -| (?m)^(?!$) | first | 2 | 3 | +| (?m)^(?!$) | first | 4 | 5 | +| (?m)^(?!$) | first | 8 | 9 | | (?m)^(?!$) | last | 4 | 5 | | (?m)^(?!$) | last | 8 | 9 | | (\\033\|~{) | first | 1 | 5 | diff --git a/python/ql/test/library-tests/regex/GroupContents.expected b/python/ql/test/library-tests/regex/GroupContents.expected index 0174acb78b0..c7c4ac97a1e 100644 --- a/python/ql/test/library-tests/regex/GroupContents.expected +++ b/python/ql/test/library-tests/regex/GroupContents.expected @@ -8,7 +8,6 @@ | (?:[^%]\|^)?%\\((\\w*)\\)[a-z] | 0 | 10 | (?:[^%]\|^) | 3 | 9 | [^%]\|^ | | (?:[^%]\|^)?%\\((\\w*)\\)[a-z] | 14 | 19 | (\\w*) | 15 | 18 | \\w* | | (?P[\\w]+)\| | 0 | 15 | (?P[\\w]+) | 9 | 14 | [\\w]+ | -| (?m)^(?!$) | 0 | 4 | (?m) | 2 | 3 | m | | (?m)^(?!$) | 5 | 10 | (?!$) | 8 | 9 | $ | | (\\033\|~{) | 0 | 9 | (\\033\|~{) | 1 | 8 | \\033\|~{ | | \\[(?P[^[]*)\\]\\((?P[^)]*) | 2 | 16 | (?P[^[]*) | 10 | 15 | [^[]* | diff --git a/python/ql/test/library-tests/regex/Regex.expected b/python/ql/test/library-tests/regex/Regex.expected index b2ad03aa16a..e5e0ea1719e 100644 --- a/python/ql/test/library-tests/regex/Regex.expected +++ b/python/ql/test/library-tests/regex/Regex.expected @@ -77,11 +77,9 @@ | (?P[\\w]+)\| | sequence | 0 | 15 | | (?m)^(?!$) | $ | 8 | 9 | | (?m)^(?!$) | ^ | 4 | 5 | -| (?m)^(?!$) | char | 2 | 3 | +| (?m)^(?!$) | empty group | 0 | 4 | | (?m)^(?!$) | empty group | 5 | 10 | -| (?m)^(?!$) | non-empty group | 0 | 4 | | (?m)^(?!$) | sequence | 0 | 10 | -| (?m)^(?!$) | sequence | 2 | 3 | | (?m)^(?!$) | sequence | 8 | 9 | | (\\033\|~{) | char | 1 | 5 | | (\\033\|~{) | char | 6 | 7 | diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/DataflowQueryTest.ql b/python/ql/test/query-tests/Security/CWE-022-PathInjection/DataflowQueryTest.ql index c78e5a7c8c6..91ba1765724 100644 --- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/DataflowQueryTest.ql +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/DataflowQueryTest.ql @@ -1,3 +1,4 @@ import python import experimental.dataflow.TestUtil.DataflowQueryTest import semmle.python.security.dataflow.PathInjectionQuery +import FromLegacyConfiguration diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql index c69cc5c7578..ecb787218b1 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql @@ -1,3 +1,4 @@ import python import experimental.dataflow.TestUtil.DataflowQueryTest import semmle.python.security.dataflow.CommandInjectionQuery +import FromLegacyConfiguration diff --git a/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/DataflowQueryTest.ql b/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/DataflowQueryTest.ql index f9a934e1794..b00d364b853 100644 --- a/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/DataflowQueryTest.ql +++ b/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/DataflowQueryTest.ql @@ -1,3 +1,4 @@ import python import experimental.dataflow.TestUtil.DataflowQueryTest import semmle.python.security.dataflow.UnsafeShellCommandConstructionQuery +import FromLegacyConfiguration diff --git a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py index 15761274f1c..98682f04f3c 100644 --- a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py +++ b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py @@ -1,5 +1,5 @@ import json -from flask import Flask, request, make_response, escape +from flask import Flask, request, make_response, escape, jsonify app = Flask(__name__) @@ -26,3 +26,9 @@ def unsafe_json(): def safe_json(): data = json.loads(request.data) return make_response(json.dumps(data), 200, {'Content-Type': 'application/json'}) # OK, FP + + +@app.route("/jsonify") +def jsonify(): + data = request.data + return jsonify(data) # OK, FP diff --git a/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/BadTagFilter.expected b/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/BadTagFilter.expected index cc9da9cfdc8..407a5490e8c 100644 --- a/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/BadTagFilter.expected +++ b/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/BadTagFilter.expected @@ -1,6 +1,7 @@ | tst.py:4:20:4:43 | .*?<\\/script> | This regular expression does not match script end tags like . | | tst.py:5:20:5:43 | .*?<\\/script> | This regular expression does not match script end tags like . | | tst.py:9:20:9:30 |