From 91375d3a4901f5a7fdbcf57ebb159d383f9c6f46 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 27 Sep 2024 11:04:00 +0100 Subject: [PATCH 01/30] Update ExternalFlow.qll docs on `subtypes` column --- go/ql/lib/semmle/go/dataflow/ExternalFlow.qll | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll index d905201fd453..1dffde971510 100644 --- a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll @@ -25,8 +25,12 @@ * packages in the group `` according to the `packageGrouping` * predicate. * 2. The `type` column selects a type within that package. - * 3. The `subtypes` is a boolean that indicates whether to jump to an - * arbitrary subtype of that type. + * 3. The `subtypes` column is a boolean that controls what restrictions we + * place on the type `t` of the selector base when accessing a field or + * calling a method. When it is false, `t` must be the exact type specified + * by this row. When it is true, `t` may be a type which embeds the specified + * type, and for interface methods `t` may be a type which implements the + * interface. * 4. The `name` column optionally selects a specific named member of the type. * 5. The `signature` column is always empty. * 6. The `ext` column is always empty. From e46ec5a171a883ecfa4dbc47f3ea98579cd76f73 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 11 Nov 2024 23:41:11 +0000 Subject: [PATCH 02/30] Fix MaD inheritance --- go/ql/lib/semmle/go/dataflow/ExternalFlow.qll | 25 ++- .../go/dataflow/internal/FlowSummaryImpl.qll | 146 +++++++++++++++++- .../mad_IEmbedI1_subtypes_true.ext.yml | 4 +- .../mad_IEmbedI1_subtypes_true.ql | 6 +- .../mad_IEmbedI2_subtypes_true.ext.yml | 4 +- .../mad_IEmbedI2_subtypes_true.ql | 6 +- .../mad_SEmbedI1_subtypes_true.ext.yml | 6 +- .../mad_SEmbedI1_subtypes_true.ql | 6 +- .../mad_SEmbedI2_subtypes_true.ext.yml | 4 +- .../mad_SEmbedI2_subtypes_true.ql | 6 +- .../mad_SEmbedS1_subtypes_true.ext.yml | 6 +- .../mad_SEmbedS1_subtypes_true.ql | 6 +- .../mad_SEmbedS2_subtypes_true.ext.yml | 4 +- .../mad_SEmbedS2_subtypes_true.ql | 6 +- .../mad_SImplEmbedI1_subtypes_true.ext.yml | 6 +- .../mad_SImplEmbedI1_subtypes_true.ql | 6 +- .../mad_SImplEmbedI2_subtypes_true.ext.yml | 4 +- .../mad_SImplEmbedI2_subtypes_true.ql | 6 +- .../mad_SImplEmbedS1_subtypes_true.ext.yml | 6 +- .../mad_SImplEmbedS1_subtypes_true.ql | 6 +- .../mad_SImplEmbedS2_subtypes_true.ext.yml | 4 +- .../mad_SImplEmbedS2_subtypes_true.ql | 6 +- .../mad_i1_subtypes_false.ext.yml | 4 +- .../mad_i1_subtypes_false.ql | 6 +- .../mad_i1_subtypes_true.ext.yml | 4 +- .../mad_i1_subtypes_true.ql | 6 +- .../mad_i2_subtypes_false.ext.yml | 4 +- .../mad_i2_subtypes_false.ql | 6 +- .../mad_i2_subtypes_true.ext.yml | 4 +- .../mad_i2_subtypes_true.ql | 6 +- .../mad_s1_subtypes_false.ext.yml | 6 +- .../mad_s1_subtypes_false.ql | 6 +- .../mad_s1_subtypes_true.ext.yml | 6 +- .../mad_s1_subtypes_true.ql | 6 +- .../dataflow/ExternalFlowInheritance/ql_I1.ql | 36 ++--- .../dataflow/ExternalFlowInheritance/ql_S1.ql | 46 +++--- .../dataflow/ExternalFlowInheritance/test.go | 89 ----------- .../ExternalFlowInheritance/test_fields.go | 40 +++++ .../ExternalFlowInheritance/test_methods.go | 101 ++++++++++++ .../github.com/nonexistent/test/stub.go | 41 ++++- 40 files changed, 442 insertions(+), 254 deletions(-) delete mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test.go create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go diff --git a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll index 1dffde971510..68a876deaea6 100644 --- a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll @@ -474,17 +474,30 @@ SourceSinkInterpretationInput::SourceOrSinkElement interpretElement( elementSpec(pkg, type, subtypes, name, signature, ext) and // Go does not need to distinguish functions with signature signature = "" and - ( - exists(Field f | f.hasQualifiedName(interpretPackage(pkg), type, name) | result.asEntity() = f) + exists(string p | p = interpretPackage(pkg) | + exists(Field f | f.hasQualifiedName(p, type, name) | + result.asEntity() = f and + result.hasTypeInfo(p, type, subtypes) + ) or - exists(Method m | m.hasQualifiedName(interpretPackage(pkg), type, name) | - result.asEntity() = m + exists(Method m | m.hasQualifiedName(p, type, name) | + result.asEntity() = m and + result.hasTypeInfo(p, type, subtypes) or - subtypes = true and result.asEntity().(Method).implementsIncludingInterfaceMethods(m) + subtypes = true and + // p.type is an interface and we include types which implement it + exists(Method m2, string pkg2, string type2 | + m2.getReceiverType().implements(p, type) and + m2.getName() = name and + m2.getReceiverBaseType().hasQualifiedName(pkg2, type2) + | + result.asEntity() = m2 and + result.hasTypeInfo(pkg2, type2, subtypes) + ) ) or type = "" and - exists(Entity e | e.hasQualifiedName(interpretPackage(pkg), name) | result.asEntity() = e) + exists(Entity e | e.hasQualifiedName(p, name) | result.asEntity() = e) ) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 211974f75a56..14a92748d526 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -150,20 +150,50 @@ module SourceSinkInterpretationInput implements } private newtype TSourceOrSinkElement = - TEntityElement(Entity e) or + TMethodEntityElement(Method m, string pkg, string type, boolean subtypes) { + m.hasQualifiedName(pkg, type, _) and subtypes = [true, false] + } or + TFieldEntityElement(Field f, string pkg, string type, boolean subtypes) { + f.hasQualifiedName(pkg, type, _) and subtypes = [true, false] + } or + TOtherEntityElement(Entity e) { + not e instanceof Method and + not e instanceof Field + } or TAstElement(AstNode n) /** An element representable by CSV modeling. */ class SourceOrSinkElement extends TSourceOrSinkElement { /** Gets this source or sink element as an entity, if it is one. */ - Entity asEntity() { this = TEntityElement(result) } + Entity asEntity() { + this = TMethodEntityElement(result, _, _, _) or + this = TFieldEntityElement(result, _, _, _) or + this = TOtherEntityElement(result) + } /** Gets this source or sink element as an AST node, if it is one. */ AstNode asAstNode() { this = TAstElement(result) } + /** + * Holds if this source or sink element is a method that was specified + * with the given values for `pkg`, `type` and `subtypes`. + */ + predicate hasTypeInfo(string pkg, string type, boolean subtypes) { + this = TMethodEntityElement(_, pkg, type, subtypes) or + this = TFieldEntityElement(_, pkg, type, subtypes) + } + /** Gets a textual representation of this source or sink element. */ string toString() { + not this.hasTypeInfo(_, _, _) and result = "element representing " + [this.asEntity().toString(), this.asAstNode().toString()] + or + exists(string pkg, string name, boolean subtypes | + this.hasTypeInfo(pkg, name, subtypes) and + result = + "element representing " + this.asEntity().toString() + " with receiver type " + pkg + "." + + name + " and subtypes=" + subtypes + ) } /** Gets the location of this element. */ @@ -203,7 +233,17 @@ module SourceSinkInterpretationInput implements /** Gets the target of this call, if any. */ SourceOrSinkElement getCallTarget() { - result.asEntity() = this.asCall().getNode().(DataFlow::CallNode).getTarget() + exists(DataFlow::CallNode cn, Function callTarget | + cn = this.asCall().getNode() and + callTarget = cn.getTarget() + | + result.asEntity() = callTarget and + ( + not callTarget instanceof Method + or + ensureCorrectTypeInfo(result, cn.getReceiver()) + ) + ) } /** Gets a textual representation of this node. */ @@ -228,6 +268,90 @@ module SourceSinkInterpretationInput implements } } + private predicate ensureCorrectTypeInfo(SourceOrSinkElement sse, DataFlow::Node recv) { + ( + exists(DataFlow::CallNode cn | cn.getReceiver() = recv and cn.getTarget() = sse.asEntity()) + or + exists(DataFlow::FieldReadNode frn | frn.getBase() = recv and frn.getField() = sse.asEntity()) + or + exists(DataFlow::Write fw | fw.writesField(recv, sse.asEntity(), _)) + ) and + exists(string pkg, string typename, boolean subtypes, Type syntacticRecvBaseType | + sse.hasTypeInfo(pkg, typename, subtypes) and + syntacticRecvBaseType = lookThroughPointerType(getSyntacticRecv(recv).getType()) + | + subtypes = [true, false] and + syntacticRecvBaseType.hasQualifiedName(pkg, typename) + or + subtypes = true and + ( + // `syntacticRecvBaseType`'s underlying type might be an interface type and `sse` + // might be a method defined on an interface which is a subtype of it. + exists(Type t | + t = syntacticRecvBaseType.getUnderlyingType().(InterfaceType).getAnEmbeddedInterface() and + t.hasQualifiedName(pkg, typename) and + sse.asEntity().(Method).hasQualifiedName(pkg, typename, _) + ) + or + // `syntacticRecvBaseType`'s underlying type might be a struct type and `sse` + // might be a promoted method or field. + exists(StructType st, Field field1, Field field2, int depth1, int depth2, Type t1, Type t2 | + st = syntacticRecvBaseType.getUnderlyingType() and + field1 = st.getFieldAtDepth(_, depth1) and + field2 = st.getFieldAtDepth(_, depth2) and + t1 = lookThroughPointerType(field1.getType()) and + t2 = lookThroughPointerType(field2.getType()) and + ( + field1 = field2 + or + field2 = t1.getUnderlyingType().(StructType).getFieldAtDepth(_, depth2 - depth1 - 1) + ) and + matchTypeInfo(sse, t1) + | + sse.asEntity().(Method).getReceiverBaseType() = t2 + or + sse.asEntity().(Field).getDeclaringType() = t2.getUnderlyingType() + ) + ) + ) + } + + private DataFlow::Node getSyntacticRecv(DataFlow::Node n) { + exists(DataFlow::Node n2 | + // look through implicit dereference, if there is one + not exists(n.asInstruction().(IR::EvalImplicitDerefInstruction).getOperand()) and + n2 = n + or + n2.asExpr() = n.asInstruction().(IR::EvalImplicitDerefInstruction).getOperand() + | + result = skipImplicitFieldReads(n2) + ) + } + + private DataFlow::Node skipImplicitFieldReads(DataFlow::Node n) { + not exists(getImplicitFieldReadInstruction(n)) and result = n + or + result = skipImplicitFieldReads(getImplicitFieldReadInstruction(n)) + } + + pragma[inline] + private DataFlow::Node getImplicitFieldReadInstruction(DataFlow::Node n) { + result.asInstruction() = + n.(DataFlow::InstructionNode) + .asInstruction() + .(IR::ImplicitFieldReadInstruction) + .getBaseInstruction() + } + + bindingset[sse, t] + pragma[inline_late] + private predicate matchTypeInfo(SourceOrSinkElement sse, Type t) { + exists(string pkg, string typename | + sse.hasTypeInfo(pkg, typename, true) and + t.hasQualifiedName(pkg, typename) + ) + } + /** Provides additional sink specification logic. */ bindingset[c] predicate interpretOutput(string c, InterpretNode mid, InterpretNode node) { @@ -244,8 +368,11 @@ module SourceSinkInterpretationInput implements (c = "Parameter" or c = "") and node.asNode().asParameter() = e.asEntity() or - c = "" and - n.(DataFlow::FieldReadNode).getField() = e.asEntity() + exists(DataFlow::FieldReadNode frn | frn = n | + c = "" and + frn.getField() = e.asEntity() and + ensureCorrectTypeInfo(e, frn.getBase()) + ) ) } @@ -259,10 +386,13 @@ module SourceSinkInterpretationInput implements mid.asCallable() = getNodeEnclosingCallable(ret) ) or - exists(DataFlow::Write fw, Field f | + exists(SourceOrSinkElement e, DataFlow::Write fw, DataFlow::Node base, Field f | + e = mid.asElement() and + f = e.asEntity() + | c = "" and - f = mid.asElement().asEntity() and - fw.writesField(_, f, node.asNode()) + fw.writesField(base, f, node.asNode()) and + ensureCorrectTypeInfo(e, base) ) } } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI1_subtypes_true.ext.yml index 7d2e45d89f31..faf2e6ba6063 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI1_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI1_subtypes_true.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "IEmbedI1", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "IEmbedI1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "IEmbedI1", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "IEmbedI1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI1_subtypes_true.ql index 7af5b7795b9f..e4d35a2d1830 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI1_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI1_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI2_subtypes_true.ext.yml index b723867e3e79..066e1846fbf6 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI2_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI2_subtypes_true.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "IEmbedI2", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "IEmbedI2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "IEmbedI2", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "IEmbedI2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI2_subtypes_true.ql index 388370ba6b8c..18e461357890 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI2_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_IEmbedI2_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI1_subtypes_true.ext.yml index 93f8f74dfb5b..a210d4213261 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI1_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI1_subtypes_true.ext.yml @@ -3,7 +3,8 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "SEmbedI1", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "SEmbedI1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedI1", True, "SourceField", "", "", "", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +14,5 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "SEmbedI1", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "SEmbedI1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedI1", True, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI1_subtypes_true.ql index d56f8ae0f0f9..f401e958315d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI1_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI1_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI2_subtypes_true.ext.yml index ba94082e7e31..f1378ba6fa23 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI2_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI2_subtypes_true.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "SEmbedI2", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "SEmbedI2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "SEmbedI2", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "SEmbedI2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI2_subtypes_true.ql index dd46393546fc..0d7169c93cf7 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI2_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedI2_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS1_subtypes_true.ext.yml index 89218840c0bf..35baccbe09f6 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS1_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS1_subtypes_true.ext.yml @@ -3,7 +3,8 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "SEmbedS1", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "SEmbedS1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedS1", True, "SourceField", "", "", "", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +14,5 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "SEmbedS1", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "SEmbedS1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedS1", True, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS1_subtypes_true.ql index 0789ada5c51f..f58fd32770a9 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS1_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS1_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS2_subtypes_true.ext.yml index e773cf215b40..4772c9de698e 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS2_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS2_subtypes_true.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "SEmbedS2", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "SEmbedS2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "SEmbedS2", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "SEmbedS2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS2_subtypes_true.ql index 76d0b6fcd1a1..db9d98e06d28 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS2_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedS2_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI1_subtypes_true.ext.yml index 4b572ad124cc..f75fc2f7652f 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI1_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI1_subtypes_true.ext.yml @@ -3,7 +3,8 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "SImplEmbedI1", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedI1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedI1", True, "SourceField", "", "", "", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +14,5 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "SImplEmbedI1", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedI1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedI1", True, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI1_subtypes_true.ql index 4fb7909d7610..c4e8afd1fbf4 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI1_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI1_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI2_subtypes_true.ext.yml index 9d695502c29a..65cba7782506 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI2_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI2_subtypes_true.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "SImplEmbedI2", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedI2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "SImplEmbedI2", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedI2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI2_subtypes_true.ql index f5dba02a1528..b8ebb68ecdb8 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI2_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedI2_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS1_subtypes_true.ext.yml index 0936a7d253b2..30d240d4a2e4 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS1_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS1_subtypes_true.ext.yml @@ -3,7 +3,8 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "SImplEmbedS1", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedS1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedS1", True, "SourceField", "", "", "", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +14,5 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "SImplEmbedS1", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedS1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedS1", True, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS1_subtypes_true.ql index e08c787aa10a..10e9fb96d4c8 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS1_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS1_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS2_subtypes_true.ext.yml index 04bc012e7f41..6873efc4258a 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS2_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS2_subtypes_true.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "SImplEmbedS2", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedS2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "SImplEmbedS2", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "SImplEmbedS2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS2_subtypes_true.ql index 4c2d832620cb..403b6238b4f3 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS2_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SImplEmbedS2_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ext.yml index 11067b1760da..a50fb9449a35 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "I1", False, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "I1", False, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "I1", False, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "I1", False, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ql index 82d63025f226..3915c20b92bc 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ext.yml index 48c3a4daca8c..4b59e9a255f2 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "I1", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "I1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "I1", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "I1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ql index 85a18e65096e..2db01e3a76f5 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ext.yml index 8b01fd001766..660eb326eaaf 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "I2", False, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "I2", False, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "I2", False, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "I2", False, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ql index f8dafe8b4f71..9cff9e92009f 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ext.yml index d9fbc304b518..8d2c2ff522ff 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ext.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "I2", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "I2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +13,4 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "I2", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "I2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ql index 140591813924..79220e979c08 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ext.yml index b0322a6ecd30..804a920b3242 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ext.yml @@ -3,7 +3,8 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "S1", False, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "S1", False, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "S1", False, "SourceField", "", "", "", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +14,5 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "S1", False, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "S1", False, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "S1", False, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ql index 72cea1afe969..c5754d1ded77 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ext.yml index 3adf2d35ca48..14f2914b9421 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ext.yml @@ -3,7 +3,8 @@ extensions: pack: codeql/go-all extensible: sourceModel data: - - ["github.com/nonexistent/test", "S1", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - ["github.com/nonexistent/test", "S1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "S1", True, "SourceField", "", "", "", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel @@ -13,4 +14,5 @@ extensions: pack: codeql/go-all extensible: sinkModel data: - - ["github.com/nonexistent/test", "S1", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] + - ["github.com/nonexistent/test", "S1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "S1", True, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ql index 4afbff7ac9e1..92c895b61a33 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ql @@ -1,14 +1,12 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } } module Flow = TaintTracking::Global; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_I1.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_I1.ql index 9e563a5bb70e..f4beb7ea28df 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_I1.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_I1.ql @@ -1,14 +1,22 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "I1", "Source") and + source = m.getACall().getResult() + ) + } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "I1", "Sink") and + sink = m.getACall().getArgument(0) + ) + } } module Flow = TaintTracking::Global; @@ -27,15 +35,6 @@ module FlowTest implements TestSig { } } -class MySource extends RemoteFlowSource::Range instanceof DataFlow::Node { - MySource() { - exists(Method m | - m.hasQualifiedName("github.com/nonexistent/test", "I1", "Source") and - this = m.getACall().getResult() - ) - } -} - class MyStep extends DataFlow::FunctionModel, Method { MyStep() { this.hasQualifiedName("github.com/nonexistent/test", "I1", "Step") } @@ -43,14 +42,3 @@ class MyStep extends DataFlow::FunctionModel, Method { input.isParameter(0) and output.isResult() } } - -class MySink extends FileSystemAccess::Range, DataFlow::CallNode { - MySink() { - exists(Method m | - m.hasQualifiedName("github.com/nonexistent/test", "I1", "Sink") and - this = m.getACall() - ) - } - - override DataFlow::Node getAPathArgument() { result = this.getArgument(0) } -} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_S1.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_S1.ql index bf9f36358b9d..49113c53ed7a 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_S1.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_S1.ql @@ -1,14 +1,32 @@ import go -import semmle.go.dataflow.ExternalFlow import ModelValidation -import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import TestUtilities.InlineExpectationsTest import MakeTest module Config implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSource(DataFlow::Node source) { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "S1", "Source") and + source = m.getACall().getResult() + ) + or + exists(Field f | + f.hasQualifiedName("github.com/nonexistent/test", "S1", "SourceField") and + source = f.getARead() + ) + } - predicate isSink(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } + predicate isSink(DataFlow::Node sink) { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "S1", "Sink") and + sink = m.getACall().getArgument(0) + ) + or + exists(Field f | + f.hasQualifiedName("github.com/nonexistent/test", "S1", "SinkField") and + any(DataFlow::Write w).writesField(_, f, sink) + ) + } } module Flow = TaintTracking::Global; @@ -27,15 +45,6 @@ module FlowTest implements TestSig { } } -class MySource extends RemoteFlowSource::Range instanceof DataFlow::Node { - MySource() { - exists(Method m | - m.hasQualifiedName("github.com/nonexistent/test", "S1", "Source") and - this = m.getACall().getResult() - ) - } -} - class MyStep extends DataFlow::FunctionModel, Method { MyStep() { this.hasQualifiedName("github.com/nonexistent/test", "S1", "Step") } @@ -43,14 +52,3 @@ class MyStep extends DataFlow::FunctionModel, Method { input.isParameter(0) and output.isResult() } } - -class MySink extends FileSystemAccess::Range, DataFlow::CallNode { - MySink() { - exists(Method m | - m.hasQualifiedName("github.com/nonexistent/test", "S1", "Sink") and - this = m.getACall() - ) - } - - override DataFlow::Node getAPathArgument() { result = this.getArgument(0) } -} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test.go deleted file mode 100644 index faeba00e7024..000000000000 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test.go +++ /dev/null @@ -1,89 +0,0 @@ -package main - -import ( - "github.com/nonexistent/test" -) - -func TestI1(t test.I1) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[f] I1[t] ql_I1 SPURIOUS: IEmbedI1[t] SEmbedI1[t] ql_S1 -} - -func TestI2(t test.I2) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] I2[f] I2[t] SPURIOUS: IEmbedI1[t] IEmbedI2[t] SEmbedI1[t] SEmbedI2[t] -} - -func TestS1(t test.S1) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] S1[f] S1[t] ql_S1 SPURIOUS: IEmbedI1[t] SEmbedI1[t] SEmbedS1[t] -} - -func TestS2(t test.S2) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] I2[t] SPURIOUS: IEmbedI1[t] IEmbedI2[t] SEmbedI1[t] SEmbedI2[t] SEmbedS2[t] -} - -func TestSEmbedI1(t test.SEmbedI1) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] SEmbedI1[t] ql_I1 SPURIOUS: I1[f] IEmbedI1[t] ql_S1 -} - -func TestSEmbedI2(t test.SEmbedI2) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] I2[t] SEmbedI2[t] SPURIOUS: I2[f] IEmbedI1[t] IEmbedI2[t] SEmbedI1[t] -} - -func TestIEmbedI1(t test.IEmbedI1) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] IEmbedI1[t] ql_I1 SPURIOUS: I1[f] SEmbedI1[t] ql_S1 -} - -func TestIEmbedI2(t test.IEmbedI2) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] I2[t] IEmbedI2[t] SPURIOUS: I2[f] IEmbedI1[t] SEmbedI1[t] SEmbedI2[t] -} - -func TestSImplEmbedI1(t test.SImplEmbedI1) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] SImplEmbedI1[t] SPURIOUS: IEmbedI1[t] SEmbedI1[t] -} - -func TestSImplEmbedI2(t test.SImplEmbedI2) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] I2[t] SImplEmbedI2[t] SPURIOUS: IEmbedI1[t] IEmbedI2[t] SEmbedI1[t] SEmbedI2[t] -} - -func TestSEmbedS1(t test.SEmbedS1) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] S1[t] SEmbedS1[t] ql_S1 SPURIOUS: IEmbedI1[t] S1[f] SEmbedI1[t] -} - -func TestSEmbedS2(t test.SEmbedS2) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] I2[t] SEmbedS2[t] SPURIOUS: IEmbedI1[t] IEmbedI2[t] SEmbedI1[t] SEmbedI2[t] -} - -func TestSImplEmbedS1(t test.SImplEmbedS1) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] SImplEmbedS1[t] SPURIOUS: IEmbedI1[t] SEmbedI1[t] -} - -func TestSImplEmbedS2(t test.SImplEmbedS2) { - x := t.Source() - y := t.Step(x) - t.Sink(y) // $ I1[t] I2[t] SImplEmbedS2[t] SPURIOUS: IEmbedI1[t] IEmbedI2[t] SEmbedI1[t] SEmbedI2[t] -} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go new file mode 100644 index 000000000000..a207a7ab192e --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go @@ -0,0 +1,40 @@ +package main + +import ( + "github.com/nonexistent/test" +) + +func TestFieldsS1(t test.S1) { + a := t.SourceField + t.SinkField = a // $ S1[f] S1[t] ql_S1 +} + +func TestFieldsSEmbedI1(t test.SEmbedI1) { + a := t.SourceField + t.SinkField = a // $ SEmbedI1[t] +} + +func TestFieldsSImplEmbedI1(t test.SImplEmbedI1) { + a := t.SourceField + t.SinkField = a // $ SImplEmbedI1[t] +} + +func TestFieldsSEmbedS1(t test.SEmbedS1) { + a := t.SourceField + t.SinkField = a // $ S1[t] SEmbedS1[t] ql_S1 +} + +func TestFieldsSImplEmbedS1(t test.SImplEmbedS1) { + a := t.SourceField + t.SinkField = a // $ SImplEmbedS1[t] +} + +func TestFieldsSEmbedSEmbedI1(t test.SEmbedSEmbedI1) { + a := t.SourceField + t.SinkField = a +} + +func TestFieldsSEmbedSEmbedS1(t test.SEmbedSEmbedS1) { + a := t.SourceField + t.SinkField = a // $ S1[t] ql_S1 SEmbedS1[t] +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go new file mode 100644 index 000000000000..ae915c78b1fb --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go @@ -0,0 +1,101 @@ +package main + +import ( + "github.com/nonexistent/test" +) + +func TestMethodsI1(t test.I1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[f] I1[t] ql_I1 SPURIOUS: ql_S1 +} + +func TestMethodsI2(t test.I2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[f] I2[t] +} + +func TestMethodsS1(t test.S1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] S1[f] S1[t] ql_S1 +} + +func TestMethodsS2(t test.S2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] +} + +func TestMethodsSEmbedI1(t test.SEmbedI1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] SEmbedI1[t] ql_I1 SPURIOUS: ql_S1 +} + +func TestMethodsSEmbedI2(t test.SEmbedI2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] SEmbedI2[t] +} + +func TestMethodsIEmbedI1(t test.IEmbedI1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] IEmbedI1[t] ql_I1 SPURIOUS: ql_S1 +} + +func TestMethodsIEmbedI2(t test.IEmbedI2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] IEmbedI2[t] +} + +func TestMethodsSImplEmbedI1(t test.SImplEmbedI1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] SImplEmbedI1[t] +} + +func TestMethodsSImplEmbedI2(t test.SImplEmbedI2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] SImplEmbedI2[t] +} + +func TestMethodsSEmbedS1(t test.SEmbedS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] S1[t] SEmbedS1[t] ql_S1 +} + +func TestMethodsSEmbedS2(t test.SEmbedS2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] SEmbedS2[t] +} + +func TestMethodsSImplEmbedS1(t test.SImplEmbedS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] SImplEmbedS1[t] +} + +func TestMethodsSImplEmbedS2(t test.SImplEmbedS2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] SImplEmbedS2[t] +} + +func TestMethodsSEmbedSEmbedI1(t test.SEmbedSEmbedI1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] SEmbedI1[t] ql_I1 SPURIOUS: ql_S1 +} + +func TestMethodsSEmbedSEmbedS1(t test.SEmbedSEmbedS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] S1[t] SEmbedS1[t] ql_S1 +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go index 206e1d99e383..524af77de480 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go @@ -16,7 +16,10 @@ type I2 interface { } // A struct type implementing I1 -type S1 struct{} +type S1 struct { + SourceField string + SinkField string +} func (t *S1) Source() interface{} { return nil @@ -44,7 +47,11 @@ func (t *S2) Step(val interface{}) interface{} { func (t *S2) ExtraMethodI2() {} // A struct type embedding I1 -type SEmbedI1 struct{ I1 } +type SEmbedI1 struct { + I1 + SourceField string + SinkField string +} // A struct type embedding I2 type SEmbedI2 struct{ I2 } @@ -63,7 +70,11 @@ type IEmbedI2 interface { // A struct type embedding I1 and separately implementing its methods, so the // methods of the embedded field are not promoted. -type SImplEmbedI1 struct{ I1 } +type SImplEmbedI1 struct { + I1 + SourceField string + SinkField string +} func (t *SImplEmbedI1) Source() interface{} { return nil @@ -92,14 +103,20 @@ func (t *SImplEmbedI2) Step(val interface{}) interface{} { func (t *SImplEmbedI2) ExtraMethodI2() {} // A struct type embedding S1 -type SEmbedS1 struct{ S1 } +type SEmbedS1 struct { + S1 +} // A struct type embedding S2 type SEmbedS2 struct{ S2 } -// A struct type embedding S1 and separately implementing I1's methods, so the -// methods of the embedded field are not promoted. -type SImplEmbedS1 struct{ S1 } +// A struct type embedding S1 and separately implementing I1's methods and +// fields, so the methods and fields of the embedded field are not promoted. +type SImplEmbedS1 struct { + S1 + SourceField string + SinkField string +} func (t *SImplEmbedS1) Source() interface{} { return nil @@ -126,3 +143,13 @@ func (t *SImplEmbedS2) Step(val interface{}) interface{} { } func (t *SImplEmbedS2) ExtraMethodI2() {} + +// A struct type embedding SEmbedI1 +type SEmbedSEmbedI1 struct { + SEmbedI1 + SourceField string + SinkField string +} + +// A struct type embedding SEmbedS1 +type SEmbedSEmbedS1 struct{ SEmbedS1 } From e90e31329500161566dd5e78191a5d9bb4a6a460 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 21:58:52 +0100 Subject: [PATCH 03/30] Simplify ensureCorrectTypeInfo --- .../go/dataflow/internal/FlowSummaryImpl.qll | 38 +++---------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 14a92748d526..a114a2447229 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -276,42 +276,23 @@ module SourceSinkInterpretationInput implements or exists(DataFlow::Write fw | fw.writesField(recv, sse.asEntity(), _)) ) and - exists(string pkg, string typename, boolean subtypes, Type syntacticRecvBaseType | + exists(string pkg, string typename, boolean subtypes, Type syntacticRecvBaseType, Type targetType | sse.hasTypeInfo(pkg, typename, subtypes) and + targetType.hasQualifiedName(pkg, typename) and syntacticRecvBaseType = lookThroughPointerType(getSyntacticRecv(recv).getType()) | subtypes = [true, false] and - syntacticRecvBaseType.hasQualifiedName(pkg, typename) + syntacticRecvBaseType = targetType or subtypes = true and ( // `syntacticRecvBaseType`'s underlying type might be an interface type and `sse` // might be a method defined on an interface which is a subtype of it. - exists(Type t | - t = syntacticRecvBaseType.getUnderlyingType().(InterfaceType).getAnEmbeddedInterface() and - t.hasQualifiedName(pkg, typename) and - sse.asEntity().(Method).hasQualifiedName(pkg, typename, _) - ) + targetType = syntacticRecvBaseType.getUnderlyingType().(InterfaceType).getAnEmbeddedInterface() or // `syntacticRecvBaseType`'s underlying type might be a struct type and `sse` // might be a promoted method or field. - exists(StructType st, Field field1, Field field2, int depth1, int depth2, Type t1, Type t2 | - st = syntacticRecvBaseType.getUnderlyingType() and - field1 = st.getFieldAtDepth(_, depth1) and - field2 = st.getFieldAtDepth(_, depth2) and - t1 = lookThroughPointerType(field1.getType()) and - t2 = lookThroughPointerType(field2.getType()) and - ( - field1 = field2 - or - field2 = t1.getUnderlyingType().(StructType).getFieldAtDepth(_, depth2 - depth1 - 1) - ) and - matchTypeInfo(sse, t1) - | - sse.asEntity().(Method).getReceiverBaseType() = t2 - or - sse.asEntity().(Field).getDeclaringType() = t2.getUnderlyingType() - ) + syntacticRecvBaseType.getUnderlyingType().(StructType).hasEmbeddedField(targetType, _) ) ) } @@ -343,15 +324,6 @@ module SourceSinkInterpretationInput implements .getBaseInstruction() } - bindingset[sse, t] - pragma[inline_late] - private predicate matchTypeInfo(SourceOrSinkElement sse, Type t) { - exists(string pkg, string typename | - sse.hasTypeInfo(pkg, typename, true) and - t.hasQualifiedName(pkg, typename) - ) - } - /** Provides additional sink specification logic. */ bindingset[c] predicate interpretOutput(string c, InterpretNode mid, InterpretNode node) { From d9126d384f6d6278832dc438f4367592b9800c05 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:04:32 +0100 Subject: [PATCH 04/30] Simplify interpretElement --- go/ql/lib/semmle/go/dataflow/ExternalFlow.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll index 68a876deaea6..1a59b272fb81 100644 --- a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll @@ -475,10 +475,8 @@ SourceSinkInterpretationInput::SourceOrSinkElement interpretElement( // Go does not need to distinguish functions with signature signature = "" and exists(string p | p = interpretPackage(pkg) | - exists(Field f | f.hasQualifiedName(p, type, name) | - result.asEntity() = f and - result.hasTypeInfo(p, type, subtypes) - ) + result.asEntity().(Field).hasQualifiedName(p, type, name) and + result.hasTypeInfo(p, type, subtypes) or exists(Method m | m.hasQualifiedName(p, type, name) | result.asEntity() = m and From 520acc4b1c706691751abdd3499c06530d164d49 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:08:26 +0100 Subject: [PATCH 05/30] Further simplify interpretElement to avoid 'm' only being used on one side of a disjunction --- go/ql/lib/semmle/go/dataflow/ExternalFlow.qll | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll index 1a59b272fb81..c557b5af7de3 100644 --- a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll @@ -475,23 +475,21 @@ SourceSinkInterpretationInput::SourceOrSinkElement interpretElement( // Go does not need to distinguish functions with signature signature = "" and exists(string p | p = interpretPackage(pkg) | - result.asEntity().(Field).hasQualifiedName(p, type, name) and - result.hasTypeInfo(p, type, subtypes) + result.hasTypeInfo(p, type, subtypes) and + ( + result.asEntity().(Field).hasQualifiedName(p, type, name) or + result.asEntity().(Method).hasQualifiedName(p, type, name) + ) or - exists(Method m | m.hasQualifiedName(p, type, name) | - result.asEntity() = m and - result.hasTypeInfo(p, type, subtypes) - or - subtypes = true and - // p.type is an interface and we include types which implement it - exists(Method m2, string pkg2, string type2 | - m2.getReceiverType().implements(p, type) and - m2.getName() = name and - m2.getReceiverBaseType().hasQualifiedName(pkg2, type2) - | - result.asEntity() = m2 and - result.hasTypeInfo(pkg2, type2, subtypes) - ) + subtypes = true and + // p.type is an interface and we include types which implement it + exists(Method m2, string pkg2, string type2 | + m2.getReceiverType().implements(p, type) and + m2.getName() = name and + m2.getReceiverBaseType().hasQualifiedName(pkg2, type2) + | + result.asEntity() = m2 and + result.hasTypeInfo(pkg2, type2, subtypes) ) or type = "" and From 20e8d48869745906d90de106ab09946c302f135f Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:13:14 +0100 Subject: [PATCH 06/30] Add comment noting that a Method or Field might have multiple SourceOrSinkElements --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index a114a2447229..5caa2570394b 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -149,6 +149,9 @@ module SourceSinkInterpretationInput implements ) } + // Note that due to embedding, which is currently implemented via some Methods + // or Fields having multiple qualified names, a given Method or Field is liable + // to have more than one SourceOrSinkElement, one for each of the names it claims. private newtype TSourceOrSinkElement = TMethodEntityElement(Method m, string pkg, string type, boolean subtypes) { m.hasQualifiedName(pkg, type, _) and subtypes = [true, false] From 17a3429f1e0e018fc621d20552fe24b607207fc0 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:13:58 +0100 Subject: [PATCH 07/30] Correct hasTypeInfo doc comment --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 5caa2570394b..90b2771b2060 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -178,7 +178,7 @@ module SourceSinkInterpretationInput implements AstNode asAstNode() { this = TAstElement(result) } /** - * Holds if this source or sink element is a method that was specified + * Holds if this source or sink element is a method or field that was specified * with the given values for `pkg`, `type` and `subtypes`. */ predicate hasTypeInfo(string pkg, string type, boolean subtypes) { From e290cecabd63ff16764cd039a6187e890eea8a5f Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:19:18 +0100 Subject: [PATCH 08/30] Rename ensureCorrectTypeInfo and getSyntacticRecv --- .../go/dataflow/internal/FlowSummaryImpl.qll | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 90b2771b2060..18e7c3613b56 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -244,7 +244,7 @@ module SourceSinkInterpretationInput implements ( not callTarget instanceof Method or - ensureCorrectTypeInfo(result, cn.getReceiver()) + elementAppliesToQualifier(result, cn.getReceiver()) ) ) } @@ -271,36 +271,39 @@ module SourceSinkInterpretationInput implements } } - private predicate ensureCorrectTypeInfo(SourceOrSinkElement sse, DataFlow::Node recv) { + private predicate elementAppliesToQualifier(SourceOrSinkElement sse, DataFlow::Node qual) { ( - exists(DataFlow::CallNode cn | cn.getReceiver() = recv and cn.getTarget() = sse.asEntity()) + exists(DataFlow::CallNode cn | cn.getReceiver() = qual and cn.getTarget() = sse.asEntity()) or - exists(DataFlow::FieldReadNode frn | frn.getBase() = recv and frn.getField() = sse.asEntity()) + exists(DataFlow::FieldReadNode frn | frn.getBase() = qual and frn.getField() = sse.asEntity()) or - exists(DataFlow::Write fw | fw.writesField(recv, sse.asEntity(), _)) + exists(DataFlow::Write fw | fw.writesField(qual, sse.asEntity(), _)) ) and - exists(string pkg, string typename, boolean subtypes, Type syntacticRecvBaseType, Type targetType | + exists( + string pkg, string typename, boolean subtypes, Type syntacticQualBaseType, Type targetType + | sse.hasTypeInfo(pkg, typename, subtypes) and targetType.hasQualifiedName(pkg, typename) and - syntacticRecvBaseType = lookThroughPointerType(getSyntacticRecv(recv).getType()) + syntacticQualBaseType = lookThroughPointerType(getSyntacticQualifier(qual).getType()) | subtypes = [true, false] and - syntacticRecvBaseType = targetType + syntacticQualBaseType = targetType or subtypes = true and ( - // `syntacticRecvBaseType`'s underlying type might be an interface type and `sse` + // `syntacticQualBaseType`'s underlying type might be an interface type and `sse` // might be a method defined on an interface which is a subtype of it. - targetType = syntacticRecvBaseType.getUnderlyingType().(InterfaceType).getAnEmbeddedInterface() + targetType = + syntacticQualBaseType.getUnderlyingType().(InterfaceType).getAnEmbeddedInterface() or - // `syntacticRecvBaseType`'s underlying type might be a struct type and `sse` + // `syntacticQualBaseType`'s underlying type might be a struct type and `sse` // might be a promoted method or field. - syntacticRecvBaseType.getUnderlyingType().(StructType).hasEmbeddedField(targetType, _) + syntacticQualBaseType.getUnderlyingType().(StructType).hasEmbeddedField(targetType, _) ) ) } - private DataFlow::Node getSyntacticRecv(DataFlow::Node n) { + private DataFlow::Node getSyntacticQualifier(DataFlow::Node n) { exists(DataFlow::Node n2 | // look through implicit dereference, if there is one not exists(n.asInstruction().(IR::EvalImplicitDerefInstruction).getOperand()) and @@ -346,7 +349,7 @@ module SourceSinkInterpretationInput implements exists(DataFlow::FieldReadNode frn | frn = n | c = "" and frn.getField() = e.asEntity() and - ensureCorrectTypeInfo(e, frn.getBase()) + elementAppliesToQualifier(e, frn.getBase()) ) ) } @@ -367,7 +370,7 @@ module SourceSinkInterpretationInput implements | c = "" and fw.writesField(base, f, node.asNode()) and - ensureCorrectTypeInfo(e, base) + elementAppliesToQualifier(e, base) ) } } From fd40662ad87a1cdb9f2fb075af2252bfc071e2c6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:21:39 +0100 Subject: [PATCH 09/30] Rename getImplicitFieldReadInstruction --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 18e7c3613b56..ca16d9abd01c 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -316,13 +316,13 @@ module SourceSinkInterpretationInput implements } private DataFlow::Node skipImplicitFieldReads(DataFlow::Node n) { - not exists(getImplicitFieldReadInstruction(n)) and result = n + not exists(lookThroughImplicitFieldRead(n)) and result = n or - result = skipImplicitFieldReads(getImplicitFieldReadInstruction(n)) + result = skipImplicitFieldReads(lookThroughImplicitFieldRead(n)) } pragma[inline] - private DataFlow::Node getImplicitFieldReadInstruction(DataFlow::Node n) { + private DataFlow::Node lookThroughImplicitFieldRead(DataFlow::Node n) { result.asInstruction() = n.(DataFlow::InstructionNode) .asInstruction() From ccc525abd3c8fc3598496b4e2ae2b75ba7593ad9 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:22:29 +0100 Subject: [PATCH 10/30] Remove probably-unnecessary pragma --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index ca16d9abd01c..4c9680ef3507 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -321,7 +321,6 @@ module SourceSinkInterpretationInput implements result = skipImplicitFieldReads(lookThroughImplicitFieldRead(n)) } - pragma[inline] private DataFlow::Node lookThroughImplicitFieldRead(DataFlow::Node n) { result.asInstruction() = n.(DataFlow::InstructionNode) From cd99bea9c10b55513329712bd9ff48d8881ff79f Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:30:05 +0100 Subject: [PATCH 11/30] Explain getSyntacticQual --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 4c9680ef3507..77d7fdc10dc0 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -303,6 +303,13 @@ module SourceSinkInterpretationInput implements ) } + /** + * Gets `underlying`, where `n` if of the form `implicitDeref?(underlying.implicitFieldRead1.implicitFieldRead2...)` + * + * For Go syntax like `qualifier.method()` or `qualifier.field`, this is the type of `qualifier`, before any + * implicit dereference is interposed because `qualifier` is of pointer type, or implicit field accesses + * navigate to any embedded struct types that truly host `field`. + */ private DataFlow::Node getSyntacticQualifier(DataFlow::Node n) { exists(DataFlow::Node n2 | // look through implicit dereference, if there is one From 7ffff434245d4a41a6adbf42f0483596ce27b0cd Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:34:41 +0100 Subject: [PATCH 12/30] Improve comments --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 77d7fdc10dc0..35ffeb26bed0 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -292,12 +292,12 @@ module SourceSinkInterpretationInput implements subtypes = true and ( // `syntacticQualBaseType`'s underlying type might be an interface type and `sse` - // might be a method defined on an interface which is a subtype of it. + // might refer to a method defined on an interface embedded within it. targetType = syntacticQualBaseType.getUnderlyingType().(InterfaceType).getAnEmbeddedInterface() or // `syntacticQualBaseType`'s underlying type might be a struct type and `sse` - // might be a promoted method or field. + // might refer to an embedded method or field. syntacticQualBaseType.getUnderlyingType().(StructType).hasEmbeddedField(targetType, _) ) ) From f61251cc24974fa5414b8b91148bdb2187b238cc Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 23 Oct 2024 22:53:02 +0100 Subject: [PATCH 13/30] Document elementAppliesToQualifier --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 35ffeb26bed0..e54fb5665042 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -271,6 +271,14 @@ module SourceSinkInterpretationInput implements } } + /** + * Holds if method or field spec `sse` applies in the context of qualifier `qual`. + * + * Note that naively checking `sse.asEntity()`'s qualified name is not correct, because + * `Method`s and `Field`s may have multiple qualified names due to embedding. We must instead + * check that the specific name given be `sse.hasTypeInfo` refers to either `qual`'s type + * or to a type it embeds. + */ private predicate elementAppliesToQualifier(SourceOrSinkElement sse, DataFlow::Node qual) { ( exists(DataFlow::CallNode cn | cn.getReceiver() = qual and cn.getTarget() = sse.asEntity()) From 4a1fce9168604225377e6269dbfc16c59bb73f18 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 11 Nov 2024 23:46:10 +0000 Subject: [PATCH 14/30] Test non-promoted fields and methods --- .../go/dataflow/ExternalFlowInheritance/test_fields.go | 5 +++++ .../go/dataflow/ExternalFlowInheritance/test_methods.go | 6 ++++++ .../vendor/github.com/nonexistent/test/stub.go | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go index a207a7ab192e..4b6972d67917 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go @@ -38,3 +38,8 @@ func TestFieldsSEmbedSEmbedS1(t test.SEmbedSEmbedS1) { a := t.SourceField t.SinkField = a // $ S1[t] ql_S1 SEmbedS1[t] } + +func TestFieldsSEmbedS1AndSEmbedS1(t test.SEmbedS1AndSEmbedS1) { + a := t.SourceField + t.SinkField = a // $ S1[t] ql_S1 +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go index ae915c78b1fb..a106e4ee9d69 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go @@ -99,3 +99,9 @@ func TestMethodsSEmbedSEmbedS1(t test.SEmbedSEmbedS1) { y := t.Step(x) t.Sink(y) // $ I1[t] S1[t] SEmbedS1[t] ql_S1 } + +func TestMethodsSEmbedS1AndSEmbedS1(t test.SEmbedS1AndSEmbedS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] S1[t] ql_S1 +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go index 524af77de480..f2ee55d438ea 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go @@ -153,3 +153,9 @@ type SEmbedSEmbedI1 struct { // A struct type embedding SEmbedS1 type SEmbedSEmbedS1 struct{ SEmbedS1 } + +// A struct type embedding S1 and SEmbedS1 +type SEmbedS1AndSEmbedS1 struct { + S1 + SEmbedS1 +} From adc946ec2b3a15c0a28bf29d31aa378935b5a5a8 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 24 Oct 2024 13:41:57 +0100 Subject: [PATCH 15/30] Revert simplification to make tests pass --- .../go/dataflow/internal/FlowSummaryImpl.qll | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index e54fb5665042..8bcf48b9fb58 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -306,7 +306,23 @@ module SourceSinkInterpretationInput implements or // `syntacticQualBaseType`'s underlying type might be a struct type and `sse` // might refer to an embedded method or field. - syntacticQualBaseType.getUnderlyingType().(StructType).hasEmbeddedField(targetType, _) + exists(StructType st, Field field1, Field field2, int depth1, int depth2, Type t2 | + st = syntacticQualBaseType.getUnderlyingType() and + field1 = st.getFieldAtDepth(_, depth1) and + field2 = st.getFieldAtDepth(_, depth2) and + targetType = lookThroughPointerType(field1.getType()) and + t2 = lookThroughPointerType(field2.getType()) and + ( + field1 = field2 + or + field2 = + targetType.getUnderlyingType().(StructType).getFieldAtDepth(_, depth2 - depth1 - 1) + ) + | + sse.asEntity().(Method).getReceiverBaseType() = t2 + or + sse.asEntity().(Field).getDeclaringType() = t2.getUnderlyingType() + ) ) ) } From e335737f387960b33d1de7fab74cd8316aa2782e Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 24 Oct 2024 13:52:33 +0100 Subject: [PATCH 16/30] Minor fixes to docs --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 8bcf48b9fb58..026838cda03d 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -276,7 +276,7 @@ module SourceSinkInterpretationInput implements * * Note that naively checking `sse.asEntity()`'s qualified name is not correct, because * `Method`s and `Field`s may have multiple qualified names due to embedding. We must instead - * check that the specific name given be `sse.hasTypeInfo` refers to either `qual`'s type + * check that the specific name given by `sse.hasTypeInfo` refers to either `qual`'s type * or to a type it embeds. */ private predicate elementAppliesToQualifier(SourceOrSinkElement sse, DataFlow::Node qual) { @@ -305,7 +305,7 @@ module SourceSinkInterpretationInput implements syntacticQualBaseType.getUnderlyingType().(InterfaceType).getAnEmbeddedInterface() or // `syntacticQualBaseType`'s underlying type might be a struct type and `sse` - // might refer to an embedded method or field. + // might be a promoted method or field in it. exists(StructType st, Field field1, Field field2, int depth1, int depth2, Type t2 | st = syntacticQualBaseType.getUnderlyingType() and field1 = st.getFieldAtDepth(_, depth1) and From ede3b9f03333031f0727f9d94bc2fa8427b50e08 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 25 Oct 2024 01:08:48 +0100 Subject: [PATCH 17/30] Improve join order by making a separate predicate --- .../go/dataflow/internal/FlowSummaryImpl.qll | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 026838cda03d..5d70cc682d51 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -306,27 +306,35 @@ module SourceSinkInterpretationInput implements or // `syntacticQualBaseType`'s underlying type might be a struct type and `sse` // might be a promoted method or field in it. - exists(StructType st, Field field1, Field field2, int depth1, int depth2, Type t2 | - st = syntacticQualBaseType.getUnderlyingType() and - field1 = st.getFieldAtDepth(_, depth1) and - field2 = st.getFieldAtDepth(_, depth2) and - targetType = lookThroughPointerType(field1.getType()) and - t2 = lookThroughPointerType(field2.getType()) and - ( - field1 = field2 - or - field2 = - targetType.getUnderlyingType().(StructType).getFieldAtDepth(_, depth2 - depth1 - 1) - ) - | - sse.asEntity().(Method).getReceiverBaseType() = t2 - or - sse.asEntity().(Field).getDeclaringType() = t2.getUnderlyingType() - ) + targetType = + getIntermediateEmbeddedType(sse.asEntity(), syntacticQualBaseType.getUnderlyingType()) ) ) } + /** + * Gets the type of an embedded field of `st` which is on the path to `e`, + * which is a promoted method or field of `st`, or its base type if it's a + * pointer type. + */ + private Type getIntermediateEmbeddedType(Entity e, StructType st) { + exists(Field field1, Field field2, int depth1, int depth2, Type t2 | + field1 = st.getFieldAtDepth(_, depth1) and + field2 = st.getFieldAtDepth(_, depth2) and + result = lookThroughPointerType(field1.getType()) and + t2 = lookThroughPointerType(field2.getType()) and + ( + field1 = field2 + or + field2 = result.getUnderlyingType().(StructType).getFieldAtDepth(_, depth2 - depth1 - 1) + ) + | + e.(Method).getReceiverBaseType() = t2 + or + e.(Field).getDeclaringType() = t2.getUnderlyingType() + ) + } + /** * Gets `underlying`, where `n` if of the form `implicitDeref?(underlying.implicitFieldRead1.implicitFieldRead2...)` * From c2aee37210467172fcb59cf759c78851654f3335 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 25 Oct 2024 10:01:53 +0100 Subject: [PATCH 18/30] `getSyntacticQualifier` -> `getSyntacticQualifierBaseType` This improves performance. --- .../lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 5d70cc682d51..cebe7c712276 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -292,7 +292,7 @@ module SourceSinkInterpretationInput implements | sse.hasTypeInfo(pkg, typename, subtypes) and targetType.hasQualifiedName(pkg, typename) and - syntacticQualBaseType = lookThroughPointerType(getSyntacticQualifier(qual).getType()) + syntacticQualBaseType = getSyntacticQualifierBaseType(qual) | subtypes = [true, false] and syntacticQualBaseType = targetType @@ -336,13 +336,14 @@ module SourceSinkInterpretationInput implements } /** - * Gets `underlying`, where `n` if of the form `implicitDeref?(underlying.implicitFieldRead1.implicitFieldRead2...)` + * Gets the base type of `underlying`, where `n` is of the form + * `implicitDeref?(underlying.implicitFieldRead1.implicitFieldRead2...)` * * For Go syntax like `qualifier.method()` or `qualifier.field`, this is the type of `qualifier`, before any * implicit dereference is interposed because `qualifier` is of pointer type, or implicit field accesses * navigate to any embedded struct types that truly host `field`. */ - private DataFlow::Node getSyntacticQualifier(DataFlow::Node n) { + private Type getSyntacticQualifierBaseType(DataFlow::Node n) { exists(DataFlow::Node n2 | // look through implicit dereference, if there is one not exists(n.asInstruction().(IR::EvalImplicitDerefInstruction).getOperand()) and @@ -350,7 +351,7 @@ module SourceSinkInterpretationInput implements or n2.asExpr() = n.asInstruction().(IR::EvalImplicitDerefInstruction).getOperand() | - result = skipImplicitFieldReads(n2) + result = lookThroughPointerType(skipImplicitFieldReads(n2).getType()) ) } From 80e8015e67a6552cd6a9acefa42647891c8ee0e0 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 25 Oct 2024 12:32:39 +0100 Subject: [PATCH 19/30] Inline late and remove manual magic --- .../lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index cebe7c712276..44cc37e2e82a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -279,14 +279,9 @@ module SourceSinkInterpretationInput implements * check that the specific name given by `sse.hasTypeInfo` refers to either `qual`'s type * or to a type it embeds. */ + bindingset[sse, qual] + pragma[inline_late] private predicate elementAppliesToQualifier(SourceOrSinkElement sse, DataFlow::Node qual) { - ( - exists(DataFlow::CallNode cn | cn.getReceiver() = qual and cn.getTarget() = sse.asEntity()) - or - exists(DataFlow::FieldReadNode frn | frn.getBase() = qual and frn.getField() = sse.asEntity()) - or - exists(DataFlow::Write fw | fw.writesField(qual, sse.asEntity(), _)) - ) and exists( string pkg, string typename, boolean subtypes, Type syntacticQualBaseType, Type targetType | From 39afb18ee4b553b0d7f57f311b309deae6fc94de Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 25 Oct 2024 13:12:28 +0100 Subject: [PATCH 20/30] Fix bad join order --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 44cc37e2e82a..66f39af78514 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -378,12 +378,12 @@ module SourceSinkInterpretationInput implements e = mid.asElement() | (c = "Parameter" or c = "") and - node.asNode().asParameter() = e.asEntity() + n.asParameter() = pragma[only_bind_into](e).asEntity() or exists(DataFlow::FieldReadNode frn | frn = n | c = "" and - frn.getField() = e.asEntity() and - elementAppliesToQualifier(e, frn.getBase()) + frn.getField() = pragma[only_bind_into](e).asEntity() and + elementAppliesToQualifier(pragma[only_bind_into](e), frn.getBase()) ) ) } @@ -404,7 +404,7 @@ module SourceSinkInterpretationInput implements | c = "" and fw.writesField(base, f, node.asNode()) and - elementAppliesToQualifier(e, base) + elementAppliesToQualifier(pragma[only_bind_into](e), base) ) } } From b2c2a94866bb8f2abd57b2d87a24410f990d129d Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 25 Oct 2024 14:35:22 +0100 Subject: [PATCH 21/30] Accept review comment - doc clarification --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 66f39af78514..a5dd5922470a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -149,9 +149,9 @@ module SourceSinkInterpretationInput implements ) } - // Note that due to embedding, which is currently implemented via some Methods - // or Fields having multiple qualified names, a given Method or Field is liable - // to have more than one SourceOrSinkElement, one for each of the names it claims. + // Note that due to embedding, which is currently implemented via some + // Methods having multiple qualified names, a given Method is liable to have + // more than one SourceOrSinkElement, one for each of the names it claims. private newtype TSourceOrSinkElement = TMethodEntityElement(Method m, string pkg, string type, boolean subtypes) { m.hasQualifiedName(pkg, type, _) and subtypes = [true, false] From 8abb0594c35eaa7e91389cb658eb1c4a998c492d Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 25 Oct 2024 14:37:38 +0100 Subject: [PATCH 22/30] Combine two arms of newtype `TSourceOrSinkElement` --- .../go/dataflow/internal/FlowSummaryImpl.qll | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index a5dd5922470a..4e2d1552dab9 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -153,11 +153,12 @@ module SourceSinkInterpretationInput implements // Methods having multiple qualified names, a given Method is liable to have // more than one SourceOrSinkElement, one for each of the names it claims. private newtype TSourceOrSinkElement = - TMethodEntityElement(Method m, string pkg, string type, boolean subtypes) { - m.hasQualifiedName(pkg, type, _) and subtypes = [true, false] - } or - TFieldEntityElement(Field f, string pkg, string type, boolean subtypes) { - f.hasQualifiedName(pkg, type, _) and subtypes = [true, false] + TMethodOrFieldEntityElement(Entity e, string pkg, string type, boolean subtypes) { + ( + e.(Method).hasQualifiedName(pkg, type, _) or + e.(Field).hasQualifiedName(pkg, type, _) + ) and + subtypes = [true, false] } or TOtherEntityElement(Entity e) { not e instanceof Method and @@ -169,8 +170,7 @@ module SourceSinkInterpretationInput implements class SourceOrSinkElement extends TSourceOrSinkElement { /** Gets this source or sink element as an entity, if it is one. */ Entity asEntity() { - this = TMethodEntityElement(result, _, _, _) or - this = TFieldEntityElement(result, _, _, _) or + this = TMethodOrFieldEntityElement(result, _, _, _) or this = TOtherEntityElement(result) } @@ -182,8 +182,7 @@ module SourceSinkInterpretationInput implements * with the given values for `pkg`, `type` and `subtypes`. */ predicate hasTypeInfo(string pkg, string type, boolean subtypes) { - this = TMethodEntityElement(_, pkg, type, subtypes) or - this = TFieldEntityElement(_, pkg, type, subtypes) + this = TMethodOrFieldEntityElement(_, pkg, type, subtypes) } /** Gets a textual representation of this source or sink element. */ From e813fa346b5764b98442f2014a683f1e9ae11b10 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 25 Oct 2024 14:45:33 +0100 Subject: [PATCH 23/30] Fix case in some test-related file names --- ..._i1_subtypes_false.expected => mad_I1_subtypes_false.expected} | 0 ...ad_i1_subtypes_false.ext.yml => mad_I1_subtypes_false.ext.yml} | 0 .../{mad_i1_subtypes_false.ql => mad_I1_subtypes_false.ql} | 0 ...ad_i1_subtypes_true.expected => mad_I1_subtypes_true.expected} | 0 ...{mad_i1_subtypes_true.ext.yml => mad_I1_subtypes_true.ext.yml} | 0 .../{mad_i1_subtypes_true.ql => mad_I1_subtypes_true.ql} | 0 ..._i2_subtypes_false.expected => mad_I2_subtypes_false.expected} | 0 ...ad_i2_subtypes_false.ext.yml => mad_I2_subtypes_false.ext.yml} | 0 .../{mad_i2_subtypes_false.ql => mad_I2_subtypes_false.ql} | 0 ...ad_i2_subtypes_true.expected => mad_I2_subtypes_true.expected} | 0 ...{mad_i2_subtypes_true.ext.yml => mad_I2_subtypes_true.ext.yml} | 0 .../{mad_i2_subtypes_true.ql => mad_I2_subtypes_true.ql} | 0 ..._s1_subtypes_false.expected => mad_S1_subtypes_false.expected} | 0 ...ad_s1_subtypes_false.ext.yml => mad_S1_subtypes_false.ext.yml} | 0 .../{mad_s1_subtypes_false.ql => mad_S1_subtypes_false.ql} | 0 ...ad_s1_subtypes_true.expected => mad_S1_subtypes_true.expected} | 0 ...{mad_s1_subtypes_true.ext.yml => mad_S1_subtypes_true.ext.yml} | 0 .../{mad_s1_subtypes_true.ql => mad_S1_subtypes_true.ql} | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i1_subtypes_false.expected => mad_I1_subtypes_false.expected} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i1_subtypes_false.ext.yml => mad_I1_subtypes_false.ext.yml} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i1_subtypes_false.ql => mad_I1_subtypes_false.ql} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i1_subtypes_true.expected => mad_I1_subtypes_true.expected} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i1_subtypes_true.ext.yml => mad_I1_subtypes_true.ext.yml} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i1_subtypes_true.ql => mad_I1_subtypes_true.ql} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i2_subtypes_false.expected => mad_I2_subtypes_false.expected} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i2_subtypes_false.ext.yml => mad_I2_subtypes_false.ext.yml} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i2_subtypes_false.ql => mad_I2_subtypes_false.ql} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i2_subtypes_true.expected => mad_I2_subtypes_true.expected} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i2_subtypes_true.ext.yml => mad_I2_subtypes_true.ext.yml} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_i2_subtypes_true.ql => mad_I2_subtypes_true.ql} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_s1_subtypes_false.expected => mad_S1_subtypes_false.expected} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_s1_subtypes_false.ext.yml => mad_S1_subtypes_false.ext.yml} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_s1_subtypes_false.ql => mad_S1_subtypes_false.ql} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_s1_subtypes_true.expected => mad_S1_subtypes_true.expected} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_s1_subtypes_true.ext.yml => mad_S1_subtypes_true.ext.yml} (100%) rename go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/{mad_s1_subtypes_true.ql => mad_S1_subtypes_true.ql} (100%) diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_false.expected similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.expected rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_false.expected diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_false.ext.yml similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ext.yml rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_false.ext.yml diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_false.ql similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_false.ql rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_false.ql diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_true.expected similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.expected rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_true.expected diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_true.ext.yml similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ext.yml rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_true.ext.yml diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_true.ql similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i1_subtypes_true.ql rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I1_subtypes_true.ql diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_false.expected similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.expected rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_false.expected diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_false.ext.yml similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ext.yml rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_false.ext.yml diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_false.ql similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_false.ql rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_false.ql diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_true.expected similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.expected rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_true.expected diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_true.ext.yml similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ext.yml rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_true.ext.yml diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_true.ql similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_i2_subtypes_true.ql rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_I2_subtypes_true.ql diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_false.expected similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.expected rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_false.expected diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_false.ext.yml similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ext.yml rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_false.ext.yml diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_false.ql similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_false.ql rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_false.ql diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_true.expected similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.expected rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_true.expected diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_true.ext.yml similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ext.yml rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_true.ext.yml diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_true.ql similarity index 100% rename from go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_s1_subtypes_true.ql rename to go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_S1_subtypes_true.ql From 57192e8154f49eaa8e216d34979521e0e1d09dfd Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 29 Oct 2024 15:59:14 +0000 Subject: [PATCH 24/30] Add even more tests --- .../mad_PImplEmbedI1_subtypes_true.expected | 3 + .../mad_PImplEmbedI1_subtypes_true.ext.yml | 18 +++ .../mad_PImplEmbedI1_subtypes_true.ql | 26 ++++ .../mad_PImplEmbedI2_subtypes_true.expected | 3 + .../mad_PImplEmbedI2_subtypes_true.ext.yml | 16 +++ .../mad_PImplEmbedI2_subtypes_true.ql | 26 ++++ .../mad_SEmbedP1_subtypes_true.expected | 3 + .../mad_SEmbedP1_subtypes_true.ext.yml | 18 +++ .../mad_SEmbedP1_subtypes_true.ql | 26 ++++ .../mad_SEmbedP2_subtypes_true.expected | 3 + .../mad_SEmbedP2_subtypes_true.ext.yml | 16 +++ .../mad_SEmbedP2_subtypes_true.ql | 26 ++++ .../mad_SEmbedPtrP1_subtypes_true.expected | 3 + .../mad_SEmbedPtrP1_subtypes_true.ext.yml | 18 +++ .../mad_SEmbedPtrP1_subtypes_true.ql | 26 ++++ .../mad_SEmbedPtrP2_subtypes_true.expected | 3 + .../mad_SEmbedPtrP2_subtypes_true.ext.yml | 16 +++ .../mad_SEmbedPtrP2_subtypes_true.ql | 26 ++++ .../mad_SEmbedPtrS1_subtypes_true.expected | 3 + .../mad_SEmbedPtrS1_subtypes_true.ext.yml | 18 +++ .../mad_SEmbedPtrS1_subtypes_true.ql | 26 ++++ .../mad_SEmbedPtrS2_subtypes_true.expected | 3 + .../mad_SEmbedPtrS2_subtypes_true.ext.yml | 16 +++ .../mad_SEmbedPtrS2_subtypes_true.ql | 26 ++++ .../ExternalFlowInheritance/ql_P1.expected | 3 + .../dataflow/ExternalFlowInheritance/ql_P1.ql | 54 ++++++++ .../ExternalFlowInheritance/test_fields.go | 48 ++++++- .../ExternalFlowInheritance/test_methods.go | 74 ++++++++++- .../github.com/nonexistent/test/stub.go | 124 +++++++++++++++--- 29 files changed, 646 insertions(+), 25 deletions(-) create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.ql diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.ext.yml new file mode 100644 index 000000000000..b7a7badf0979 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.ext.yml @@ -0,0 +1,18 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "PImplEmbedI1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "PImplEmbedI1", True, "SourceField", "", "", "", "qltest", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "PImplEmbedI1", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "PImplEmbedI1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "PImplEmbedI1", True, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.ql new file mode 100644 index 000000000000..6e84bbe2ffbf --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI1_subtypes_true.ql @@ -0,0 +1,26 @@ +import go +import ModelValidation +import TestUtilities.InlineExpectationsTest +import MakeTest + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } + + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } +} + +module Flow = TaintTracking::Global; + +module FlowTest implements TestSig { + string getARelevantTag() { result = "PImplEmbedI1[t]" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "PImplEmbedI1[t]" and + exists(DataFlow::Node sink | Flow::flowTo(sink) | + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sink.toString() and + value = "" + ) + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.ext.yml new file mode 100644 index 000000000000..2a10c84a20fa --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.ext.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "PImplEmbedI2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "PImplEmbedI2", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "PImplEmbedI2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.ql new file mode 100644 index 000000000000..63a829d1ac4e --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_PImplEmbedI2_subtypes_true.ql @@ -0,0 +1,26 @@ +import go +import ModelValidation +import TestUtilities.InlineExpectationsTest +import MakeTest + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } + + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } +} + +module Flow = TaintTracking::Global; + +module FlowTest implements TestSig { + string getARelevantTag() { result = "PImplEmbedI2[t]" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "PImplEmbedI2[t]" and + exists(DataFlow::Node sink | Flow::flowTo(sink) | + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sink.toString() and + value = "" + ) + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.ext.yml new file mode 100644 index 000000000000..8a927bde1adf --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.ext.yml @@ -0,0 +1,18 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "SEmbedP1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedP1", True, "SourceField", "", "", "", "qltest", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "SEmbedP1", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "SEmbedP1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedP1", True, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.ql new file mode 100644 index 000000000000..35c780f603d0 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP1_subtypes_true.ql @@ -0,0 +1,26 @@ +import go +import ModelValidation +import TestUtilities.InlineExpectationsTest +import MakeTest + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } + + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } +} + +module Flow = TaintTracking::Global; + +module FlowTest implements TestSig { + string getARelevantTag() { result = "SEmbedP1[t]" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "SEmbedP1[t]" and + exists(DataFlow::Node sink | Flow::flowTo(sink) | + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sink.toString() and + value = "" + ) + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.ext.yml new file mode 100644 index 000000000000..6357f141b117 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.ext.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "SEmbedP2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "SEmbedP2", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "SEmbedP2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.ql new file mode 100644 index 000000000000..6b5cad78d8bc --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedP2_subtypes_true.ql @@ -0,0 +1,26 @@ +import go +import ModelValidation +import TestUtilities.InlineExpectationsTest +import MakeTest + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } + + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } +} + +module Flow = TaintTracking::Global; + +module FlowTest implements TestSig { + string getARelevantTag() { result = "SEmbedP2[t]" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "SEmbedP2[t]" and + exists(DataFlow::Node sink | Flow::flowTo(sink) | + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sink.toString() and + value = "" + ) + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.ext.yml new file mode 100644 index 000000000000..e34aa2af5351 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.ext.yml @@ -0,0 +1,18 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrP1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedPtrP1", True, "SourceField", "", "", "", "qltest", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrP1", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrP1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedPtrP1", True, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.ql new file mode 100644 index 000000000000..344dc37e41a4 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP1_subtypes_true.ql @@ -0,0 +1,26 @@ +import go +import ModelValidation +import TestUtilities.InlineExpectationsTest +import MakeTest + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } + + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } +} + +module Flow = TaintTracking::Global; + +module FlowTest implements TestSig { + string getARelevantTag() { result = "SEmbedPtrP1[t]" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "SEmbedPtrP1[t]" and + exists(DataFlow::Node sink | Flow::flowTo(sink) | + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sink.toString() and + value = "" + ) + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.ext.yml new file mode 100644 index 000000000000..7c03fc22bcbb --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.ext.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrP2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrP2", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrP2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.ql new file mode 100644 index 000000000000..a7c2e497f556 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrP2_subtypes_true.ql @@ -0,0 +1,26 @@ +import go +import ModelValidation +import TestUtilities.InlineExpectationsTest +import MakeTest + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } + + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } +} + +module Flow = TaintTracking::Global; + +module FlowTest implements TestSig { + string getARelevantTag() { result = "SEmbedPtrP2[t]" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "SEmbedPtrP2[t]" and + exists(DataFlow::Node sink | Flow::flowTo(sink) | + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sink.toString() and + value = "" + ) + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.ext.yml new file mode 100644 index 000000000000..81a3500562d3 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.ext.yml @@ -0,0 +1,18 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrS1", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedPtrS1", True, "SourceField", "", "", "", "qltest", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrS1", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrS1", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] + - ["github.com/nonexistent/test", "SEmbedPtrS1", True, "SinkField", "", "", "", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.ql new file mode 100644 index 000000000000..cf847c781bcc --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS1_subtypes_true.ql @@ -0,0 +1,26 @@ +import go +import ModelValidation +import TestUtilities.InlineExpectationsTest +import MakeTest + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } + + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } +} + +module Flow = TaintTracking::Global; + +module FlowTest implements TestSig { + string getARelevantTag() { result = "SEmbedPtrS1[t]" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "SEmbedPtrS1[t]" and + exists(DataFlow::Node sink | Flow::flowTo(sink) | + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sink.toString() and + value = "" + ) + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.ext.yml new file mode 100644 index 000000000000..50c72d96ce18 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.ext.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrS2", True, "Source", "", "", "ReturnValue", "qltest", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrS2", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "SEmbedPtrS2", True, "Sink", "", "", "Argument[0]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.ql new file mode 100644 index 000000000000..0c7b05dd3ff8 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_SEmbedPtrS2_subtypes_true.ql @@ -0,0 +1,26 @@ +import go +import ModelValidation +import TestUtilities.InlineExpectationsTest +import MakeTest + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") } + + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") } +} + +module Flow = TaintTracking::Global; + +module FlowTest implements TestSig { + string getARelevantTag() { result = "SEmbedPtrS2[t]" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "SEmbedPtrS2[t]" and + exists(DataFlow::Node sink | Flow::flowTo(sink) | + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sink.toString() and + value = "" + ) + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.ql new file mode 100644 index 000000000000..3022e13ff749 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.ql @@ -0,0 +1,54 @@ +import go +import ModelValidation +import TestUtilities.InlineExpectationsTest +import MakeTest + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "P1", "Source") and + source = m.getACall().getResult() + ) + or + exists(Field f | + f.hasQualifiedName("github.com/nonexistent/test", "P1", "SourceField") and + source = f.getARead() + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "P1", "Sink") and + sink = m.getACall().getArgument(0) + ) + or + exists(Field f | + f.hasQualifiedName("github.com/nonexistent/test", "P1", "SinkField") and + any(DataFlow::Write w).writesField(_, f, sink) + ) + } +} + +module Flow = TaintTracking::Global; + +module FlowTest implements TestSig { + string getARelevantTag() { result = "ql_P1" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "ql_P1" and + exists(DataFlow::Node sink | Flow::flowTo(sink) | + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sink.toString() and + value = "" + ) + } +} + +class MyStep extends DataFlow::FunctionModel, Method { + MyStep() { this.hasQualifiedName("github.com/nonexistent/test", "P1", "Step") } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + input.isParameter(0) and output.isResult() + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go index 4b6972d67917..86d5828ce120 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_fields.go @@ -4,9 +4,14 @@ import ( "github.com/nonexistent/test" ) +func TestFieldsP1(t test.P1) { + a := t.SourceField + t.SinkField = a // $ P1[f] P1[t] ql_P1 SPURIOUS: ql_S1 +} + func TestFieldsS1(t test.S1) { a := t.SourceField - t.SinkField = a // $ S1[f] S1[t] ql_S1 + t.SinkField = a // $ S1[f] S1[t] ql_S1 SPURIOUS: ql_P1 } func TestFieldsSEmbedI1(t test.SEmbedI1) { @@ -19,9 +24,29 @@ func TestFieldsSImplEmbedI1(t test.SImplEmbedI1) { t.SinkField = a // $ SImplEmbedI1[t] } +func TestFieldsPImplEmbedI1(t test.PImplEmbedI1) { + a := t.SourceField + t.SinkField = a // $ PImplEmbedI1[t] +} + +func TestFieldsSEmbedP1(t test.SEmbedP1) { + a := t.SourceField + t.SinkField = a // $ P1[t] SEmbedP1[t] ql_P1 SPURIOUS: ql_S1 +} + func TestFieldsSEmbedS1(t test.SEmbedS1) { a := t.SourceField - t.SinkField = a // $ S1[t] SEmbedS1[t] ql_S1 + t.SinkField = a // $ S1[t] SEmbedS1[t] ql_S1 SPURIOUS: ql_P1 +} + +func TestFieldsSEmbedPtrP1(t test.SEmbedPtrP1) { + a := t.SourceField + t.SinkField = a // $ P1[t] SEmbedPtrP1[t] ql_P1 SPURIOUS: ql_S1 +} + +func TestFieldsSEmbedPtrS1(t test.SEmbedPtrS1) { + a := t.SourceField + t.SinkField = a // $ S1[t] SEmbedPtrS1[t] ql_S1 SPURIOUS: ql_P1 } func TestFieldsSImplEmbedS1(t test.SImplEmbedS1) { @@ -36,10 +61,25 @@ func TestFieldsSEmbedSEmbedI1(t test.SEmbedSEmbedI1) { func TestFieldsSEmbedSEmbedS1(t test.SEmbedSEmbedS1) { a := t.SourceField - t.SinkField = a // $ S1[t] ql_S1 SEmbedS1[t] + t.SinkField = a // $ S1[t] SEmbedS1[t] ql_S1 SPURIOUS: ql_P1 +} + +func TestFieldsSEmbedSEmbedPtrS1(t test.SEmbedSEmbedPtrS1) { + a := t.SourceField + t.SinkField = a // $ S1[t] SEmbedPtrS1[t] ql_S1 SPURIOUS: ql_P1 +} + +func TestFieldsSEmbedPtrSEmbedS1(t test.SEmbedPtrSEmbedS1) { + a := t.SourceField + t.SinkField = a // $ S1[t] SEmbedS1[t] ql_S1 SPURIOUS: ql_P1 +} + +func TestFieldsSEmbedPtrSEmbedPtrS1(t test.SEmbedPtrSEmbedPtrS1) { + a := t.SourceField + t.SinkField = a // $ S1[t] SEmbedPtrS1[t] ql_S1 SPURIOUS: ql_P1 } func TestFieldsSEmbedS1AndSEmbedS1(t test.SEmbedS1AndSEmbedS1) { a := t.SourceField - t.SinkField = a // $ S1[t] ql_S1 + t.SinkField = a // $ S1[t] ql_S1 SPURIOUS: ql_P1 } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go index a106e4ee9d69..8d4c592e0cd1 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test_methods.go @@ -7,7 +7,7 @@ import ( func TestMethodsI1(t test.I1) { x := t.Source() y := t.Step(x) - t.Sink(y) // $ I1[f] I1[t] ql_I1 SPURIOUS: ql_S1 + t.Sink(y) // $ I1[f] I1[t] ql_I1 SPURIOUS: ql_P1 ql_S1 } func TestMethodsI2(t test.I2) { @@ -22,16 +22,28 @@ func TestMethodsS1(t test.S1) { t.Sink(y) // $ I1[t] S1[f] S1[t] ql_S1 } +func TestMethodsP1(t test.P1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] P1[f] P1[t] ql_P1 +} + func TestMethodsS2(t test.S2) { x := t.Source() y := t.Step(x) t.Sink(y) // $ I1[t] I2[t] } +func TestMethodsP2(t test.P2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] +} + func TestMethodsSEmbedI1(t test.SEmbedI1) { x := t.Source() y := t.Step(x) - t.Sink(y) // $ I1[t] SEmbedI1[t] ql_I1 SPURIOUS: ql_S1 + t.Sink(y) // $ I1[t] SEmbedI1[t] ql_I1 SPURIOUS: ql_P1 ql_S1 } func TestMethodsSEmbedI2(t test.SEmbedI2) { @@ -43,7 +55,7 @@ func TestMethodsSEmbedI2(t test.SEmbedI2) { func TestMethodsIEmbedI1(t test.IEmbedI1) { x := t.Source() y := t.Step(x) - t.Sink(y) // $ I1[t] IEmbedI1[t] ql_I1 SPURIOUS: ql_S1 + t.Sink(y) // $ I1[t] IEmbedI1[t] ql_I1 SPURIOUS: ql_P1 ql_S1 } func TestMethodsIEmbedI2(t test.IEmbedI2) { @@ -64,6 +76,18 @@ func TestMethodsSImplEmbedI2(t test.SImplEmbedI2) { t.Sink(y) // $ I1[t] I2[t] SImplEmbedI2[t] } +func TestMethodsPImplEmbedI1(t test.PImplEmbedI1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] PImplEmbedI1[t] +} + +func TestMethodsPImplEmbedI2(t test.PImplEmbedI2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] PImplEmbedI2[t] +} + func TestMethodsSEmbedS1(t test.SEmbedS1) { x := t.Source() y := t.Step(x) @@ -76,6 +100,30 @@ func TestMethodsSEmbedS2(t test.SEmbedS2) { t.Sink(y) // $ I1[t] I2[t] SEmbedS2[t] } +func TestMethodsSEmbedPtrS1(t test.SEmbedPtrS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] S1[t] SEmbedPtrS1[t] ql_S1 +} + +func TestMethodsSEmbedPtrS2(t test.SEmbedPtrS2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] SEmbedPtrS2[t] +} + +func TestMethodsSEmbedP1(t *test.SEmbedP1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] P1[t] SEmbedP1[t] ql_P1 +} + +func TestMethodsSEmbedP2(t *test.SEmbedP2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] I2[t] SEmbedP2[t] +} + func TestMethodsSImplEmbedS1(t test.SImplEmbedS1) { x := t.Source() y := t.Step(x) @@ -91,7 +139,7 @@ func TestMethodsSImplEmbedS2(t test.SImplEmbedS2) { func TestMethodsSEmbedSEmbedI1(t test.SEmbedSEmbedI1) { x := t.Source() y := t.Step(x) - t.Sink(y) // $ I1[t] SEmbedI1[t] ql_I1 SPURIOUS: ql_S1 + t.Sink(y) // $ I1[t] SEmbedI1[t] ql_I1 SPURIOUS: ql_P1 ql_S1 } func TestMethodsSEmbedSEmbedS1(t test.SEmbedSEmbedS1) { @@ -100,6 +148,24 @@ func TestMethodsSEmbedSEmbedS1(t test.SEmbedSEmbedS1) { t.Sink(y) // $ I1[t] S1[t] SEmbedS1[t] ql_S1 } +func TestMethodsSEmbedSEmbedPtrS1(t test.SEmbedSEmbedPtrS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] S1[t] SEmbedPtrS1[t] ql_S1 +} + +func TestMethodsSEmbedPtrSEmbedS1(t test.SEmbedPtrSEmbedS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] S1[t] SEmbedS1[t] ql_S1 +} + +func TestMethodsSEmbedPtrSEmbedPtrS1(t test.SEmbedPtrSEmbedPtrS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) // $ I1[t] S1[t] SEmbedPtrS1[t] ql_S1 +} + func TestMethodsSEmbedS1AndSEmbedS1(t test.SEmbedS1AndSEmbedS1) { x := t.Source() y := t.Step(x) diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go index f2ee55d438ea..093c24eab9d9 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go @@ -21,30 +21,61 @@ type S1 struct { SinkField string } -func (t *S1) Source() interface{} { +func (t S1) Source() interface{} { return nil } -func (t *S1) Sink(interface{}) {} +func (t S1) Sink(interface{}) {} -func (t *S1) Step(val interface{}) interface{} { +func (t S1) Step(val interface{}) interface{} { + return val +} + +// A struct type whose pointer type implements I1 +type P1 struct { + SourceField string + SinkField string +} + +func (t *P1) Source() interface{} { + return nil +} + +func (t *P1) Sink(interface{}) {} + +func (t *P1) Step(val interface{}) interface{} { return val } // A struct type implementing I2 type S2 struct{} -func (t *S2) Source() interface{} { +func (t S2) Source() interface{} { + return nil +} + +func (t S2) Sink(interface{}) {} + +func (t S2) Step(val interface{}) interface{} { + return val +} + +func (t S2) ExtraMethodI2() {} + +// A struct type whose pointer type implements I2 +type P2 struct{} + +func (t *P2) Source() interface{} { return nil } -func (t *S2) Sink(interface{}) {} +func (t *P2) Sink(interface{}) {} -func (t *S2) Step(val interface{}) interface{} { +func (t *P2) Step(val interface{}) interface{} { return val } -func (t *S2) ExtraMethodI2() {} +func (t *P2) ExtraMethodI2() {} // A struct type embedding I1 type SEmbedI1 struct { @@ -76,13 +107,13 @@ type SImplEmbedI1 struct { SinkField string } -func (t *SImplEmbedI1) Source() interface{} { +func (t SImplEmbedI1) Source() interface{} { return nil } -func (t *SImplEmbedI1) Sink(interface{}) {} +func (t SImplEmbedI1) Sink(interface{}) {} -func (t *SImplEmbedI1) Step(val interface{}) interface{} { +func (t SImplEmbedI1) Step(val interface{}) interface{} { return val } @@ -90,26 +121,76 @@ func (t *SImplEmbedI1) Step(val interface{}) interface{} { // methods of the embedded field are not promoted. type SImplEmbedI2 struct{ I2 } -func (t *SImplEmbedI2) Source() interface{} { +func (t SImplEmbedI2) Source() interface{} { return nil } -func (t *SImplEmbedI2) Sink(interface{}) {} +func (t SImplEmbedI2) Sink(interface{}) {} -func (t *SImplEmbedI2) Step(val interface{}) interface{} { +func (t SImplEmbedI2) Step(val interface{}) interface{} { return val } -func (t *SImplEmbedI2) ExtraMethodI2() {} +func (t SImplEmbedI2) ExtraMethodI2() {} -// A struct type embedding S1 -type SEmbedS1 struct { - S1 +// A struct type embedding I1 and separately implementing its methods on its +// pointer type, so the methods of the embedded field are not promoted. +type PImplEmbedI1 struct { + I1 + SourceField string + SinkField string +} + +func (t *PImplEmbedI1) Source() interface{} { + return nil } +func (t *PImplEmbedI1) Sink(interface{}) {} + +func (t *PImplEmbedI1) Step(val interface{}) interface{} { + return val +} + +// A struct type embedding I2 and separately implementing its methods, so the +// methods of the embedded field are not promoted. +type PImplEmbedI2 struct{ I2 } + +func (t *PImplEmbedI2) Source() interface{} { + return nil +} + +func (t *PImplEmbedI2) Sink(interface{}) {} + +func (t *PImplEmbedI2) Step(val interface{}) interface{} { + return val +} + +func (t *PImplEmbedI2) ExtraMethodI2() {} + +// A struct type embedding S1 +type SEmbedS1 struct{ S1 } + // A struct type embedding S2 type SEmbedS2 struct{ S2 } +// A struct type embedding P1 +type SEmbedP1 struct{ P1 } + +// A struct type embedding P2 +type SEmbedP2 struct{ P2 } + +// A struct type embedding *S1 +type SEmbedPtrS1 struct{ *S1 } + +// A struct type embedding *S2 +type SEmbedPtrS2 struct{ *S2 } + +// A struct type embedding *P1 +type SEmbedPtrP1 struct{ *P1 } + +// A struct type embedding *P2 +type SEmbedPtrP2 struct{ *P2 } + // A struct type embedding S1 and separately implementing I1's methods and // fields, so the methods and fields of the embedded field are not promoted. type SImplEmbedS1 struct { @@ -154,6 +235,15 @@ type SEmbedSEmbedI1 struct { // A struct type embedding SEmbedS1 type SEmbedSEmbedS1 struct{ SEmbedS1 } +// A struct type embedding SEmbedPtrS1 +type SEmbedSEmbedPtrS1 struct{ SEmbedPtrS1 } + +// A struct type embedding SEmbedS1 +type SEmbedPtrSEmbedS1 struct{ *SEmbedS1 } + +// A struct type embedding SEmbedPtrS1 +type SEmbedPtrSEmbedPtrS1 struct{ *SEmbedPtrS1 } + // A struct type embedding S1 and SEmbedS1 type SEmbedS1AndSEmbedS1 struct { S1 From b6a31b1def6f74410231d09d2225225b28fa7a2f Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 30 Oct 2024 14:48:45 +0000 Subject: [PATCH 25/30] Restrict to Methods --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 4e2d1552dab9..4770297bfcc4 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -243,6 +243,7 @@ module SourceSinkInterpretationInput implements ( not callTarget instanceof Method or + callTarget instanceof Method and elementAppliesToQualifier(result, cn.getReceiver()) ) ) From 3986dffc9180d055bfc02b916e2bac0fdb64723e Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 30 Oct 2024 15:45:49 +0000 Subject: [PATCH 26/30] Keep methods and fields separate in SourceOrSinkElement This improves performance. --- go/ql/lib/semmle/go/dataflow/ExternalFlow.qll | 8 ++--- .../go/dataflow/internal/FlowSummaryImpl.qll | 34 +++++++++++-------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll index c557b5af7de3..c738221c093e 100644 --- a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll @@ -477,8 +477,8 @@ SourceSinkInterpretationInput::SourceOrSinkElement interpretElement( exists(string p | p = interpretPackage(pkg) | result.hasTypeInfo(p, type, subtypes) and ( - result.asEntity().(Field).hasQualifiedName(p, type, name) or - result.asEntity().(Method).hasQualifiedName(p, type, name) + result.asFieldEntity().hasQualifiedName(p, type, name) or + result.asMethodEntity().hasQualifiedName(p, type, name) ) or subtypes = true and @@ -488,12 +488,12 @@ SourceSinkInterpretationInput::SourceOrSinkElement interpretElement( m2.getName() = name and m2.getReceiverBaseType().hasQualifiedName(pkg2, type2) | - result.asEntity() = m2 and + result.asMethodEntity() = m2 and result.hasTypeInfo(pkg2, type2, subtypes) ) or type = "" and - exists(Entity e | e.hasQualifiedName(p, name) | result.asEntity() = e) + exists(Entity e | e.hasQualifiedName(p, name) | result.asOtherEntity() = e) ) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 4770297bfcc4..792584e1da7a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -153,11 +153,12 @@ module SourceSinkInterpretationInput implements // Methods having multiple qualified names, a given Method is liable to have // more than one SourceOrSinkElement, one for each of the names it claims. private newtype TSourceOrSinkElement = - TMethodOrFieldEntityElement(Entity e, string pkg, string type, boolean subtypes) { - ( - e.(Method).hasQualifiedName(pkg, type, _) or - e.(Field).hasQualifiedName(pkg, type, _) - ) and + TMethodEntityElement(Method m, string pkg, string type, boolean subtypes) { + m.hasQualifiedName(pkg, type, _) and + subtypes = [true, false] + } or + TFieldEntityElement(Field f, string pkg, string type, boolean subtypes) { + f.hasQualifiedName(pkg, type, _) and subtypes = [true, false] } or TOtherEntityElement(Entity e) { @@ -170,10 +171,15 @@ module SourceSinkInterpretationInput implements class SourceOrSinkElement extends TSourceOrSinkElement { /** Gets this source or sink element as an entity, if it is one. */ Entity asEntity() { - this = TMethodOrFieldEntityElement(result, _, _, _) or - this = TOtherEntityElement(result) + result = [this.asMethodEntity(), this.asFieldEntity(), this.asOtherEntity()] } + Method asMethodEntity() { this = TMethodEntityElement(result, _, _, _) } + + Field asFieldEntity() { this = TFieldEntityElement(result, _, _, _) } + + Entity asOtherEntity() { this = TOtherEntityElement(result) } + /** Gets this source or sink element as an AST node, if it is one. */ AstNode asAstNode() { this = TAstElement(result) } @@ -182,7 +188,8 @@ module SourceSinkInterpretationInput implements * with the given values for `pkg`, `type` and `subtypes`. */ predicate hasTypeInfo(string pkg, string type, boolean subtypes) { - this = TMethodOrFieldEntityElement(_, pkg, type, subtypes) + this = TMethodEntityElement(_, pkg, type, subtypes) or + this = TFieldEntityElement(_, pkg, type, subtypes) } /** Gets a textual representation of this source or sink element. */ @@ -239,11 +246,10 @@ module SourceSinkInterpretationInput implements cn = this.asCall().getNode() and callTarget = cn.getTarget() | - result.asEntity() = callTarget and ( - not callTarget instanceof Method + result.asOtherEntity() = callTarget or - callTarget instanceof Method and + result.asMethodEntity() = callTarget and elementAppliesToQualifier(result, cn.getReceiver()) ) ) @@ -302,7 +308,7 @@ module SourceSinkInterpretationInput implements // `syntacticQualBaseType`'s underlying type might be a struct type and `sse` // might be a promoted method or field in it. targetType = - getIntermediateEmbeddedType(sse.asEntity(), syntacticQualBaseType.getUnderlyingType()) + getIntermediateEmbeddedType(sse.asMethodEntity(), syntacticQualBaseType.getUnderlyingType()) ) ) } @@ -382,7 +388,7 @@ module SourceSinkInterpretationInput implements or exists(DataFlow::FieldReadNode frn | frn = n | c = "" and - frn.getField() = pragma[only_bind_into](e).asEntity() and + frn.getField() = pragma[only_bind_into](e).asFieldEntity() and elementAppliesToQualifier(pragma[only_bind_into](e), frn.getBase()) ) ) @@ -400,7 +406,7 @@ module SourceSinkInterpretationInput implements or exists(SourceOrSinkElement e, DataFlow::Write fw, DataFlow::Node base, Field f | e = mid.asElement() and - f = e.asEntity() + f = e.asFieldEntity() | c = "" and fw.writesField(base, f, node.asNode()) and From 6af5b55d5123660b51b2ecdc463e9f6e49374625 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 6 Nov 2024 14:24:39 +0000 Subject: [PATCH 27/30] Refactor elementAppliesToQualifier This is needed for performance when there are lots of embeddings. --- go/ql/lib/semmle/go/dataflow/ExternalFlow.qll | 10 ++- .../go/dataflow/internal/FlowSummaryImpl.qll | 63 ++++++++++--------- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll index c738221c093e..a59c7294e802 100644 --- a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll @@ -475,10 +475,9 @@ SourceSinkInterpretationInput::SourceOrSinkElement interpretElement( // Go does not need to distinguish functions with signature signature = "" and exists(string p | p = interpretPackage(pkg) | - result.hasTypeInfo(p, type, subtypes) and - ( - result.asFieldEntity().hasQualifiedName(p, type, name) or - result.asMethodEntity().hasQualifiedName(p, type, name) + exists(Entity e | result.hasFullInfo(e, p, type, subtypes) | + e.(Field).hasQualifiedName(p, type, name) or + e.(Method).hasQualifiedName(p, type, name) ) or subtypes = true and @@ -488,8 +487,7 @@ SourceSinkInterpretationInput::SourceOrSinkElement interpretElement( m2.getName() = name and m2.getReceiverBaseType().hasQualifiedName(pkg2, type2) | - result.asMethodEntity() = m2 and - result.hasTypeInfo(pkg2, type2, subtypes) + result.hasFullInfo(m2, pkg2, type2, subtypes) ) or type = "" and diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 792584e1da7a..ed3006a8d740 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -185,23 +185,23 @@ module SourceSinkInterpretationInput implements /** * Holds if this source or sink element is a method or field that was specified - * with the given values for `pkg`, `type` and `subtypes`. + * with the given values for `e`, `pkg`, `type` and `subtypes`. */ - predicate hasTypeInfo(string pkg, string type, boolean subtypes) { - this = TMethodEntityElement(_, pkg, type, subtypes) or - this = TFieldEntityElement(_, pkg, type, subtypes) + predicate hasFullInfo(Entity e, string pkg, string type, boolean subtypes) { + this = TMethodEntityElement(e, pkg, type, subtypes) or + this = TFieldEntityElement(e, pkg, type, subtypes) } /** Gets a textual representation of this source or sink element. */ string toString() { - not this.hasTypeInfo(_, _, _) and + (this instanceof TOtherEntityElement or this instanceof TAstElement) and result = "element representing " + [this.asEntity().toString(), this.asAstNode().toString()] or - exists(string pkg, string name, boolean subtypes | - this.hasTypeInfo(pkg, name, subtypes) and + exists(Entity e, string pkg, string name, boolean subtypes | + this.hasFullInfo(e, pkg, name, subtypes) and result = - "element representing " + this.asEntity().toString() + " with receiver type " + pkg + "." + - name + " and subtypes=" + subtypes + "element representing " + e.toString() + " with receiver type " + pkg + "." + name + + " and subtypes=" + subtypes ) } @@ -249,8 +249,8 @@ module SourceSinkInterpretationInput implements ( result.asOtherEntity() = callTarget or - result.asMethodEntity() = callTarget and - elementAppliesToQualifier(result, cn.getReceiver()) + callTarget instanceof Method and + result = getElementWithQualifier(callTarget, cn.getReceiver()) ) ) } @@ -278,22 +278,20 @@ module SourceSinkInterpretationInput implements } /** - * Holds if method or field spec `sse` applies in the context of qualifier `qual`. + * Gets a method or field spec for `e` which applies in the context of + * qualifier `qual`. * - * Note that naively checking `sse.asEntity()`'s qualified name is not correct, because - * `Method`s and `Field`s may have multiple qualified names due to embedding. We must instead - * check that the specific name given by `sse.hasTypeInfo` refers to either `qual`'s type - * or to a type it embeds. + * Note that naively checking `e`'s qualified name is not correct, because + * `Method`s and `Field`s may have multiple qualified names due to embedding. + * We must instead check that the package and type name given by + * `result.hasFullInfo` refer to either `qual`'s type or to a type it embeds. */ - bindingset[sse, qual] + bindingset[e, qual] pragma[inline_late] - private predicate elementAppliesToQualifier(SourceOrSinkElement sse, DataFlow::Node qual) { - exists( - string pkg, string typename, boolean subtypes, Type syntacticQualBaseType, Type targetType - | - sse.hasTypeInfo(pkg, typename, subtypes) and - targetType.hasQualifiedName(pkg, typename) and - syntacticQualBaseType = getSyntacticQualifierBaseType(qual) + private SourceOrSinkElement getElementWithQualifier(Entity e, DataFlow::Node qual) { + exists(boolean subtypes, Type syntacticQualBaseType, Type targetType | + syntacticQualBaseType = getSyntacticQualifierBaseType(qual) and + result = constructElement(e, targetType, subtypes) | subtypes = [true, false] and syntacticQualBaseType = targetType @@ -307,12 +305,20 @@ module SourceSinkInterpretationInput implements or // `syntacticQualBaseType`'s underlying type might be a struct type and `sse` // might be a promoted method or field in it. - targetType = - getIntermediateEmbeddedType(sse.asMethodEntity(), syntacticQualBaseType.getUnderlyingType()) + targetType = getIntermediateEmbeddedType(e, syntacticQualBaseType.getUnderlyingType()) ) ) } + bindingset[e, targetType, subtypes] + pragma[inline_late] + private SourceOrSinkElement constructElement(Entity e, Type targetType, boolean subtypes) { + exists(string pkg, string typename | + targetType.hasQualifiedName(pkg, typename) and + result.hasFullInfo(e, pkg, typename, subtypes) + ) + } + /** * Gets the type of an embedded field of `st` which is on the path to `e`, * which is a promoted method or field of `st`, or its base type if it's a @@ -388,8 +394,7 @@ module SourceSinkInterpretationInput implements or exists(DataFlow::FieldReadNode frn | frn = n | c = "" and - frn.getField() = pragma[only_bind_into](e).asFieldEntity() and - elementAppliesToQualifier(pragma[only_bind_into](e), frn.getBase()) + pragma[only_bind_into](e) = getElementWithQualifier(frn.getField(), frn.getBase()) ) ) } @@ -410,7 +415,7 @@ module SourceSinkInterpretationInput implements | c = "" and fw.writesField(base, f, node.asNode()) and - elementAppliesToQualifier(pragma[only_bind_into](e), base) + pragma[only_bind_into](e) = getElementWithQualifier(f, base) ) } } From d3a6452860926873a0cbdbe91e2755bd9ed1ca71 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 6 Nov 2024 16:42:14 +0000 Subject: [PATCH 28/30] Add missing QLDoc --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index ed3006a8d740..9efb61cf3eaf 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -174,10 +174,13 @@ module SourceSinkInterpretationInput implements result = [this.asMethodEntity(), this.asFieldEntity(), this.asOtherEntity()] } + /** Gets this source or sink element as a method, if it is one. */ Method asMethodEntity() { this = TMethodEntityElement(result, _, _, _) } + /** Gets this source or sink element as a field, if it is one. */ Field asFieldEntity() { this = TFieldEntityElement(result, _, _, _) } + /** Gets this source or sink element as an entity which isn't a field or method, if it is one. */ Entity asOtherEntity() { this = TOtherEntityElement(result) } /** Gets this source or sink element as an AST node, if it is one. */ From 13fb92ad3e77d5211917166cb0a0d202a4c3d695 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 11 Nov 2024 23:53:14 +0000 Subject: [PATCH 29/30] Rename `getIntermediateEmbeddedType` --- go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 9efb61cf3eaf..b82039a32fe3 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -308,7 +308,7 @@ module SourceSinkInterpretationInput implements or // `syntacticQualBaseType`'s underlying type might be a struct type and `sse` // might be a promoted method or field in it. - targetType = getIntermediateEmbeddedType(e, syntacticQualBaseType.getUnderlyingType()) + targetType = getAnIntermediateEmbeddedType(e, syntacticQualBaseType.getUnderlyingType()) ) ) } @@ -327,7 +327,7 @@ module SourceSinkInterpretationInput implements * which is a promoted method or field of `st`, or its base type if it's a * pointer type. */ - private Type getIntermediateEmbeddedType(Entity e, StructType st) { + private Type getAnIntermediateEmbeddedType(Entity e, StructType st) { exists(Field field1, Field field2, int depth1, int depth2, Type t2 | field1 = st.getFieldAtDepth(_, depth1) and field2 = st.getFieldAtDepth(_, depth2) and From fd4a6d4bb83f00aeb0d40550ae22dd151c066bbb Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 11 Nov 2024 23:55:57 +0000 Subject: [PATCH 30/30] Change note --- .../change-notes/2024-11-11-models-as-data-subtypes-column.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 go/ql/lib/change-notes/2024-11-11-models-as-data-subtypes-column.md diff --git a/go/ql/lib/change-notes/2024-11-11-models-as-data-subtypes-column.md b/go/ql/lib/change-notes/2024-11-11-models-as-data-subtypes-column.md new file mode 100644 index 000000000000..25115f74d711 --- /dev/null +++ b/go/ql/lib/change-notes/2024-11-11-models-as-data-subtypes-column.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* The behaviour of the `subtypes` column in models-as-data now matches other languages more closely.