Compare commits

..

4 Commits

Author SHA1 Message Date
Taus
66743b4351 Python: hotfix - disable instanceFieldStep to avoid type-tracker blowup
The `instanceFieldStep` disjunct of `TypeTrackingInput::levelStepCall`
that was added in 7.2.0 uses `classInstanceTracker(cls)` -- which is
itself a type-tracker -- inside `levelStepCall`. That creates a
structural mutual recursion between the main type-tracker fixpoint and
`classInstanceTracker`, causing the type-tracker delta to blow up to
~100M tuples per iteration on some OOP-heavy Python codebases.
Verified on the python/mypy database: SSRF query wall time goes from
~12s before the offending commit to >40 minutes after it.

This hotfix temporarily drops the `instanceFieldStep` disjunct and
keeps only `inheritedFieldStep`, which does not pull on the call
graph and is well-behaved (verified at ~12s on mypy). The
`instanceFieldStep` helper predicate itself is kept in place, and
the `levelStepCall` body has a commented-out call to it so the
change is trivial to re-enable once the recursion issue is properly
addressed.
2026-07-01 09:37:03 +01:00
Owen Mansel-Chan
c31c5cacde Fix cleartext logging test 2026-06-30 23:54:49 +01:00
Owen Mansel-Chan
c84c6f33a9 Revert "Merge pull request #21888 from owen-mc/py/remove-imprecise-container-steps"
This reverts commit 1f91f915c7, reversing
changes made to ba8eebe2b5.
2026-06-30 23:53:56 +01:00
Owen Mansel-Chan
5aa0429e97 Revert "Merge pull request #21941 from hvitved/python/content-approx"
This reverts commit f5919875b7, reversing
changes made to 8d456df26f.
2026-06-30 23:46:53 +01:00
189 changed files with 8978 additions and 11419 deletions

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* Removed support for using variables as sources and sinks in models-as-data. Users of this feature should convert such sources and sinks to models defined using the QL language.

View File

@@ -931,6 +931,31 @@ private Element interpretElement0(
signature = "" and signature = "" and
elementSpec(namespace, type, subtypes, name, signature, _) elementSpec(namespace, type, subtypes, name, signature, _)
) )
or
// Member variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
exists(Class namedClass, Class classWithMember, MemberVariable member |
member.getName() = name and
member = classWithMember.getAMember() and
namedClass.hasQualifiedName(namespace, type) and
result = member
|
// field declared in the named type or a subtype of it (or an extension of any)
subtypes = true and
classWithMember = namedClass.getADerivedClass*()
or
// field declared directly in the named type (or an extension of it)
subtypes = false and
classWithMember = namedClass
)
or
// Global or namespace variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
type = "" and
subtypes = false and
result = any(GlobalOrNamespaceVariable v | v.hasQualifiedName(namespace, name))
} }
cached cached

View File

@@ -6,7 +6,6 @@ private import cpp as Cpp
private import codeql.dataflow.internal.FlowSummaryImpl private import codeql.dataflow.internal.FlowSummaryImpl
private import codeql.dataflow.internal.AccessPathSyntax as AccessPath private import codeql.dataflow.internal.AccessPathSyntax as AccessPath
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific as DataFlowImplSpecific private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific as DataFlowImplSpecific
private import semmle.code.cpp.dataflow.ExternalFlow private import semmle.code.cpp.dataflow.ExternalFlow
@@ -21,22 +20,8 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
class SinkBase = Void; class SinkBase = Void;
class FlowSummaryCallBase = CallInstruction;
predicate callableFromSource(SummarizedCallableBase c) { exists(c.getBlock()) } predicate callableFromSource(SummarizedCallableBase c) { exists(c.getBlock()) }
FlowSummaryCallBase getASourceCall(SummarizedCallableBase sc) {
result.getStaticCallTarget() = sc
}
DataFlowCallable getSummarizedCallableAsDataFlowCallable(SummarizedCallableBase c) {
result.asSummarizedCallable() = c
}
DataFlowCallable getSourceCallEnclosingCallable(FlowSummaryCallBase call) {
result.asSourceCallable() = call.getEnclosingFunction()
}
ArgumentPosition callbackSelfParameterPosition() { result = TDirectPosition(-1) } ArgumentPosition callbackSelfParameterPosition() { result = TDirectPosition(-1) }
ReturnKind getStandardReturnValueKind() { result = getReturnValueKind("") } ReturnKind getStandardReturnValueKind() { result = getReturnValueKind("") }
@@ -45,10 +30,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
arg = repeatStars(result.(NormalReturnKind).getIndirectionIndex()) arg = repeatStars(result.(NormalReturnKind).getIndirectionIndex())
} }
ParameterPosition getFlowSummaryParameterPosition(ReturnKind rk) {
result = TFlowSummaryPosition(rk)
}
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() } string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }
string encodeArgumentPosition(ArgumentPosition pos) { result = pos.toString() } string encodeArgumentPosition(ArgumentPosition pos) { result = pos.toString() }
@@ -133,22 +114,10 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
private import Make<Location, DataFlowImplSpecific::CppDataFlow, Input> as Impl private import Make<Location, DataFlowImplSpecific::CppDataFlow, Input> as Impl
private module StepsInput implements Impl::Private::StepsInputSig { private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable sc) { DataFlowCall getACall(Public::SummarizedCallable sc) {
result.getStaticCallTarget().getUnderlyingCallable() = sc result.getStaticCallTarget().getUnderlyingCallable() = sc
} }
Node getSourceOutNode(Input::FlowSummaryCallBase call, ReturnKind rk) {
exists(IndirectReturnOutNode out | result = out |
out.getCallInstruction() = call and
pragma[only_bind_out](rk.(NormalReturnKind).getIndirectionIndex()) =
pragma[only_bind_out](out.getIndirectionIndex())
)
}
DataFlowCallable getSourceNodeEnclosingCallable(Input::SourceBase source) { none() } DataFlowCallable getSourceNodeEnclosingCallable(Input::SourceBase source) { none() }
Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) { none() } Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) { none() }
@@ -261,11 +230,40 @@ module SourceSinkInterpretationInput implements
/** Provides additional sink specification logic. */ /** Provides additional sink specification logic. */
bindingset[c] bindingset[c]
predicate interpretOutput(string c, InterpretNode mid, InterpretNode node) { none() } predicate interpretOutput(string c, InterpretNode mid, InterpretNode node) {
// Allow variables to be picked as output nodes.
exists(Node n, Element ast |
n = node.asNode() and
ast = mid.asElement()
|
c = "" and
n.asExpr().(VariableAccess).getTarget() = ast
)
}
/** Provides additional source specification logic. */ /** Provides additional source specification logic. */
bindingset[c] bindingset[c]
predicate interpretInput(string c, InterpretNode mid, InterpretNode node) { none() } predicate interpretInput(string c, InterpretNode mid, InterpretNode node) {
exists(Node n, Element ast, VariableAccess e |
n = node.asNode() and
ast = mid.asElement() and
e.getTarget() = ast
|
// Allow variables to be picked as input nodes.
// We could simply do this as `e = n.asExpr()`, but that would not allow
// us to pick `x` as a sink in an example such as `x = source()` (but
// only subsequent uses of `x`) since the variable access on `x` doesn't
// actually load the value of `x`. So instead, we pick the instruction
// node corresponding to the generated `StoreInstruction` and use the
// expression associated with the destination instruction. This means
// that the `x` in `x = source()` can be marked as an input.
c = "" and
exists(StoreInstruction store |
store.getDestinationAddress().getUnconvertedResultExpression() = e and
n.asInstruction() = store
)
)
}
} }
module Private { module Private {

View File

@@ -1534,8 +1534,12 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
result = this.getSummaryNode().getSummarizedCallable() result = this.getSummaryNode().getSummarizedCallable()
} }
/**
* Gets the enclosing callable. For a `FlowSummaryNode` this is always the
* summarized function this node is part of.
*/
override DataFlowCallable getEnclosingCallable() { override DataFlowCallable getEnclosingCallable() {
result = FlowSummaryImpl::Private::getEnclosingCallable(this.getSummaryNode()) result.asSummarizedCallable() = this.getSummarizedCallable()
} }
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() } override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }

View File

@@ -561,21 +561,6 @@ class SummaryArgumentNode extends ArgumentNode, FlowSummaryNode {
} }
} }
/** An argument node that re-enters return output as input to a flow summary. */
private class FlowSummaryArgumentNode extends ArgumentNode, FlowSummaryNode {
private CallInstruction callInstruction;
private ReturnKind rk;
FlowSummaryArgumentNode() {
this.getSummaryNode() = FlowSummaryImpl::Private::summaryArgumentNode(callInstruction, rk)
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
call.asCallInstruction() = callInstruction and
pos = TFlowSummaryPosition(rk)
}
}
/** A parameter position represented by an integer. */ /** A parameter position represented by an integer. */
class ParameterPosition = Position; class ParameterPosition = Position;
@@ -631,18 +616,6 @@ class IndirectionPosition extends Position, TIndirectionPosition {
final override int getIndirectionIndex() { result = indirectionIndex } final override int getIndirectionIndex() { result = indirectionIndex }
} }
class FlowSummaryPosition extends Position, TFlowSummaryPosition {
ReturnKind rk;
FlowSummaryPosition() { this = TFlowSummaryPosition(rk) }
override string toString() { result = "write to: " + rk.toString() }
override int getArgumentIndex() { none() }
final override int getIndirectionIndex() { result = rk.getIndirectionIndex() }
}
newtype TPosition = newtype TPosition =
TDirectPosition(int argumentIndex) { TDirectPosition(int argumentIndex) {
exists(any(CallInstruction c).getArgument(argumentIndex)) exists(any(CallInstruction c).getArgument(argumentIndex))
@@ -661,8 +634,7 @@ newtype TPosition =
p = f.getParameter(argumentIndex) and p = f.getParameter(argumentIndex) and
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1] indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1]
) )
} or }
TFlowSummaryPosition(ReturnKind rk) { FlowSummaryImpl::Private::relevantFlowSummaryPosition(rk) }
private newtype TReturnKind = private newtype TReturnKind =
TNormalReturnKind(int indirectionIndex) { TNormalReturnKind(int indirectionIndex) {

View File

@@ -158,7 +158,7 @@ private module Cached {
model = "" model = ""
or or
// models-as-data summarized flow // models-as-data summarized flow
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model) nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
} }

View File

@@ -67,7 +67,7 @@ private module Cached {
model = "" model = ""
or or
// models-as-data summarized flow // models-as-data summarized flow
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model) nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
or or
// object->field conflation for content that is a `TaintInheritingContent`. // object->field conflation for content that is a `TaintInheritingContent`.

View File

@@ -53,17 +53,14 @@ models
| 52 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated | | 52 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 53 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual | | 53 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 54 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual | | 54 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 55 | Summary: ; MyString; true; operator[]; ; ; Argument[-1]; ReturnValue[*]; taint; manual | | 55 | Summary: ; TemplateClass1; true; templateFunction2<U,V>; (U,V); ; Argument[1]; ReturnValue; value; manual |
| 56 | Summary: ; MyString; true; operator[]; ; ; ReturnValue[*]; Argument[-1]; taint; manual | | 56 | Summary: ; TemplateClass1<T>; false; templateFunction<U>; (T,U); ; Argument[0]; ReturnValue; value; manual |
| 57 | Summary: ; ReverseFlow; true; get_ptr; ; ; ReturnValue[*]; Argument[-1].Field[ReverseFlow::value]; value; manual | | 57 | Summary: ; TemplateClass2<T,U>; true; function; (U,T); ; Argument[1]; ReturnValue; value; manual |
| 58 | Summary: ; TemplateClass1; true; templateFunction2<U,V>; (U,V); ; Argument[1]; ReturnValue; value; manual | | 58 | Summary: Azure::Core::IO; BodyStream; true; Read; ; ; Argument[-1]; Argument[*0]; taint; manual |
| 59 | Summary: ; TemplateClass1<T>; false; templateFunction<U>; (T,U); ; Argument[0]; ReturnValue; value; manual | | 59 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; taint; manual |
| 60 | Summary: ; TemplateClass2<T,U>; true; function; (U,T); ; Argument[1]; ReturnValue; value; manual | | 60 | Summary: Azure::Core::IO; BodyStream; true; ReadToEnd; ; ; Argument[-1]; ReturnValue.Element; taint; manual |
| 61 | Summary: Azure::Core::IO; BodyStream; true; Read; ; ; Argument[-1]; Argument[*0]; taint; manual | | 61 | Summary: Azure; Nullable; true; Value; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
| 62 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; taint; manual | | 62 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
| 63 | Summary: Azure::Core::IO; BodyStream; true; ReadToEnd; ; ; Argument[-1]; ReturnValue.Element; taint; manual |
| 64 | Summary: Azure; Nullable; true; Value; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
| 65 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
edges edges
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:32 | | asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:32 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:32 Sink:MaD:2 | | asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:32 Sink:MaD:2 |
@@ -72,16 +69,16 @@ edges
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | | | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | | | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 | | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:65 | | asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:62 |
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:253:48:253:60 | *call to GetBodyStream | provenance | Src:MaD:29 | | azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:253:48:253:60 | *call to GetBodyStream | provenance | Src:MaD:29 |
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:257:5:257:8 | *resp | provenance | | | azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:257:5:257:8 | *resp | provenance | |
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:262:5:262:8 | *resp | provenance | | | azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:262:5:262:8 | *resp | provenance | |
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:266:38:266:41 | *resp | provenance | | | azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:266:38:266:41 | *resp | provenance | |
| azure.cpp:257:5:257:8 | *resp | azure.cpp:257:16:257:21 | Read output argument | provenance | MaD:61 | | azure.cpp:257:5:257:8 | *resp | azure.cpp:257:16:257:21 | Read output argument | provenance | MaD:58 |
| azure.cpp:257:16:257:21 | Read output argument | azure.cpp:258:10:258:16 | * ... | provenance | | | azure.cpp:257:16:257:21 | Read output argument | azure.cpp:258:10:258:16 | * ... | provenance | |
| azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument | provenance | MaD:62 | | azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument | provenance | MaD:59 |
| azure.cpp:262:23:262:28 | ReadToCount output argument | azure.cpp:263:10:263:16 | * ... | provenance | | | azure.cpp:262:23:262:28 | ReadToCount output argument | azure.cpp:263:10:263:16 | * ... | provenance | |
| azure.cpp:266:38:266:41 | *resp | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | MaD:63 | | azure.cpp:266:38:266:41 | *resp | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | MaD:60 |
| azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | | | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | |
| azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:267:10:267:12 | vec [element] | provenance | | | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:267:10:267:12 | vec [element] | provenance | |
| azure.cpp:267:10:267:12 | vec [element] | azure.cpp:267:10:267:12 | vec | provenance | | | azure.cpp:267:10:267:12 | vec [element] | azure.cpp:267:10:267:12 | vec | provenance | |
@@ -97,10 +94,10 @@ edges
| azure.cpp:278:10:278:13 | body | azure.cpp:278:10:278:13 | body | provenance | | | azure.cpp:278:10:278:13 | body | azure.cpp:278:10:278:13 | body | provenance | |
| azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:281:68:281:84 | *call to ExtractBodyStream | provenance | Src:MaD:26 | | azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:281:68:281:84 | *call to ExtractBodyStream | provenance | Src:MaD:26 |
| azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:282:21:282:23 | *call to get | provenance | | | azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:282:21:282:23 | *call to get | provenance | |
| azure.cpp:282:21:282:23 | *call to get | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | MaD:63 | | azure.cpp:282:21:282:23 | *call to get | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | MaD:60 |
| azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:10:282:38 | call to ReadToEnd | provenance | | | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:10:282:38 | call to ReadToEnd | provenance | |
| azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | | | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | |
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:64 | | azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:61 |
| azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:24:289:56 | call to GetHeader | provenance | | | azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:24:289:56 | call to GetHeader | provenance | |
| azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:32:289:40 | call to GetHeader | provenance | Src:MaD:30 | | azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:32:289:40 | call to GetHeader | provenance | Src:MaD:30 |
| azure.cpp:289:63:289:65 | call to Value | azure.cpp:289:63:289:65 | call to Value | provenance | | | azure.cpp:289:63:289:65 | call to Value | azure.cpp:289:63:289:65 | call to Value | provenance | |
@@ -162,27 +159,27 @@ edges
| test.cpp:133:10:133:18 | call to ymlSource | test.cpp:134:45:134:45 | x | provenance | | | test.cpp:133:10:133:18 | call to ymlSource | test.cpp:134:45:134:45 | x | provenance | |
| test.cpp:134:13:134:43 | call to templateFunction | test.cpp:134:13:134:43 | call to templateFunction | provenance | | | test.cpp:134:13:134:43 | call to templateFunction | test.cpp:134:13:134:43 | call to templateFunction | provenance | |
| test.cpp:134:13:134:43 | call to templateFunction | test.cpp:135:10:135:10 | y | provenance | Sink:MaD:1 | | test.cpp:134:13:134:43 | call to templateFunction | test.cpp:135:10:135:10 | y | provenance | Sink:MaD:1 |
| test.cpp:134:45:134:45 | x | test.cpp:134:13:134:43 | call to templateFunction | provenance | MaD:59 | | test.cpp:134:45:134:45 | x | test.cpp:134:13:134:43 | call to templateFunction | provenance | MaD:56 |
| test.cpp:146:10:146:18 | call to ymlSource | test.cpp:146:10:146:18 | call to ymlSource | provenance | Src:MaD:25 | | test.cpp:146:10:146:18 | call to ymlSource | test.cpp:146:10:146:18 | call to ymlSource | provenance | Src:MaD:25 |
| test.cpp:146:10:146:18 | call to ymlSource | test.cpp:148:26:148:26 | x | provenance | | | test.cpp:146:10:146:18 | call to ymlSource | test.cpp:148:26:148:26 | x | provenance | |
| test.cpp:148:10:148:27 | call to function | test.cpp:148:10:148:27 | call to function | provenance | | | test.cpp:148:10:148:27 | call to function | test.cpp:148:10:148:27 | call to function | provenance | |
| test.cpp:148:10:148:27 | call to function | test.cpp:149:10:149:10 | z | provenance | Sink:MaD:1 | | test.cpp:148:10:148:27 | call to function | test.cpp:149:10:149:10 | z | provenance | Sink:MaD:1 |
| test.cpp:148:26:148:26 | x | test.cpp:148:10:148:27 | call to function | provenance | MaD:60 | | test.cpp:148:26:148:26 | x | test.cpp:148:10:148:27 | call to function | provenance | MaD:57 |
| test.cpp:155:10:155:18 | call to ymlSource | test.cpp:155:10:155:18 | call to ymlSource | provenance | Src:MaD:25 | | test.cpp:155:10:155:18 | call to ymlSource | test.cpp:155:10:155:18 | call to ymlSource | provenance | Src:MaD:25 |
| test.cpp:155:10:155:18 | call to ymlSource | test.cpp:157:26:157:26 | x | provenance | | | test.cpp:155:10:155:18 | call to ymlSource | test.cpp:157:26:157:26 | x | provenance | |
| test.cpp:157:13:157:20 | call to function | test.cpp:157:13:157:20 | call to function | provenance | | | test.cpp:157:13:157:20 | call to function | test.cpp:157:13:157:20 | call to function | provenance | |
| test.cpp:157:13:157:20 | call to function | test.cpp:158:10:158:10 | z | provenance | Sink:MaD:1 | | test.cpp:157:13:157:20 | call to function | test.cpp:158:10:158:10 | z | provenance | Sink:MaD:1 |
| test.cpp:157:26:157:26 | x | test.cpp:157:13:157:20 | call to function | provenance | MaD:60 | | test.cpp:157:26:157:26 | x | test.cpp:157:13:157:20 | call to function | provenance | MaD:57 |
| test.cpp:164:34:164:34 | x | test.cpp:165:69:165:69 | x | provenance | | | test.cpp:164:34:164:34 | x | test.cpp:165:69:165:69 | x | provenance | |
| test.cpp:165:12:165:64 | call to templateFunction2 | test.cpp:164:7:164:7 | *templateFunction3 | provenance | | | test.cpp:165:12:165:64 | call to templateFunction2 | test.cpp:164:7:164:7 | *templateFunction3 | provenance | |
| test.cpp:165:12:165:64 | call to templateFunction2 | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | | | test.cpp:165:12:165:64 | call to templateFunction2 | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | |
| test.cpp:165:69:165:69 | x | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | MaD:58 | | test.cpp:165:69:165:69 | x | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | MaD:55 |
| test.cpp:170:10:170:18 | call to ymlSource | test.cpp:170:10:170:18 | call to ymlSource | provenance | Src:MaD:25 | | test.cpp:170:10:170:18 | call to ymlSource | test.cpp:170:10:170:18 | call to ymlSource | provenance | Src:MaD:25 |
| test.cpp:170:10:170:18 | call to ymlSource | test.cpp:172:51:172:51 | x | provenance | | | test.cpp:170:10:170:18 | call to ymlSource | test.cpp:172:51:172:51 | x | provenance | |
| test.cpp:172:13:172:44 | call to templateFunction3 | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | | | test.cpp:172:13:172:44 | call to templateFunction3 | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | |
| test.cpp:172:13:172:44 | call to templateFunction3 | test.cpp:173:10:173:10 | y | provenance | Sink:MaD:1 | | test.cpp:172:13:172:44 | call to templateFunction3 | test.cpp:173:10:173:10 | y | provenance | Sink:MaD:1 |
| test.cpp:172:51:172:51 | x | test.cpp:164:34:164:34 | x | provenance | | | test.cpp:172:51:172:51 | x | test.cpp:164:34:164:34 | x | provenance | |
| test.cpp:172:51:172:51 | x | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | MaD:58 | | test.cpp:172:51:172:51 | x | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | MaD:55 |
| test.cpp:186:2:186:2 | *s [post update] [myField] | test.cpp:187:33:187:34 | *& ... [myField] | provenance | | | test.cpp:186:2:186:2 | *s [post update] [myField] | test.cpp:187:33:187:34 | *& ... [myField] | provenance | |
| test.cpp:186:2:186:24 | ... = ... | test.cpp:186:2:186:2 | *s [post update] [myField] | provenance | | | test.cpp:186:2:186:24 | ... = ... | test.cpp:186:2:186:2 | *s [post update] [myField] | provenance | |
| test.cpp:186:14:186:22 | call to ymlSource | test.cpp:186:2:186:24 | ... = ... | provenance | Src:MaD:25 | | test.cpp:186:14:186:22 | call to ymlSource | test.cpp:186:2:186:24 | ... = ... | provenance | Src:MaD:25 |
@@ -195,18 +192,6 @@ edges
| test.cpp:200:10:200:33 | call to read_field_from_struct_2 | test.cpp:200:10:200:33 | call to read_field_from_struct_2 | provenance | | | test.cpp:200:10:200:33 | call to read_field_from_struct_2 | test.cpp:200:10:200:33 | call to read_field_from_struct_2 | provenance | |
| test.cpp:200:10:200:33 | call to read_field_from_struct_2 | test.cpp:201:10:201:10 | x | provenance | Sink:MaD:1 | | test.cpp:200:10:200:33 | call to read_field_from_struct_2 | test.cpp:201:10:201:10 | x | provenance | Sink:MaD:1 |
| test.cpp:200:35:200:36 | *& ... [myField] | test.cpp:200:10:200:33 | call to read_field_from_struct_2 | provenance | MaD:51 | | test.cpp:200:35:200:36 | *& ... [myField] | test.cpp:200:10:200:33 | call to read_field_from_struct_2 | provenance | MaD:51 |
| test.cpp:216:3:216:4 | get_ptr output argument [value] | test.cpp:217:11:217:12 | *rf [value] | provenance | |
| test.cpp:216:3:216:28 | ... = ... | test.cpp:216:3:216:4 | get_ptr output argument [value] | provenance | MaD:57 |
| test.cpp:216:18:216:26 | call to ymlSource | test.cpp:216:3:216:28 | ... = ... | provenance | Src:MaD:25 |
| test.cpp:217:11:217:12 | *rf [value] | test.cpp:217:14:217:18 | value | provenance | |
| test.cpp:217:14:217:18 | value | test.cpp:217:14:217:18 | value | provenance | |
| test.cpp:217:14:217:18 | value | test.cpp:218:11:218:11 | x | provenance | Sink:MaD:1 |
| test.cpp:222:3:222:3 | operator[] output argument | test.cpp:223:12:223:12 | *s | provenance | |
| test.cpp:222:3:222:20 | ... = ... | test.cpp:222:3:222:3 | operator[] output argument | provenance | MaD:56 |
| test.cpp:222:10:222:20 | call to ymlSource | test.cpp:222:3:222:20 | ... = ... | provenance | Src:MaD:25 |
| test.cpp:223:12:223:12 | *s | test.cpp:223:13:223:15 | call to operator[] | provenance | MaD:55 |
| test.cpp:223:13:223:15 | call to operator[] | test.cpp:223:13:223:15 | call to operator[] | provenance | |
| test.cpp:223:13:223:15 | call to operator[] | test.cpp:224:11:224:11 | c | provenance | Sink:MaD:1 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:27:36:27:38 | *cmd | provenance | | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:27:36:27:38 | *cmd | provenance | |
@@ -485,20 +470,6 @@ nodes
| test.cpp:200:10:200:33 | call to read_field_from_struct_2 | semmle.label | call to read_field_from_struct_2 | | test.cpp:200:10:200:33 | call to read_field_from_struct_2 | semmle.label | call to read_field_from_struct_2 |
| test.cpp:200:35:200:36 | *& ... [myField] | semmle.label | *& ... [myField] | | test.cpp:200:35:200:36 | *& ... [myField] | semmle.label | *& ... [myField] |
| test.cpp:201:10:201:10 | x | semmle.label | x | | test.cpp:201:10:201:10 | x | semmle.label | x |
| test.cpp:216:3:216:4 | get_ptr output argument [value] | semmle.label | get_ptr output argument [value] |
| test.cpp:216:3:216:28 | ... = ... | semmle.label | ... = ... |
| test.cpp:216:18:216:26 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:217:11:217:12 | *rf [value] | semmle.label | *rf [value] |
| test.cpp:217:14:217:18 | value | semmle.label | value |
| test.cpp:217:14:217:18 | value | semmle.label | value |
| test.cpp:218:11:218:11 | x | semmle.label | x |
| test.cpp:222:3:222:3 | operator[] output argument | semmle.label | operator[] output argument |
| test.cpp:222:3:222:20 | ... = ... | semmle.label | ... = ... |
| test.cpp:222:10:222:20 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:223:12:223:12 | *s | semmle.label | *s |
| test.cpp:223:13:223:15 | call to operator[] | semmle.label | call to operator[] |
| test.cpp:223:13:223:15 | call to operator[] | semmle.label | call to operator[] |
| test.cpp:224:11:224:11 | c | semmle.label | c |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
| windows.cpp:24:8:24:11 | * ... | semmle.label | * ... | | windows.cpp:24:8:24:11 | * ... | semmle.label | * ... |

View File

@@ -24,6 +24,3 @@ extensions:
- ["", "TemplateClass2<T,U>", True, "function", "(U,T)", "", "Argument[1]", "ReturnValue", "value", "manual"] - ["", "TemplateClass2<T,U>", True, "function", "(U,T)", "", "Argument[1]", "ReturnValue", "value", "manual"]
- ["", "", False, "read_field_from_struct", "", "", "Argument[*0].Field[MyNamespace::MyStructInNamespace::myField]", "ReturnValue", "value", "manual"] - ["", "", False, "read_field_from_struct", "", "", "Argument[*0].Field[MyNamespace::MyStructInNamespace::myField]", "ReturnValue", "value", "manual"]
- ["", "", False, "read_field_from_struct_2", "", "", "Argument[*0].Field[MyGlobalStruct::myField]", "ReturnValue", "value", "manual"] - ["", "", False, "read_field_from_struct_2", "", "", "Argument[*0].Field[MyGlobalStruct::myField]", "ReturnValue", "value", "manual"]
- ["", "ReverseFlow", True, "get_ptr", "", "", "ReturnValue[*]", "Argument[-1].Field[ReverseFlow::value]", "value", "manual"]
- ["", "MyString", True, "operator[]", "", "", "ReturnValue[*]", "Argument[-1]", "taint", "manual"]
- ["", "MyString", True, "operator[]", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]

View File

@@ -21,5 +21,3 @@
| test.cpp:173:10:173:10 | y | test-sink | | test.cpp:173:10:173:10 | y | test-sink |
| test.cpp:188:10:188:10 | x | test-sink | | test.cpp:188:10:188:10 | x | test-sink |
| test.cpp:201:10:201:10 | x | test-sink | | test.cpp:201:10:201:10 | x | test-sink |
| test.cpp:218:11:218:11 | x | test-sink |
| test.cpp:224:11:224:11 | c | test-sink |

View File

@@ -15,8 +15,6 @@
| test.cpp:170:10:170:18 | call to ymlSource | local | | test.cpp:170:10:170:18 | call to ymlSource | local |
| test.cpp:186:14:186:22 | call to ymlSource | local | | test.cpp:186:14:186:22 | call to ymlSource | local |
| test.cpp:199:14:199:22 | call to ymlSource | local | | test.cpp:199:14:199:22 | call to ymlSource | local |
| test.cpp:216:18:216:26 | call to ymlSource | local |
| test.cpp:222:10:222:20 | call to ymlSource | local |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | local | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | local |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local | | windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local |
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local | | windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local |

View File

@@ -200,27 +200,3 @@ void test_fully_qualified_field_test_2() {
int x = read_field_from_struct_2(&s); int x = read_field_from_struct_2(&s);
ymlSink(x); // $ ir ymlSink(x); // $ ir
} }
struct ReverseFlow {
int value;
int& get_ptr();
};
struct MyString {
char& operator[](unsigned);
};
void test_reverse_flow(unsigned i, unsigned j) {
{
ReverseFlow rf;
rf.get_ptr() = ymlSource();
int x = rf.value;
ymlSink(x); // $ ir
}
{
MyString s;
s[i] = ymlSource();
char c = s[j];
ymlSink(c); // $ ir
}
}

View File

@@ -33,34 +33,34 @@ summaryCalls
| file://:0:0:0:0 | [summary] call to [summary param] 0 in madCallArg0ReturnToReturnFirst in madCallArg0ReturnToReturnFirst | | file://:0:0:0:0 | [summary] call to [summary param] 0 in madCallArg0ReturnToReturnFirst in madCallArg0ReturnToReturnFirst |
| file://:0:0:0:0 | [summary] call to [summary param] 0 in madCallArg0WithValue in madCallArg0WithValue | | file://:0:0:0:0 | [summary] call to [summary param] 0 in madCallArg0WithValue in madCallArg0WithValue |
summarizedCallables summarizedCallables
| tests.cpp:127:5:127:19 | madArg0ToReturn | | tests.cpp:144:5:144:19 | madArg0ToReturn |
| tests.cpp:128:6:128:28 | madArg0ToReturnIndirect | | tests.cpp:145:6:145:28 | madArg0ToReturnIndirect |
| tests.cpp:130:5:130:28 | madArg0ToReturnValueFlow | | tests.cpp:147:5:147:28 | madArg0ToReturnValueFlow |
| tests.cpp:131:5:131:27 | madArg0IndirectToReturn | | tests.cpp:148:5:148:27 | madArg0IndirectToReturn |
| tests.cpp:132:5:132:33 | madArg0DoubleIndirectToReturn | | tests.cpp:149:5:149:33 | madArg0DoubleIndirectToReturn |
| tests.cpp:133:5:133:30 | madArg0NotIndirectToReturn | | tests.cpp:150:5:150:30 | madArg0NotIndirectToReturn |
| tests.cpp:134:6:134:26 | madArg0ToArg1Indirect | | tests.cpp:151:6:151:26 | madArg0ToArg1Indirect |
| tests.cpp:135:6:135:34 | madArg0IndirectToArg1Indirect | | tests.cpp:152:6:152:34 | madArg0IndirectToArg1Indirect |
| tests.cpp:136:5:136:18 | madArgsComplex | | tests.cpp:153:5:153:18 | madArgsComplex |
| tests.cpp:137:5:137:14 | madArgsAny | | tests.cpp:154:5:154:14 | madArgsAny |
| tests.cpp:138:5:138:28 | madAndImplementedComplex | | tests.cpp:155:5:155:28 | madAndImplementedComplex |
| tests.cpp:143:5:143:24 | madArg0FieldToReturn | | tests.cpp:160:5:160:24 | madArg0FieldToReturn |
| tests.cpp:144:5:144:32 | madArg0IndirectFieldToReturn | | tests.cpp:161:5:161:32 | madArg0IndirectFieldToReturn |
| tests.cpp:145:5:145:32 | madArg0FieldIndirectToReturn | | tests.cpp:162:5:162:32 | madArg0FieldIndirectToReturn |
| tests.cpp:146:13:146:32 | madArg0ToReturnField | | tests.cpp:163:13:163:32 | madArg0ToReturnField |
| tests.cpp:147:14:147:41 | madArg0ToReturnIndirectField | | tests.cpp:164:14:164:41 | madArg0ToReturnIndirectField |
| tests.cpp:148:13:148:40 | madArg0ToReturnFieldIndirect | | tests.cpp:165:13:165:40 | madArg0ToReturnFieldIndirect |
| tests.cpp:250:7:250:19 | madArg0ToSelf | | tests.cpp:284:7:284:19 | madArg0ToSelf |
| tests.cpp:251:6:251:20 | madSelfToReturn | | tests.cpp:285:6:285:20 | madSelfToReturn |
| tests.cpp:253:7:253:20 | madArg0ToField | | tests.cpp:287:7:287:20 | madArg0ToField |
| tests.cpp:254:6:254:21 | madFieldToReturn | | tests.cpp:288:6:288:21 | madFieldToReturn |
| tests.cpp:277:7:277:30 | namespaceMadSelfToReturn | | tests.cpp:313:7:313:30 | namespaceMadSelfToReturn |
| tests.cpp:392:5:392:29 | madCallArg0ReturnToReturn | | tests.cpp:434:5:434:29 | madCallArg0ReturnToReturn |
| tests.cpp:393:9:393:38 | madCallArg0ReturnToReturnFirst | | tests.cpp:435:9:435:38 | madCallArg0ReturnToReturnFirst |
| tests.cpp:394:6:394:25 | madCallArg0WithValue | | tests.cpp:436:6:436:25 | madCallArg0WithValue |
| tests.cpp:395:5:395:36 | madCallReturnValueIgnoreFunction | | tests.cpp:437:5:437:36 | madCallReturnValueIgnoreFunction |
| tests.cpp:417:5:417:31 | parameter_ref_to_return_ref | | tests.cpp:459:5:459:31 | parameter_ref_to_return_ref |
| tests.cpp:429:5:429:17 | receive_array | | tests.cpp:471:5:471:17 | receive_array |
sourceCallables sourceCallables
| tests.cpp:3:5:3:10 | source | | tests.cpp:3:5:3:10 | source |
| tests.cpp:4:6:4:14 | sourcePtr | | tests.cpp:4:6:4:14 | sourcePtr |
@@ -82,284 +82,297 @@ sourceCallables
| tests.cpp:19:6:19:32 | remoteMadSourceIndirectArg1 | | tests.cpp:19:6:19:32 | remoteMadSourceIndirectArg1 |
| tests.cpp:19:39:19:39 | x | | tests.cpp:19:39:19:39 | x |
| tests.cpp:19:47:19:47 | y | | tests.cpp:19:47:19:47 | y |
| tests.cpp:23:7:23:30 | namespace2LocalMadSource | | tests.cpp:20:5:20:22 | remoteMadSourceVar |
| tests.cpp:26:6:26:19 | localMadSource | | tests.cpp:21:6:21:31 | remoteMadSourceVarIndirect |
| tests.cpp:28:5:28:27 | namespaceLocalMadSource | | tests.cpp:24:6:24:28 | namespaceLocalMadSource |
| tests.cpp:30:6:30:17 | test_sources | | tests.cpp:25:6:25:31 | namespaceLocalMadSourceVar |
| tests.cpp:45:6:45:6 | v | | tests.cpp:28:7:28:30 | namespace2LocalMadSource |
| tests.cpp:46:7:46:16 | v_indirect | | tests.cpp:31:6:31:19 | localMadSource |
| tests.cpp:47:6:47:13 | v_direct | | tests.cpp:33:5:33:27 | namespaceLocalMadSource |
| tests.cpp:58:6:58:6 | a | | tests.cpp:35:6:35:17 | test_sources |
| tests.cpp:58:9:58:9 | b | | tests.cpp:50:6:50:6 | v |
| tests.cpp:58:12:58:12 | c | | tests.cpp:51:7:51:16 | v_indirect |
| tests.cpp:58:15:58:15 | d | | tests.cpp:52:6:52:13 | v_direct |
| tests.cpp:67:6:67:6 | e | | tests.cpp:63:6:63:6 | a |
| tests.cpp:75:6:75:26 | remoteMadSourceParam0 | | tests.cpp:63:9:63:9 | b |
| tests.cpp:75:32:75:32 | x | | tests.cpp:63:12:63:12 | c |
| tests.cpp:82:6:82:16 | madSinkArg0 | | tests.cpp:63:15:63:15 | d |
| tests.cpp:82:22:82:22 | x | | tests.cpp:75:6:75:6 | e |
| tests.cpp:83:6:83:13 | notASink | | tests.cpp:85:6:85:26 | remoteMadSourceParam0 |
| tests.cpp:83:19:83:19 | x | | tests.cpp:85:32:85:32 | x |
| tests.cpp:84:6:84:16 | madSinkArg1 | | tests.cpp:92:6:92:16 | madSinkArg0 |
| tests.cpp:84:22:84:22 | x | | tests.cpp:92:22:92:22 | x |
| tests.cpp:84:29:84:29 | y | | tests.cpp:93:6:93:13 | notASink |
| tests.cpp:85:6:85:17 | madSinkArg01 | | tests.cpp:93:19:93:19 | x |
| tests.cpp:85:23:85:23 | x | | tests.cpp:94:6:94:16 | madSinkArg1 |
| tests.cpp:85:30:85:30 | y | | tests.cpp:94:22:94:22 | x |
| tests.cpp:85:37:85:37 | z | | tests.cpp:94:29:94:29 | y |
| tests.cpp:86:6:86:17 | madSinkArg02 | | tests.cpp:95:6:95:17 | madSinkArg01 |
| tests.cpp:86:23:86:23 | x | | tests.cpp:95:23:95:23 | x |
| tests.cpp:86:30:86:30 | y | | tests.cpp:95:30:95:30 | y |
| tests.cpp:86:37:86:37 | z | | tests.cpp:95:37:95:37 | z |
| tests.cpp:87:6:87:24 | madSinkIndirectArg0 | | tests.cpp:96:6:96:17 | madSinkArg02 |
| tests.cpp:87:31:87:31 | x | | tests.cpp:96:23:96:23 | x |
| tests.cpp:88:6:88:30 | madSinkDoubleIndirectArg0 | | tests.cpp:96:30:96:30 | y |
| tests.cpp:88:38:88:38 | x | | tests.cpp:96:37:96:37 | z |
| tests.cpp:92:6:92:15 | test_sinks | | tests.cpp:97:6:97:24 | madSinkIndirectArg0 |
| tests.cpp:106:6:106:6 | a | | tests.cpp:97:31:97:31 | x |
| tests.cpp:107:7:107:11 | a_ptr | | tests.cpp:98:6:98:30 | madSinkDoubleIndirectArg0 |
| tests.cpp:115:6:115:18 | madSinkParam0 | | tests.cpp:98:38:98:38 | x |
| tests.cpp:115:24:115:24 | x | | tests.cpp:99:5:99:14 | madSinkVar |
| tests.cpp:121:8:121:8 | operator= | | tests.cpp:100:6:100:23 | madSinkVarIndirect |
| tests.cpp:121:8:121:8 | operator= | | tests.cpp:102:6:102:15 | test_sinks |
| tests.cpp:121:8:121:18 | MyContainer | | tests.cpp:116:6:116:6 | a |
| tests.cpp:122:6:122:10 | value | | tests.cpp:117:7:117:11 | a_ptr |
| tests.cpp:123:6:123:11 | value2 | | tests.cpp:132:6:132:18 | madSinkParam0 |
| tests.cpp:124:7:124:9 | ptr | | tests.cpp:132:24:132:24 | x |
| tests.cpp:127:5:127:19 | madArg0ToReturn | | tests.cpp:138:8:138:8 | operator= |
| tests.cpp:127:25:127:25 | x | | tests.cpp:138:8:138:8 | operator= |
| tests.cpp:128:6:128:28 | madArg0ToReturnIndirect | | tests.cpp:138:8:138:18 | MyContainer |
| tests.cpp:128:34:128:34 | x | | tests.cpp:139:6:139:10 | value |
| tests.cpp:129:5:129:15 | notASummary | | tests.cpp:140:6:140:11 | value2 |
| tests.cpp:129:21:129:21 | x | | tests.cpp:141:7:141:9 | ptr |
| tests.cpp:130:5:130:28 | madArg0ToReturnValueFlow | | tests.cpp:144:5:144:19 | madArg0ToReturn |
| tests.cpp:130:34:130:34 | x | | tests.cpp:144:25:144:25 | x |
| tests.cpp:131:5:131:27 | madArg0IndirectToReturn | | tests.cpp:145:6:145:28 | madArg0ToReturnIndirect |
| tests.cpp:131:34:131:34 | x | | tests.cpp:145:34:145:34 | x |
| tests.cpp:132:5:132:33 | madArg0DoubleIndirectToReturn | | tests.cpp:146:5:146:15 | notASummary |
| tests.cpp:132:41:132:41 | x | | tests.cpp:146:21:146:21 | x |
| tests.cpp:133:5:133:30 | madArg0NotIndirectToReturn | | tests.cpp:147:5:147:28 | madArg0ToReturnValueFlow |
| tests.cpp:133:37:133:37 | x | | tests.cpp:147:34:147:34 | x |
| tests.cpp:134:6:134:26 | madArg0ToArg1Indirect | | tests.cpp:148:5:148:27 | madArg0IndirectToReturn |
| tests.cpp:134:32:134:32 | x | | tests.cpp:148:34:148:34 | x |
| tests.cpp:134:40:134:40 | y | | tests.cpp:149:5:149:33 | madArg0DoubleIndirectToReturn |
| tests.cpp:135:6:135:34 | madArg0IndirectToArg1Indirect | | tests.cpp:149:41:149:41 | x |
| tests.cpp:135:47:135:47 | x | | tests.cpp:150:5:150:30 | madArg0NotIndirectToReturn |
| tests.cpp:135:55:135:55 | y | | tests.cpp:150:37:150:37 | x |
| tests.cpp:136:5:136:18 | madArgsComplex | | tests.cpp:151:6:151:26 | madArg0ToArg1Indirect |
| tests.cpp:136:25:136:25 | a | | tests.cpp:151:32:151:32 | x |
| tests.cpp:136:33:136:33 | b | | tests.cpp:151:40:151:40 | y |
| tests.cpp:136:40:136:40 | c | | tests.cpp:152:6:152:34 | madArg0IndirectToArg1Indirect |
| tests.cpp:136:47:136:47 | d | | tests.cpp:152:47:152:47 | x |
| tests.cpp:137:5:137:14 | madArgsAny | | tests.cpp:152:55:152:55 | y |
| tests.cpp:137:20:137:20 | a | | tests.cpp:153:5:153:18 | madArgsComplex |
| tests.cpp:137:28:137:28 | b | | tests.cpp:153:25:153:25 | a |
| tests.cpp:138:5:138:28 | madAndImplementedComplex | | tests.cpp:153:33:153:33 | b |
| tests.cpp:138:34:138:34 | a | | tests.cpp:153:40:153:40 | c |
| tests.cpp:138:41:138:41 | b | | tests.cpp:153:47:153:47 | d |
| tests.cpp:138:48:138:48 | c | | tests.cpp:154:5:154:14 | madArgsAny |
| tests.cpp:143:5:143:24 | madArg0FieldToReturn | | tests.cpp:154:20:154:20 | a |
| tests.cpp:143:38:143:39 | mc | | tests.cpp:154:28:154:28 | b |
| tests.cpp:144:5:144:32 | madArg0IndirectFieldToReturn | | tests.cpp:155:5:155:28 | madAndImplementedComplex |
| tests.cpp:144:47:144:48 | mc | | tests.cpp:155:34:155:34 | a |
| tests.cpp:145:5:145:32 | madArg0FieldIndirectToReturn | | tests.cpp:155:41:155:41 | b |
| tests.cpp:145:46:145:47 | mc | | tests.cpp:155:48:155:48 | c |
| tests.cpp:146:13:146:32 | madArg0ToReturnField | | tests.cpp:160:5:160:24 | madArg0FieldToReturn |
| tests.cpp:146:38:146:38 | x | | tests.cpp:160:38:160:39 | mc |
| tests.cpp:147:14:147:41 | madArg0ToReturnIndirectField | | tests.cpp:161:5:161:32 | madArg0IndirectFieldToReturn |
| tests.cpp:147:47:147:47 | x | | tests.cpp:161:47:161:48 | mc |
| tests.cpp:148:13:148:40 | madArg0ToReturnFieldIndirect | | tests.cpp:162:5:162:32 | madArg0FieldIndirectToReturn |
| tests.cpp:148:46:148:46 | x | | tests.cpp:162:46:162:47 | mc |
| tests.cpp:150:6:150:19 | test_summaries | | tests.cpp:163:13:163:32 | madArg0ToReturnField |
| tests.cpp:153:6:153:6 | a | | tests.cpp:163:38:163:38 | x |
| tests.cpp:153:9:153:9 | b | | tests.cpp:164:14:164:41 | madArg0ToReturnIndirectField |
| tests.cpp:153:12:153:12 | c | | tests.cpp:164:47:164:47 | x |
| tests.cpp:153:15:153:15 | d | | tests.cpp:165:13:165:40 | madArg0ToReturnFieldIndirect |
| tests.cpp:153:18:153:18 | e | | tests.cpp:165:46:165:46 | x |
| tests.cpp:154:7:154:11 | a_ptr | | tests.cpp:167:13:167:30 | madFieldToFieldVar |
| tests.cpp:197:14:197:16 | mc1 | | tests.cpp:168:13:168:38 | madFieldToIndirectFieldVar |
| tests.cpp:197:19:197:21 | mc2 | | tests.cpp:169:14:169:39 | madIndirectFieldToFieldVar |
| tests.cpp:216:15:216:18 | rtn1 | | tests.cpp:171:6:171:19 | test_summaries |
| tests.cpp:219:14:219:17 | rtn2 | | tests.cpp:174:6:174:6 | a |
| tests.cpp:220:7:220:14 | rtn2_ptr | | tests.cpp:174:9:174:9 | b |
| tests.cpp:233:7:233:7 | operator= | | tests.cpp:174:12:174:12 | c |
| tests.cpp:233:7:233:7 | operator= | | tests.cpp:174:15:174:15 | d |
| tests.cpp:233:7:233:13 | MyClass | | tests.cpp:174:18:174:18 | e |
| tests.cpp:236:6:236:26 | memberRemoteMadSource | | tests.cpp:175:7:175:11 | a_ptr |
| tests.cpp:237:7:237:39 | memberRemoteMadSourceIndirectArg0 | | tests.cpp:218:14:218:16 | mc1 |
| tests.cpp:237:46:237:46 | x | | tests.cpp:218:19:218:21 | mc2 |
| tests.cpp:239:7:239:21 | qualifierSource | | tests.cpp:237:15:237:18 | rtn1 |
| tests.cpp:240:7:240:26 | qualifierFieldSource | | tests.cpp:240:14:240:17 | rtn2 |
| tests.cpp:243:7:243:23 | memberMadSinkArg0 | | tests.cpp:241:7:241:14 | rtn2_ptr |
| tests.cpp:243:29:243:29 | x | | tests.cpp:267:7:267:7 | operator= |
| tests.cpp:245:7:245:19 | qualifierSink | | tests.cpp:267:7:267:7 | operator= |
| tests.cpp:246:7:246:23 | qualifierArg0Sink | | tests.cpp:267:7:267:13 | MyClass |
| tests.cpp:246:29:246:29 | x | | tests.cpp:270:6:270:26 | memberRemoteMadSource |
| tests.cpp:247:7:247:24 | qualifierFieldSink | | tests.cpp:271:7:271:39 | memberRemoteMadSourceIndirectArg0 |
| tests.cpp:250:7:250:19 | madArg0ToSelf | | tests.cpp:271:46:271:46 | x |
| tests.cpp:250:25:250:25 | x | | tests.cpp:272:6:272:29 | memberRemoteMadSourceVar |
| tests.cpp:251:6:251:20 | madSelfToReturn | | tests.cpp:273:7:273:21 | qualifierSource |
| tests.cpp:252:6:252:16 | notASummary | | tests.cpp:274:7:274:26 | qualifierFieldSource |
| tests.cpp:253:7:253:20 | madArg0ToField | | tests.cpp:277:7:277:23 | memberMadSinkArg0 |
| tests.cpp:253:26:253:26 | x | | tests.cpp:277:29:277:29 | x |
| tests.cpp:254:6:254:21 | madFieldToReturn | | tests.cpp:278:6:278:21 | memberMadSinkVar |
| tests.cpp:256:6:256:8 | val | | tests.cpp:279:7:279:19 | qualifierSink |
| tests.cpp:259:7:259:7 | MyDerivedClass | | tests.cpp:280:7:280:23 | qualifierArg0Sink |
| tests.cpp:259:7:259:7 | operator= | | tests.cpp:280:29:280:29 | x |
| tests.cpp:259:7:259:7 | operator= | | tests.cpp:281:7:281:24 | qualifierFieldSink |
| tests.cpp:259:7:259:20 | MyDerivedClass | | tests.cpp:284:7:284:19 | madArg0ToSelf |
| tests.cpp:261:6:261:28 | subtypeRemoteMadSource1 | | tests.cpp:284:25:284:25 | x |
| tests.cpp:262:6:262:21 | subtypeNonSource | | tests.cpp:285:6:285:20 | madSelfToReturn |
| tests.cpp:263:6:263:28 | subtypeRemoteMadSource2 | | tests.cpp:286:6:286:16 | notASummary |
| tests.cpp:266:9:266:15 | source2 | | tests.cpp:287:7:287:20 | madArg0ToField |
| tests.cpp:267:6:267:9 | sink | | tests.cpp:287:26:287:26 | x |
| tests.cpp:267:19:267:20 | mc | | tests.cpp:288:6:288:21 | madFieldToReturn |
| tests.cpp:270:8:270:8 | operator= | | tests.cpp:290:6:290:8 | val |
| tests.cpp:270:8:270:8 | operator= | | tests.cpp:293:7:293:7 | MyDerivedClass |
| tests.cpp:270:8:270:14 | MyClass | | tests.cpp:293:7:293:7 | operator= |
| tests.cpp:273:8:273:33 | namespaceMemberMadSinkArg0 | | tests.cpp:293:7:293:7 | operator= |
| tests.cpp:273:39:273:39 | x | | tests.cpp:293:7:293:20 | MyDerivedClass |
| tests.cpp:274:15:274:46 | namespaceStaticMemberMadSinkArg0 | | tests.cpp:295:6:295:28 | subtypeRemoteMadSource1 |
| tests.cpp:274:52:274:52 | x | | tests.cpp:296:6:296:21 | subtypeNonSource |
| tests.cpp:277:7:277:30 | namespaceMadSelfToReturn | | tests.cpp:297:6:297:28 | subtypeRemoteMadSource2 |
| tests.cpp:281:22:281:28 | source3 | | tests.cpp:300:9:300:15 | source2 |
| tests.cpp:283:6:283:23 | test_class_members | | tests.cpp:301:6:301:9 | sink |
| tests.cpp:284:10:284:11 | mc | | tests.cpp:301:19:301:20 | mc |
| tests.cpp:284:14:284:16 | mc2 | | tests.cpp:304:8:304:8 | operator= |
| tests.cpp:284:19:284:21 | mc3 | | tests.cpp:304:8:304:8 | operator= |
| tests.cpp:284:24:284:26 | mc4 | | tests.cpp:304:8:304:14 | MyClass |
| tests.cpp:284:29:284:31 | mc5 | | tests.cpp:307:8:307:33 | namespaceMemberMadSinkArg0 |
| tests.cpp:284:34:284:36 | mc6 | | tests.cpp:307:39:307:39 | x |
| tests.cpp:284:39:284:41 | mc7 | | tests.cpp:308:15:308:46 | namespaceStaticMemberMadSinkArg0 |
| tests.cpp:284:44:284:46 | mc8 | | tests.cpp:308:52:308:52 | x |
| tests.cpp:284:49:284:51 | mc9 | | tests.cpp:309:7:309:31 | namespaceMemberMadSinkVar |
| tests.cpp:284:54:284:57 | mc10 | | tests.cpp:310:14:310:44 | namespaceStaticMemberMadSinkVar |
| tests.cpp:284:60:284:63 | mc11 | | tests.cpp:313:7:313:30 | namespaceMadSelfToReturn |
| tests.cpp:285:11:285:13 | ptr | | tests.cpp:317:22:317:28 | source3 |
| tests.cpp:285:17:285:23 | mc4_ptr | | tests.cpp:319:6:319:23 | test_class_members |
| tests.cpp:286:17:286:19 | mdc | | tests.cpp:320:10:320:11 | mc |
| tests.cpp:287:23:287:25 | mnc | | tests.cpp:320:14:320:16 | mc2 |
| tests.cpp:287:28:287:31 | mnc2 | | tests.cpp:320:19:320:21 | mc3 |
| tests.cpp:288:24:288:31 | mnc2_ptr | | tests.cpp:320:24:320:26 | mc4 |
| tests.cpp:294:6:294:6 | a | | tests.cpp:320:29:320:31 | mc5 |
| tests.cpp:387:8:387:8 | operator= | | tests.cpp:320:34:320:36 | mc6 |
| tests.cpp:387:8:387:8 | operator= | | tests.cpp:320:39:320:41 | mc7 |
| tests.cpp:387:8:387:14 | intPair | | tests.cpp:320:44:320:46 | mc8 |
| tests.cpp:388:6:388:10 | first | | tests.cpp:320:49:320:51 | mc9 |
| tests.cpp:389:6:389:11 | second | | tests.cpp:320:54:320:57 | mc10 |
| tests.cpp:392:5:392:29 | madCallArg0ReturnToReturn | | tests.cpp:320:60:320:63 | mc11 |
| tests.cpp:392:37:392:43 | fun_ptr | | tests.cpp:321:11:321:13 | ptr |
| tests.cpp:393:9:393:38 | madCallArg0ReturnToReturnFirst | | tests.cpp:321:17:321:23 | mc4_ptr |
| tests.cpp:393:46:393:52 | fun_ptr | | tests.cpp:322:17:322:19 | mdc |
| tests.cpp:394:6:394:25 | madCallArg0WithValue | | tests.cpp:323:23:323:25 | mnc |
| tests.cpp:394:34:394:40 | fun_ptr | | tests.cpp:323:28:323:31 | mnc2 |
| tests.cpp:394:53:394:57 | value | | tests.cpp:324:24:324:31 | mnc2_ptr |
| tests.cpp:395:5:395:36 | madCallReturnValueIgnoreFunction | | tests.cpp:330:6:330:6 | a |
| tests.cpp:395:45:395:51 | fun_ptr | | tests.cpp:429:8:429:8 | operator= |
| tests.cpp:395:64:395:68 | value | | tests.cpp:429:8:429:8 | operator= |
| tests.cpp:397:5:397:14 | getTainted | | tests.cpp:429:8:429:14 | intPair |
| tests.cpp:398:6:398:13 | useValue | | tests.cpp:430:6:430:10 | first |
| tests.cpp:398:19:398:19 | x | | tests.cpp:431:6:431:11 | second |
| tests.cpp:399:6:399:17 | dontUseValue | | tests.cpp:434:5:434:29 | madCallArg0ReturnToReturn |
| tests.cpp:399:23:399:23 | x | | tests.cpp:434:37:434:43 | fun_ptr |
| tests.cpp:401:6:401:27 | test_function_pointers | | tests.cpp:435:9:435:38 | madCallArg0ReturnToReturnFirst |
| tests.cpp:414:19:414:19 | X | | tests.cpp:435:46:435:52 | fun_ptr |
| tests.cpp:415:8:415:35 | StructWithTypedefInParameter<X> | | tests.cpp:436:6:436:25 | madCallArg0WithValue |
| tests.cpp:415:8:415:35 | StructWithTypedefInParameter<int> | | tests.cpp:436:34:436:40 | fun_ptr |
| tests.cpp:416:12:416:15 | Type | | tests.cpp:436:53:436:57 | value |
| tests.cpp:417:5:417:31 | parameter_ref_to_return_ref | | tests.cpp:437:5:437:36 | madCallReturnValueIgnoreFunction |
| tests.cpp:417:5:417:31 | parameter_ref_to_return_ref | | tests.cpp:437:45:437:51 | fun_ptr |
| tests.cpp:417:45:417:45 | x | | tests.cpp:437:64:437:68 | value |
| tests.cpp:417:45:417:45 | x | | tests.cpp:439:5:439:14 | getTainted |
| tests.cpp:420:6:420:37 | test_parameter_ref_to_return_ref | | tests.cpp:440:6:440:13 | useValue |
| tests.cpp:421:6:421:6 | x | | tests.cpp:440:19:440:19 | x |
| tests.cpp:422:36:422:36 | s | | tests.cpp:441:6:441:17 | dontUseValue |
| tests.cpp:423:6:423:6 | y | | tests.cpp:441:23:441:23 | x |
| tests.cpp:427:7:427:9 | INT | | tests.cpp:443:6:443:27 | test_function_pointers |
| tests.cpp:429:5:429:17 | receive_array | | tests.cpp:456:19:456:19 | X |
| tests.cpp:429:23:429:23 | a | | tests.cpp:457:8:457:35 | StructWithTypedefInParameter<X> |
| tests.cpp:431:6:431:23 | test_receive_array | | tests.cpp:457:8:457:35 | StructWithTypedefInParameter<int> |
| tests.cpp:432:6:432:6 | x | | tests.cpp:458:12:458:15 | Type |
| tests.cpp:433:6:433:10 | array | | tests.cpp:459:5:459:31 | parameter_ref_to_return_ref |
| tests.cpp:434:6:434:6 | y | | tests.cpp:459:5:459:31 | parameter_ref_to_return_ref |
| tests.cpp:459:45:459:45 | x |
| tests.cpp:459:45:459:45 | x |
| tests.cpp:462:6:462:37 | test_parameter_ref_to_return_ref |
| tests.cpp:463:6:463:6 | x |
| tests.cpp:464:36:464:36 | s |
| tests.cpp:465:6:465:6 | y |
| tests.cpp:469:7:469:9 | INT |
| tests.cpp:471:5:471:17 | receive_array |
| tests.cpp:471:23:471:23 | a |
| tests.cpp:473:6:473:23 | test_receive_array |
| tests.cpp:474:6:474:6 | x |
| tests.cpp:475:6:475:10 | array |
| tests.cpp:476:6:476:6 | y |
flowSummaryNode flowSummaryNode
| tests.cpp:127:5:127:19 | [summary param] 0 in madArg0ToReturn | ParameterNode | madArg0ToReturn | madArg0ToReturn | | tests.cpp:144:5:144:19 | [summary param] 0 in madArg0ToReturn | ParameterNode | madArg0ToReturn | madArg0ToReturn |
| tests.cpp:127:5:127:19 | [summary] to write: ReturnValue in madArg0ToReturn | ReturnNode | madArg0ToReturn | madArg0ToReturn | | tests.cpp:144:5:144:19 | [summary] to write: ReturnValue in madArg0ToReturn | ReturnNode | madArg0ToReturn | madArg0ToReturn |
| tests.cpp:128:6:128:28 | [summary param] 0 in madArg0ToReturnIndirect | ParameterNode | madArg0ToReturnIndirect | madArg0ToReturnIndirect | | tests.cpp:145:6:145:28 | [summary param] 0 in madArg0ToReturnIndirect | ParameterNode | madArg0ToReturnIndirect | madArg0ToReturnIndirect |
| tests.cpp:128:6:128:28 | [summary] to write: ReturnValue[*] in madArg0ToReturnIndirect | ReturnNode | madArg0ToReturnIndirect | madArg0ToReturnIndirect | | tests.cpp:145:6:145:28 | [summary] to write: ReturnValue[*] in madArg0ToReturnIndirect | ReturnNode | madArg0ToReturnIndirect | madArg0ToReturnIndirect |
| tests.cpp:130:5:130:28 | [summary param] 0 in madArg0ToReturnValueFlow | ParameterNode | madArg0ToReturnValueFlow | madArg0ToReturnValueFlow | | tests.cpp:147:5:147:28 | [summary param] 0 in madArg0ToReturnValueFlow | ParameterNode | madArg0ToReturnValueFlow | madArg0ToReturnValueFlow |
| tests.cpp:130:5:130:28 | [summary] to write: ReturnValue in madArg0ToReturnValueFlow | ReturnNode | madArg0ToReturnValueFlow | madArg0ToReturnValueFlow | | tests.cpp:147:5:147:28 | [summary] to write: ReturnValue in madArg0ToReturnValueFlow | ReturnNode | madArg0ToReturnValueFlow | madArg0ToReturnValueFlow |
| tests.cpp:131:5:131:27 | [summary param] *0 in madArg0IndirectToReturn | ParameterNode | madArg0IndirectToReturn | madArg0IndirectToReturn | | tests.cpp:148:5:148:27 | [summary param] *0 in madArg0IndirectToReturn | ParameterNode | madArg0IndirectToReturn | madArg0IndirectToReturn |
| tests.cpp:131:5:131:27 | [summary] to write: ReturnValue in madArg0IndirectToReturn | ReturnNode | madArg0IndirectToReturn | madArg0IndirectToReturn | | tests.cpp:148:5:148:27 | [summary] to write: ReturnValue in madArg0IndirectToReturn | ReturnNode | madArg0IndirectToReturn | madArg0IndirectToReturn |
| tests.cpp:132:5:132:33 | [summary param] **0 in madArg0DoubleIndirectToReturn | ParameterNode | madArg0DoubleIndirectToReturn | madArg0DoubleIndirectToReturn | | tests.cpp:149:5:149:33 | [summary param] **0 in madArg0DoubleIndirectToReturn | ParameterNode | madArg0DoubleIndirectToReturn | madArg0DoubleIndirectToReturn |
| tests.cpp:132:5:132:33 | [summary] to write: ReturnValue in madArg0DoubleIndirectToReturn | ReturnNode | madArg0DoubleIndirectToReturn | madArg0DoubleIndirectToReturn | | tests.cpp:149:5:149:33 | [summary] to write: ReturnValue in madArg0DoubleIndirectToReturn | ReturnNode | madArg0DoubleIndirectToReturn | madArg0DoubleIndirectToReturn |
| tests.cpp:133:5:133:30 | [summary param] 0 in madArg0NotIndirectToReturn | ParameterNode | madArg0NotIndirectToReturn | madArg0NotIndirectToReturn | | tests.cpp:150:5:150:30 | [summary param] 0 in madArg0NotIndirectToReturn | ParameterNode | madArg0NotIndirectToReturn | madArg0NotIndirectToReturn |
| tests.cpp:133:5:133:30 | [summary] to write: ReturnValue in madArg0NotIndirectToReturn | ReturnNode | madArg0NotIndirectToReturn | madArg0NotIndirectToReturn | | tests.cpp:150:5:150:30 | [summary] to write: ReturnValue in madArg0NotIndirectToReturn | ReturnNode | madArg0NotIndirectToReturn | madArg0NotIndirectToReturn |
| tests.cpp:134:6:134:26 | [summary param] 0 in madArg0ToArg1Indirect | ParameterNode | madArg0ToArg1Indirect | madArg0ToArg1Indirect | | tests.cpp:151:6:151:26 | [summary param] 0 in madArg0ToArg1Indirect | ParameterNode | madArg0ToArg1Indirect | madArg0ToArg1Indirect |
| tests.cpp:134:6:134:26 | [summary param] *1 in madArg0ToArg1Indirect | ParameterNode | madArg0ToArg1Indirect | madArg0ToArg1Indirect | | tests.cpp:151:6:151:26 | [summary param] *1 in madArg0ToArg1Indirect | ParameterNode | madArg0ToArg1Indirect | madArg0ToArg1Indirect |
| tests.cpp:134:6:134:26 | [summary] to write: Argument[*1] in madArg0ToArg1Indirect | PostUpdateNode | madArg0ToArg1Indirect | madArg0ToArg1Indirect | | tests.cpp:151:6:151:26 | [summary] to write: Argument[*1] in madArg0ToArg1Indirect | PostUpdateNode | madArg0ToArg1Indirect | madArg0ToArg1Indirect |
| tests.cpp:135:6:135:34 | [summary param] *0 in madArg0IndirectToArg1Indirect | ParameterNode | madArg0IndirectToArg1Indirect | madArg0IndirectToArg1Indirect | | tests.cpp:152:6:152:34 | [summary param] *0 in madArg0IndirectToArg1Indirect | ParameterNode | madArg0IndirectToArg1Indirect | madArg0IndirectToArg1Indirect |
| tests.cpp:135:6:135:34 | [summary param] *1 in madArg0IndirectToArg1Indirect | ParameterNode | madArg0IndirectToArg1Indirect | madArg0IndirectToArg1Indirect | | tests.cpp:152:6:152:34 | [summary param] *1 in madArg0IndirectToArg1Indirect | ParameterNode | madArg0IndirectToArg1Indirect | madArg0IndirectToArg1Indirect |
| tests.cpp:135:6:135:34 | [summary] to write: Argument[*1] in madArg0IndirectToArg1Indirect | PostUpdateNode | madArg0IndirectToArg1Indirect | madArg0IndirectToArg1Indirect | | tests.cpp:152:6:152:34 | [summary] to write: Argument[*1] in madArg0IndirectToArg1Indirect | PostUpdateNode | madArg0IndirectToArg1Indirect | madArg0IndirectToArg1Indirect |
| tests.cpp:136:5:136:18 | [summary param] 2 in madArgsComplex | ParameterNode | madArgsComplex | madArgsComplex | | tests.cpp:153:5:153:18 | [summary param] 2 in madArgsComplex | ParameterNode | madArgsComplex | madArgsComplex |
| tests.cpp:136:5:136:18 | [summary param] *0 in madArgsComplex | ParameterNode | madArgsComplex | madArgsComplex | | tests.cpp:153:5:153:18 | [summary param] *0 in madArgsComplex | ParameterNode | madArgsComplex | madArgsComplex |
| tests.cpp:136:5:136:18 | [summary param] *1 in madArgsComplex | ParameterNode | madArgsComplex | madArgsComplex | | tests.cpp:153:5:153:18 | [summary param] *1 in madArgsComplex | ParameterNode | madArgsComplex | madArgsComplex |
| tests.cpp:136:5:136:18 | [summary] to write: ReturnValue in madArgsComplex | ReturnNode | madArgsComplex | madArgsComplex | | tests.cpp:153:5:153:18 | [summary] to write: ReturnValue in madArgsComplex | ReturnNode | madArgsComplex | madArgsComplex |
| tests.cpp:138:5:138:28 | [summary param] 2 in madAndImplementedComplex | ParameterNode | madAndImplementedComplex | madAndImplementedComplex | | tests.cpp:155:5:155:28 | [summary param] 2 in madAndImplementedComplex | ParameterNode | madAndImplementedComplex | madAndImplementedComplex |
| tests.cpp:138:5:138:28 | [summary] to write: ReturnValue in madAndImplementedComplex | ReturnNode | madAndImplementedComplex | madAndImplementedComplex | | tests.cpp:155:5:155:28 | [summary] to write: ReturnValue in madAndImplementedComplex | ReturnNode | madAndImplementedComplex | madAndImplementedComplex |
| tests.cpp:143:5:143:24 | [summary param] 0 in madArg0FieldToReturn | ParameterNode | madArg0FieldToReturn | madArg0FieldToReturn | | tests.cpp:160:5:160:24 | [summary param] 0 in madArg0FieldToReturn | ParameterNode | madArg0FieldToReturn | madArg0FieldToReturn |
| tests.cpp:143:5:143:24 | [summary] read: Argument[0].Field[MyContainer::value]/Field[value] in madArg0FieldToReturn | | madArg0FieldToReturn | madArg0FieldToReturn | | tests.cpp:160:5:160:24 | [summary] read: Argument[0].Field[MyContainer::value]/Field[value] in madArg0FieldToReturn | | madArg0FieldToReturn | madArg0FieldToReturn |
| tests.cpp:143:5:143:24 | [summary] to write: ReturnValue in madArg0FieldToReturn | ReturnNode | madArg0FieldToReturn | madArg0FieldToReturn | | tests.cpp:160:5:160:24 | [summary] to write: ReturnValue in madArg0FieldToReturn | ReturnNode | madArg0FieldToReturn | madArg0FieldToReturn |
| tests.cpp:144:5:144:32 | [summary param] *0 in madArg0IndirectFieldToReturn | ParameterNode | madArg0IndirectFieldToReturn | madArg0IndirectFieldToReturn | | tests.cpp:161:5:161:32 | [summary param] *0 in madArg0IndirectFieldToReturn | ParameterNode | madArg0IndirectFieldToReturn | madArg0IndirectFieldToReturn |
| tests.cpp:144:5:144:32 | [summary] read: Argument[*0].Field[MyContainer::value]/Field[value] in madArg0IndirectFieldToReturn | | madArg0IndirectFieldToReturn | madArg0IndirectFieldToReturn | | tests.cpp:161:5:161:32 | [summary] read: Argument[*0].Field[MyContainer::value]/Field[value] in madArg0IndirectFieldToReturn | | madArg0IndirectFieldToReturn | madArg0IndirectFieldToReturn |
| tests.cpp:144:5:144:32 | [summary] to write: ReturnValue in madArg0IndirectFieldToReturn | ReturnNode | madArg0IndirectFieldToReturn | madArg0IndirectFieldToReturn | | tests.cpp:161:5:161:32 | [summary] to write: ReturnValue in madArg0IndirectFieldToReturn | ReturnNode | madArg0IndirectFieldToReturn | madArg0IndirectFieldToReturn |
| tests.cpp:145:5:145:32 | [summary param] 0 in madArg0FieldIndirectToReturn | ParameterNode | madArg0FieldIndirectToReturn | madArg0FieldIndirectToReturn | | tests.cpp:162:5:162:32 | [summary param] 0 in madArg0FieldIndirectToReturn | ParameterNode | madArg0FieldIndirectToReturn | madArg0FieldIndirectToReturn |
| tests.cpp:145:5:145:32 | [summary] read: Argument[0].Field[*MyContainer::ptr]/Field[*ptr] in madArg0FieldIndirectToReturn | | madArg0FieldIndirectToReturn | madArg0FieldIndirectToReturn | | tests.cpp:162:5:162:32 | [summary] read: Argument[0].Field[*MyContainer::ptr]/Field[*ptr] in madArg0FieldIndirectToReturn | | madArg0FieldIndirectToReturn | madArg0FieldIndirectToReturn |
| tests.cpp:145:5:145:32 | [summary] to write: ReturnValue in madArg0FieldIndirectToReturn | ReturnNode | madArg0FieldIndirectToReturn | madArg0FieldIndirectToReturn | | tests.cpp:162:5:162:32 | [summary] to write: ReturnValue in madArg0FieldIndirectToReturn | ReturnNode | madArg0FieldIndirectToReturn | madArg0FieldIndirectToReturn |
| tests.cpp:146:13:146:32 | [summary param] 0 in madArg0ToReturnField | ParameterNode | madArg0ToReturnField | madArg0ToReturnField | | tests.cpp:163:13:163:32 | [summary param] 0 in madArg0ToReturnField | ParameterNode | madArg0ToReturnField | madArg0ToReturnField |
| tests.cpp:146:13:146:32 | [summary] to write: ReturnValue in madArg0ToReturnField | ReturnNode | madArg0ToReturnField | madArg0ToReturnField | | tests.cpp:163:13:163:32 | [summary] to write: ReturnValue in madArg0ToReturnField | ReturnNode | madArg0ToReturnField | madArg0ToReturnField |
| tests.cpp:146:13:146:32 | [summary] to write: ReturnValue.Field[MyContainer::value]/Field[value] in madArg0ToReturnField | | madArg0ToReturnField | madArg0ToReturnField | | tests.cpp:163:13:163:32 | [summary] to write: ReturnValue.Field[MyContainer::value]/Field[value] in madArg0ToReturnField | | madArg0ToReturnField | madArg0ToReturnField |
| tests.cpp:147:14:147:41 | [summary param] 0 in madArg0ToReturnIndirectField | ParameterNode | madArg0ToReturnIndirectField | madArg0ToReturnIndirectField | | tests.cpp:164:14:164:41 | [summary param] 0 in madArg0ToReturnIndirectField | ParameterNode | madArg0ToReturnIndirectField | madArg0ToReturnIndirectField |
| tests.cpp:147:14:147:41 | [summary] to write: ReturnValue[*] in madArg0ToReturnIndirectField | ReturnNode | madArg0ToReturnIndirectField | madArg0ToReturnIndirectField | | tests.cpp:164:14:164:41 | [summary] to write: ReturnValue[*] in madArg0ToReturnIndirectField | ReturnNode | madArg0ToReturnIndirectField | madArg0ToReturnIndirectField |
| tests.cpp:147:14:147:41 | [summary] to write: ReturnValue[*].Field[MyContainer::value]/Field[value] in madArg0ToReturnIndirectField | | madArg0ToReturnIndirectField | madArg0ToReturnIndirectField | | tests.cpp:164:14:164:41 | [summary] to write: ReturnValue[*].Field[MyContainer::value]/Field[value] in madArg0ToReturnIndirectField | | madArg0ToReturnIndirectField | madArg0ToReturnIndirectField |
| tests.cpp:148:13:148:40 | [summary param] 0 in madArg0ToReturnFieldIndirect | ParameterNode | madArg0ToReturnFieldIndirect | madArg0ToReturnFieldIndirect | | tests.cpp:165:13:165:40 | [summary param] 0 in madArg0ToReturnFieldIndirect | ParameterNode | madArg0ToReturnFieldIndirect | madArg0ToReturnFieldIndirect |
| tests.cpp:148:13:148:40 | [summary] to write: ReturnValue in madArg0ToReturnFieldIndirect | ReturnNode | madArg0ToReturnFieldIndirect | madArg0ToReturnFieldIndirect | | tests.cpp:165:13:165:40 | [summary] to write: ReturnValue in madArg0ToReturnFieldIndirect | ReturnNode | madArg0ToReturnFieldIndirect | madArg0ToReturnFieldIndirect |
| tests.cpp:148:13:148:40 | [summary] to write: ReturnValue.Field[*MyContainer::ptr]/Field[*ptr] in madArg0ToReturnFieldIndirect | | madArg0ToReturnFieldIndirect | madArg0ToReturnFieldIndirect | | tests.cpp:165:13:165:40 | [summary] to write: ReturnValue.Field[*MyContainer::ptr]/Field[*ptr] in madArg0ToReturnFieldIndirect | | madArg0ToReturnFieldIndirect | madArg0ToReturnFieldIndirect |
| tests.cpp:250:7:250:19 | [summary param] 0 in madArg0ToSelf | ParameterNode | madArg0ToSelf | madArg0ToSelf | | tests.cpp:284:7:284:19 | [summary param] 0 in madArg0ToSelf | ParameterNode | madArg0ToSelf | madArg0ToSelf |
| tests.cpp:250:7:250:19 | [summary param] this in madArg0ToSelf | ParameterNode | madArg0ToSelf | madArg0ToSelf | | tests.cpp:284:7:284:19 | [summary param] this in madArg0ToSelf | ParameterNode | madArg0ToSelf | madArg0ToSelf |
| tests.cpp:250:7:250:19 | [summary] to write: Argument[this] in madArg0ToSelf | PostUpdateNode | madArg0ToSelf | madArg0ToSelf | | tests.cpp:284:7:284:19 | [summary] to write: Argument[this] in madArg0ToSelf | PostUpdateNode | madArg0ToSelf | madArg0ToSelf |
| tests.cpp:251:6:251:20 | [summary param] this in madSelfToReturn | ParameterNode | madSelfToReturn | madSelfToReturn | | tests.cpp:285:6:285:20 | [summary param] this in madSelfToReturn | ParameterNode | madSelfToReturn | madSelfToReturn |
| tests.cpp:251:6:251:20 | [summary] to write: ReturnValue in madSelfToReturn | ReturnNode | madSelfToReturn | madSelfToReturn | | tests.cpp:285:6:285:20 | [summary] to write: ReturnValue in madSelfToReturn | ReturnNode | madSelfToReturn | madSelfToReturn |
| tests.cpp:253:7:253:20 | [summary param] 0 in madArg0ToField | ParameterNode | madArg0ToField | madArg0ToField | | tests.cpp:287:7:287:20 | [summary param] 0 in madArg0ToField | ParameterNode | madArg0ToField | madArg0ToField |
| tests.cpp:253:7:253:20 | [summary param] this in madArg0ToField | ParameterNode | madArg0ToField | madArg0ToField | | tests.cpp:287:7:287:20 | [summary param] this in madArg0ToField | ParameterNode | madArg0ToField | madArg0ToField |
| tests.cpp:253:7:253:20 | [summary] to write: Argument[this] in madArg0ToField | PostUpdateNode | madArg0ToField | madArg0ToField | | tests.cpp:287:7:287:20 | [summary] to write: Argument[this] in madArg0ToField | PostUpdateNode | madArg0ToField | madArg0ToField |
| tests.cpp:253:7:253:20 | [summary] to write: Argument[this].Field[MyClass::val]/Field[val] in madArg0ToField | | madArg0ToField | madArg0ToField | | tests.cpp:287:7:287:20 | [summary] to write: Argument[this].Field[MyClass::val]/Field[val] in madArg0ToField | | madArg0ToField | madArg0ToField |
| tests.cpp:254:6:254:21 | [summary param] this in madFieldToReturn | ParameterNode | madFieldToReturn | madFieldToReturn | | tests.cpp:288:6:288:21 | [summary param] this in madFieldToReturn | ParameterNode | madFieldToReturn | madFieldToReturn |
| tests.cpp:254:6:254:21 | [summary] read: Argument[this].Field[MyClass::val]/Field[val] in madFieldToReturn | | madFieldToReturn | madFieldToReturn | | tests.cpp:288:6:288:21 | [summary] read: Argument[this].Field[MyClass::val]/Field[val] in madFieldToReturn | | madFieldToReturn | madFieldToReturn |
| tests.cpp:254:6:254:21 | [summary] to write: ReturnValue in madFieldToReturn | ReturnNode | madFieldToReturn | madFieldToReturn | | tests.cpp:288:6:288:21 | [summary] to write: ReturnValue in madFieldToReturn | ReturnNode | madFieldToReturn | madFieldToReturn |
| tests.cpp:277:7:277:30 | [summary param] this in namespaceMadSelfToReturn | ParameterNode | namespaceMadSelfToReturn | namespaceMadSelfToReturn | | tests.cpp:313:7:313:30 | [summary param] this in namespaceMadSelfToReturn | ParameterNode | namespaceMadSelfToReturn | namespaceMadSelfToReturn |
| tests.cpp:277:7:277:30 | [summary] to write: ReturnValue in namespaceMadSelfToReturn | ReturnNode | namespaceMadSelfToReturn | namespaceMadSelfToReturn | | tests.cpp:313:7:313:30 | [summary] to write: ReturnValue in namespaceMadSelfToReturn | ReturnNode | namespaceMadSelfToReturn | namespaceMadSelfToReturn |
| tests.cpp:392:5:392:29 | [summary param] 0 in madCallArg0ReturnToReturn | ParameterNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn | | tests.cpp:434:5:434:29 | [summary param] 0 in madCallArg0ReturnToReturn | ParameterNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn |
| tests.cpp:392:5:392:29 | [summary] read: Argument[0].Parameter[this pointer] in madCallArg0ReturnToReturn | PostUpdateNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn | | tests.cpp:434:5:434:29 | [summary] read: Argument[0].Parameter[this pointer] in madCallArg0ReturnToReturn | PostUpdateNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn |
| tests.cpp:392:5:392:29 | [summary] read: Argument[0].ReturnValue in madCallArg0ReturnToReturn | OutNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn | | tests.cpp:434:5:434:29 | [summary] read: Argument[0].ReturnValue in madCallArg0ReturnToReturn | OutNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn |
| tests.cpp:392:5:392:29 | [summary] to write: Argument[0].Parameter[this pointer] in madCallArg0ReturnToReturn | ArgumentNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn | | tests.cpp:434:5:434:29 | [summary] to write: Argument[0].Parameter[this pointer] in madCallArg0ReturnToReturn | ArgumentNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn |
| tests.cpp:392:5:392:29 | [summary] to write: ReturnValue in madCallArg0ReturnToReturn | ReturnNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn | | tests.cpp:434:5:434:29 | [summary] to write: ReturnValue in madCallArg0ReturnToReturn | ReturnNode | madCallArg0ReturnToReturn | madCallArg0ReturnToReturn |
| tests.cpp:393:9:393:38 | [summary param] 0 in madCallArg0ReturnToReturnFirst | ParameterNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst | | tests.cpp:435:9:435:38 | [summary param] 0 in madCallArg0ReturnToReturnFirst | ParameterNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst |
| tests.cpp:393:9:393:38 | [summary] read: Argument[0].Parameter[this pointer] in madCallArg0ReturnToReturnFirst | PostUpdateNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst | | tests.cpp:435:9:435:38 | [summary] read: Argument[0].Parameter[this pointer] in madCallArg0ReturnToReturnFirst | PostUpdateNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst |
| tests.cpp:393:9:393:38 | [summary] read: Argument[0].ReturnValue in madCallArg0ReturnToReturnFirst | OutNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst | | tests.cpp:435:9:435:38 | [summary] read: Argument[0].ReturnValue in madCallArg0ReturnToReturnFirst | OutNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst |
| tests.cpp:393:9:393:38 | [summary] to write: Argument[0].Parameter[this pointer] in madCallArg0ReturnToReturnFirst | ArgumentNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst | | tests.cpp:435:9:435:38 | [summary] to write: Argument[0].Parameter[this pointer] in madCallArg0ReturnToReturnFirst | ArgumentNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst |
| tests.cpp:393:9:393:38 | [summary] to write: ReturnValue in madCallArg0ReturnToReturnFirst | ReturnNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst | | tests.cpp:435:9:435:38 | [summary] to write: ReturnValue in madCallArg0ReturnToReturnFirst | ReturnNode | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst |
| tests.cpp:393:9:393:38 | [summary] to write: ReturnValue.Field[first]/Field[intPair::first] in madCallArg0ReturnToReturnFirst | | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst | | tests.cpp:435:9:435:38 | [summary] to write: ReturnValue.Field[first]/Field[intPair::first] in madCallArg0ReturnToReturnFirst | | madCallArg0ReturnToReturnFirst | madCallArg0ReturnToReturnFirst |
| tests.cpp:394:6:394:25 | [summary param] 0 in madCallArg0WithValue | ParameterNode | madCallArg0WithValue | madCallArg0WithValue | | tests.cpp:436:6:436:25 | [summary param] 0 in madCallArg0WithValue | ParameterNode | madCallArg0WithValue | madCallArg0WithValue |
| tests.cpp:394:6:394:25 | [summary param] 1 in madCallArg0WithValue | ParameterNode | madCallArg0WithValue | madCallArg0WithValue | | tests.cpp:436:6:436:25 | [summary param] 1 in madCallArg0WithValue | ParameterNode | madCallArg0WithValue | madCallArg0WithValue |
| tests.cpp:394:6:394:25 | [summary] read: Argument[0].Parameter[0] in madCallArg0WithValue | PostUpdateNode | madCallArg0WithValue | madCallArg0WithValue | | tests.cpp:436:6:436:25 | [summary] read: Argument[0].Parameter[0] in madCallArg0WithValue | PostUpdateNode | madCallArg0WithValue | madCallArg0WithValue |
| tests.cpp:394:6:394:25 | [summary] read: Argument[0].Parameter[this pointer] in madCallArg0WithValue | PostUpdateNode | madCallArg0WithValue | madCallArg0WithValue | | tests.cpp:436:6:436:25 | [summary] read: Argument[0].Parameter[this pointer] in madCallArg0WithValue | PostUpdateNode | madCallArg0WithValue | madCallArg0WithValue |
| tests.cpp:394:6:394:25 | [summary] to write: Argument[0].Parameter[0] in madCallArg0WithValue | ArgumentNode | madCallArg0WithValue | madCallArg0WithValue | | tests.cpp:436:6:436:25 | [summary] to write: Argument[0].Parameter[0] in madCallArg0WithValue | ArgumentNode | madCallArg0WithValue | madCallArg0WithValue |
| tests.cpp:394:6:394:25 | [summary] to write: Argument[0].Parameter[this pointer] in madCallArg0WithValue | ArgumentNode | madCallArg0WithValue | madCallArg0WithValue | | tests.cpp:436:6:436:25 | [summary] to write: Argument[0].Parameter[this pointer] in madCallArg0WithValue | ArgumentNode | madCallArg0WithValue | madCallArg0WithValue |
| tests.cpp:394:6:394:25 | [summary] to write: Argument[1] in madCallArg0WithValue | PostUpdateNode | madCallArg0WithValue | madCallArg0WithValue | | tests.cpp:436:6:436:25 | [summary] to write: Argument[1] in madCallArg0WithValue | PostUpdateNode | madCallArg0WithValue | madCallArg0WithValue |
| tests.cpp:395:5:395:36 | [summary param] 1 in madCallReturnValueIgnoreFunction | ParameterNode | madCallReturnValueIgnoreFunction | madCallReturnValueIgnoreFunction | | tests.cpp:437:5:437:36 | [summary param] 1 in madCallReturnValueIgnoreFunction | ParameterNode | madCallReturnValueIgnoreFunction | madCallReturnValueIgnoreFunction |
| tests.cpp:395:5:395:36 | [summary] to write: ReturnValue in madCallReturnValueIgnoreFunction | ReturnNode | madCallReturnValueIgnoreFunction | madCallReturnValueIgnoreFunction | | tests.cpp:437:5:437:36 | [summary] to write: ReturnValue in madCallReturnValueIgnoreFunction | ReturnNode | madCallReturnValueIgnoreFunction | madCallReturnValueIgnoreFunction |
| tests.cpp:417:5:417:31 | [summary param] *0 in parameter_ref_to_return_ref | ParameterNode | parameter_ref_to_return_ref | parameter_ref_to_return_ref | | tests.cpp:459:5:459:31 | [summary param] *0 in parameter_ref_to_return_ref | ParameterNode | parameter_ref_to_return_ref | parameter_ref_to_return_ref |
| tests.cpp:417:5:417:31 | [summary] to write: ReturnValue[*] in parameter_ref_to_return_ref | ReturnNode | parameter_ref_to_return_ref | parameter_ref_to_return_ref | | tests.cpp:459:5:459:31 | [summary] to write: ReturnValue[*] in parameter_ref_to_return_ref | ReturnNode | parameter_ref_to_return_ref | parameter_ref_to_return_ref |
| tests.cpp:429:5:429:17 | [summary param] *0 in receive_array | ParameterNode | receive_array | receive_array | | tests.cpp:471:5:471:17 | [summary param] *0 in receive_array | ParameterNode | receive_array | receive_array |
| tests.cpp:429:5:429:17 | [summary] to write: ReturnValue in receive_array | ReturnNode | receive_array | receive_array | | tests.cpp:471:5:471:17 | [summary] to write: ReturnValue in receive_array | ReturnNode | receive_array | receive_array |

View File

@@ -11,12 +11,15 @@ extensions:
- ["", "", False, "remoteMadSourceDoubleIndirect", "", "", "ReturnValue[**]", "remote", "manual"] - ["", "", False, "remoteMadSourceDoubleIndirect", "", "", "ReturnValue[**]", "remote", "manual"]
- ["", "", False, "remoteMadSourceIndirectArg0", "", "", "Argument[*0]", "remote", "manual"] - ["", "", False, "remoteMadSourceIndirectArg0", "", "", "Argument[*0]", "remote", "manual"]
- ["", "", False, "remoteMadSourceIndirectArg1", "", "", "Argument[*1]", "remote", "manual"] - ["", "", False, "remoteMadSourceIndirectArg1", "", "", "Argument[*1]", "remote", "manual"]
- ["", "", False, "remoteMadSourceVar", "", "", "", "remote", "manual"]
- ["", "", False, "remoteMadSourceVarIndirect", "", "", "*", "remote", "manual"] # we can't express this source/sink correctly at present, "*" is not a valid access path
- ["", "", False, "remoteMadSourceParam0", "", "", "Parameter[0]", "remote", "manual"] - ["", "", False, "remoteMadSourceParam0", "", "", "Parameter[0]", "remote", "manual"]
- ["MyNamespace", "", False, "namespaceLocalMadSource", "", "", "ReturnValue", "local", "manual"] - ["MyNamespace", "", False, "namespaceLocalMadSource", "", "", "ReturnValue", "local", "manual"]
- ["MyNamespace", "", False, "namespaceLocalMadSourceVar", "", "", "", "local", "manual"] - ["MyNamespace", "", False, "namespaceLocalMadSourceVar", "", "", "", "local", "manual"]
- ["MyNamespace::MyNamespace2", "", False, "namespace2LocalMadSource", "", "", "ReturnValue", "local", "manual"] - ["MyNamespace::MyNamespace2", "", False, "namespace2LocalMadSource", "", "", "ReturnValue", "local", "manual"]
- ["", "MyClass", True, "memberRemoteMadSource", "", "", "ReturnValue", "remote", "manual"] - ["", "MyClass", True, "memberRemoteMadSource", "", "", "ReturnValue", "remote", "manual"]
- ["", "MyClass", True, "memberRemoteMadSourceIndirectArg0", "", "", "Argument[*0]", "remote", "manual"] - ["", "MyClass", True, "memberRemoteMadSourceIndirectArg0", "", "", "Argument[*0]", "remote", "manual"]
- ["", "MyClass", True, "memberRemoteMadSourceVar", "", "", "", "remote", "manual"]
- ["", "MyClass", True, "subtypeRemoteMadSource1", "", "", "ReturnValue", "remote", "manual"] - ["", "MyClass", True, "subtypeRemoteMadSource1", "", "", "ReturnValue", "remote", "manual"]
- ["", "MyClass", False, "subtypeNonSource", "", "", "ReturnValue", "remote", "manual"] # the tests define this in MyDerivedClass, so it should *not* be recongized as a source - ["", "MyClass", False, "subtypeNonSource", "", "", "ReturnValue", "remote", "manual"] # the tests define this in MyDerivedClass, so it should *not* be recongized as a source
- ["", "MyClass", True, "qualifierSource", "", "", "Argument[-1]", "remote", "manual"] - ["", "MyClass", True, "qualifierSource", "", "", "Argument[-1]", "remote", "manual"]
@@ -32,13 +35,18 @@ extensions:
- ["", "", False, "madSinkArg02", "", "", "Argument[0,2]", "test-sink", "manual"] - ["", "", False, "madSinkArg02", "", "", "Argument[0,2]", "test-sink", "manual"]
- ["", "", False, "madSinkIndirectArg0", "", "", "Argument[*0]", "test-sink", "manual"] - ["", "", False, "madSinkIndirectArg0", "", "", "Argument[*0]", "test-sink", "manual"]
- ["", "", False, "madSinkDoubleIndirectArg0", "", "", "Argument[**0]", "test-sink", "manual"] - ["", "", False, "madSinkDoubleIndirectArg0", "", "", "Argument[**0]", "test-sink", "manual"]
- ["", "", False, "madSinkVar", "", "", "", "test-sink", "manual"]
- ["", "", False, "madSinkVarIndirect", "", "", "*", "test-sink", "manual"] # we can't express this source/sink correctly at present, "*" is not a valid access path
- ["", "", False, "madSinkParam0", "", "", "Parameter[0]", "test-sink", "manual"] - ["", "", False, "madSinkParam0", "", "", "Parameter[0]", "test-sink", "manual"]
- ["", "MyClass", True, "memberMadSinkArg0", "", "", "Argument[0]", "test-sink", "manual"] - ["", "MyClass", True, "memberMadSinkArg0", "", "", "Argument[0]", "test-sink", "manual"]
- ["", "MyClass", True, "memberMadSinkVar", "", "", "", "test-sink", "manual"]
- ["", "MyClass", True, "qualifierSink", "", "", "Argument[-1]", "test-sink", "manual"] - ["", "MyClass", True, "qualifierSink", "", "", "Argument[-1]", "test-sink", "manual"]
- ["", "MyClass", True, "qualifierArg0Sink", "", "", "Argument[-1..0]", "test-sink", "manual"] - ["", "MyClass", True, "qualifierArg0Sink", "", "", "Argument[-1..0]", "test-sink", "manual"]
- ["", "MyClass", True, "qualifierFieldSink", "", "", "Argument[-1].val", "test-sink", "manual"] - ["", "MyClass", True, "qualifierFieldSink", "", "", "Argument[-1].val", "test-sink", "manual"]
- ["MyNamespace", "MyClass", True, "namespaceMemberMadSinkArg0", "", "", "Argument[0]", "test-sink", "manual"] - ["MyNamespace", "MyClass", True, "namespaceMemberMadSinkArg0", "", "", "Argument[0]", "test-sink", "manual"]
- ["MyNamespace", "MyClass", True, "namespaceStaticMemberMadSinkArg0", "", "", "Argument[0]", "test-sink", "manual"] - ["MyNamespace", "MyClass", True, "namespaceStaticMemberMadSinkArg0", "", "", "Argument[0]", "test-sink", "manual"]
- ["MyNamespace", "MyClass", True, "namespaceMemberMadSinkVar", "", "", "", "test-sink", "manual"]
- ["MyNamespace", "MyClass", True, "namespaceStaticMemberMadSinkVar", "", "", "", "test-sink", "manual"]
- addsTo: - addsTo:
pack: codeql/cpp-all pack: codeql/cpp-all
extensible: summaryModel extensible: summaryModel
@@ -60,6 +68,9 @@ extensions:
- ["", "", False, "madArg0ToReturnField", "", "", "Argument[0]", "ReturnValue.Field[value]", "taint", "manual"] - ["", "", False, "madArg0ToReturnField", "", "", "Argument[0]", "ReturnValue.Field[value]", "taint", "manual"]
- ["", "", False, "madArg0ToReturnIndirectField", "", "", "Argument[0]", "ReturnValue[*].Field[value]", "taint", "manual"] - ["", "", False, "madArg0ToReturnIndirectField", "", "", "Argument[0]", "ReturnValue[*].Field[value]", "taint", "manual"]
- ["", "", False, "madArg0ToReturnFieldIndirect", "", "", "Argument[0]", "ReturnValue.Field[*ptr]", "taint", "manual"] - ["", "", False, "madArg0ToReturnFieldIndirect", "", "", "Argument[0]", "ReturnValue.Field[*ptr]", "taint", "manual"]
- ["", "", False, "madFieldToFieldVar", "", "", "Field[value]", "Field[value2]", "taint", "manual"] # we can't express this source/sink correctly at present, "Field[value]" is not a valid input and "Field[value2]" is not a valid output
- ["", "", False, "madFieldToIndirectFieldVar", "", "", "Field[value]", "Field[*ptr]", "taint", "manual"] # we can't express this source/sink correctly at present, "Field[value]" is not a valid input and "Field[*ptr]" is not a valid output
- ["", "", False, "madIndirectFieldToFieldVar", "", "", "Field[value]", "Field[value2]", "taint", "manual"] # we can't express this source/sink correctly at present, "Field[value]" is not a valid input and "Field[value2]" is not a valid output
- ["", "MyClass", True, "madArg0ToSelf", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["", "MyClass", True, "madArg0ToSelf", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["", "MyClass", True, "madSelfToReturn", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["", "MyClass", True, "madSelfToReturn", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["", "MyClass", True, "madArg0ToField", "", "", "Argument[0]", "Argument[-1].Field[val]", "taint", "manual"] - ["", "MyClass", True, "madArg0ToField", "", "", "Argument[0]", "Argument[-1].Field[val]", "taint", "manual"]

View File

@@ -17,8 +17,13 @@ int *remoteMadSourceIndirect(); // $ interpretElement
int **remoteMadSourceDoubleIndirect(); // $ interpretElement int **remoteMadSourceDoubleIndirect(); // $ interpretElement
void remoteMadSourceIndirectArg0(int *x, int *y); // $ interpretElement void remoteMadSourceIndirectArg0(int *x, int *y); // $ interpretElement
void remoteMadSourceIndirectArg1(int &x, int &y); // $ interpretElement void remoteMadSourceIndirectArg1(int &x, int &y); // $ interpretElement
int remoteMadSourceVar; // $ interpretElement
int *remoteMadSourceVarIndirect; // $ interpretElement
namespace MyNamespace { namespace MyNamespace {
int namespaceLocalMadSource(); // $ interpretElement
int namespaceLocalMadSourceVar; // $ interpretElement
namespace MyNamespace2 { namespace MyNamespace2 {
int namespace2LocalMadSource(); // $ interpretElement int namespace2LocalMadSource(); // $ interpretElement
} }
@@ -64,9 +69,14 @@ void test_sources() {
sink(c); sink(c);
sink(d); // $ ir sink(d); // $ ir
sink(remoteMadSourceVar); // $ ir
sink(*remoteMadSourceVarIndirect); // $ MISSING: ir
int e = localMadSource(); int e = localMadSource();
sink(e); // $ ir sink(e); // $ ir
sink(MyNamespace::namespaceLocalMadSource()); // $ ir
sink(MyNamespace::namespaceLocalMadSourceVar); // $ ir
sink(MyNamespace::MyNamespace2::namespace2LocalMadSource()); // $ ir sink(MyNamespace::MyNamespace2::namespace2LocalMadSource()); // $ ir
sink(MyNamespace::localMadSource()); // $ (the MyNamespace version of this function is not a source) sink(MyNamespace::localMadSource()); // $ (the MyNamespace version of this function is not a source)
sink(namespaceLocalMadSource()); // (the global namespace version of this function is not a source) sink(namespaceLocalMadSource()); // (the global namespace version of this function is not a source)
@@ -86,8 +96,8 @@ void madSinkArg01(int x, int y, int z); // $ interpretElement
void madSinkArg02(int x, int y, int z); // $ interpretElement void madSinkArg02(int x, int y, int z); // $ interpretElement
void madSinkIndirectArg0(int *x); // $ interpretElement void madSinkIndirectArg0(int *x); // $ interpretElement
void madSinkDoubleIndirectArg0(int **x); // $ interpretElement void madSinkDoubleIndirectArg0(int **x); // $ interpretElement
int madSinkVar; // $ interpretElement
int *madSinkVarIndirect; // $ interpretElement
void test_sinks() { void test_sinks() {
// test sinks // test sinks
@@ -108,8 +118,15 @@ void test_sinks() {
madSinkIndirectArg0(&a); // $ ir madSinkIndirectArg0(&a); // $ ir
madSinkIndirectArg0(a_ptr); // $ ir madSinkIndirectArg0(a_ptr); // $ ir
madSinkDoubleIndirectArg0(&a_ptr); // $ ir madSinkDoubleIndirectArg0(&a_ptr); // $ ir
madSinkVar = source(); // $ ir
// test sources + sinks together
madSinkArg0(localMadSource()); // $ ir madSinkArg0(localMadSource()); // $ ir
madSinkIndirectArg0(remoteMadSourceIndirect()); // $ ir madSinkIndirectArg0(remoteMadSourceIndirect()); // $ ir
madSinkVar = remoteMadSourceVar; // $ ir
*madSinkVarIndirect = remoteMadSourceVar; // $ MISSING: ir
} }
void madSinkParam0(int x) { // $ interpretElement void madSinkParam0(int x) { // $ interpretElement
@@ -147,6 +164,10 @@ MyContainer madArg0ToReturnField(int x); // $ interpretElement
MyContainer *madArg0ToReturnIndirectField(int x); // $ interpretElement MyContainer *madArg0ToReturnIndirectField(int x); // $ interpretElement
MyContainer madArg0ToReturnFieldIndirect(int x); // $ interpretElement MyContainer madArg0ToReturnFieldIndirect(int x); // $ interpretElement
MyContainer madFieldToFieldVar; // $ interpretElement
MyContainer madFieldToIndirectFieldVar; // $ interpretElement
MyContainer *madIndirectFieldToFieldVar; // $ interpretElement
void test_summaries() { void test_summaries() {
// test summaries // test summaries
@@ -220,6 +241,19 @@ void test_summaries() {
int *rtn2_ptr = rtn2.ptr; int *rtn2_ptr = rtn2.ptr;
sink(*rtn2_ptr); // $ ir sink(*rtn2_ptr); // $ ir
// test global variable summaries
madFieldToFieldVar.value = source();
sink(madFieldToFieldVar.value2); // $ MISSING: ir
madFieldToIndirectFieldVar.value = source();
sink(madFieldToIndirectFieldVar.ptr);
sink(*(madFieldToIndirectFieldVar.ptr)); // $ MISSING: ir
madIndirectFieldToFieldVar->value = source();
sink((*madIndirectFieldToFieldVar).value2); // $ MISSING: ir
sink(madIndirectFieldToFieldVar->value2); // $ MISSING: ir
// test source + sinks + summaries together // test source + sinks + summaries together
madSinkArg0(madArg0ToReturn(remoteMadSource())); // $ ir madSinkArg0(madArg0ToReturn(remoteMadSource())); // $ ir
@@ -235,13 +269,13 @@ public:
// sources // sources
int memberRemoteMadSource(); // $ interpretElement int memberRemoteMadSource(); // $ interpretElement
void memberRemoteMadSourceIndirectArg0(int *x); // $ interpretElement void memberRemoteMadSourceIndirectArg0(int *x); // $ interpretElement
int memberRemoteMadSourceVar; // $ interpretElement
void qualifierSource(); // $ interpretElement void qualifierSource(); // $ interpretElement
void qualifierFieldSource(); // $ interpretElement void qualifierFieldSource(); // $ interpretElement
// sinks // sinks
void memberMadSinkArg0(int x); // $ interpretElement void memberMadSinkArg0(int x); // $ interpretElement
int memberMadSinkVar; // $ interpretElement
void qualifierSink(); // $ interpretElement void qualifierSink(); // $ interpretElement
void qualifierArg0Sink(int x); // $ interpretElement void qualifierArg0Sink(int x); // $ interpretElement
void qualifierFieldSink(); // $ interpretElement void qualifierFieldSink(); // $ interpretElement
@@ -272,6 +306,8 @@ namespace MyNamespace {
// sinks // sinks
void namespaceMemberMadSinkArg0(int x); // $ interpretElement void namespaceMemberMadSinkArg0(int x); // $ interpretElement
static void namespaceStaticMemberMadSinkArg0(int x); // $ interpretElement static void namespaceStaticMemberMadSinkArg0(int x); // $ interpretElement
int namespaceMemberMadSinkVar; // $ interpretElement
static int namespaceStaticMemberMadSinkVar; // $ interpretElement
// summaries // summaries
int namespaceMadSelfToReturn(); // $ interpretElement int namespaceMadSelfToReturn(); // $ interpretElement
@@ -295,6 +331,8 @@ void test_class_members() {
mc.memberRemoteMadSourceIndirectArg0(&a); mc.memberRemoteMadSourceIndirectArg0(&a);
sink(a); // $ ir sink(a); // $ ir
sink(mc.memberRemoteMadSourceVar); // $ ir
// test subtype sources // test subtype sources
sink(mdc.memberRemoteMadSource()); // $ ir sink(mdc.memberRemoteMadSource()); // $ ir
@@ -306,8 +344,12 @@ void test_class_members() {
mc.memberMadSinkArg0(source()); // $ ir mc.memberMadSinkArg0(source()); // $ ir
mc.memberMadSinkVar = source(); // $ ir
mnc.namespaceMemberMadSinkArg0(source()); // $ ir mnc.namespaceMemberMadSinkArg0(source()); // $ ir
MyNamespace::MyClass::namespaceStaticMemberMadSinkArg0(source()); // $ ir MyNamespace::MyClass::namespaceStaticMemberMadSinkArg0(source()); // $ ir
mnc.namespaceMemberMadSinkVar = source(); // $ ir
MyNamespace::MyClass::namespaceStaticMemberMadSinkVar = source(); // $ ir
// test class member summaries // test class member summaries

View File

@@ -1,4 +0,0 @@
class Program
{
static void Main() {}
}

View File

@@ -1,10 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -1,5 +0,0 @@
{
"sdk": {
"version": "9.0.201"
}
}

View File

@@ -1,8 +0,0 @@
| code/Program.cs:0:0:0:0 | code/Program.cs | |
| code/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs:0:0:0:0 | code/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs | |
| code/obj/Debug/net9.0/dotnet_build.AssemblyInfo.cs:0:0:0:0 | code/obj/Debug/net9.0/dotnet_build.AssemblyInfo.cs | |
| code/obj/Debug/net9.0/dotnet_build.GlobalUsings.g.cs:0:0:0:0 | code/obj/Debug/net9.0/dotnet_build.GlobalUsings.g.cs | |
| code/obj/Debug/net9.0/dotnet_build.dll:0:0:0:0 | code/obj/Debug/net9.0/dotnet_build.dll | |
| file://:0:0:0:0 | | |
| file://Z:/dotnet_build.csproj:0:0:0:0 | Z:/dotnet_build.csproj | relative |
| file://Z:/obj/dotnet_build.csproj.nuget.g.props:0:0:0:0 | Z:/obj/dotnet_build.csproj.nuget.g.props | relative |

View File

@@ -1,7 +0,0 @@
import csharp
from File f, string relative
where
not f.getURL().matches("file://C:/Program Files/%") and
if exists(f.getRelativePath()) then relative = "relative" else relative = ""
select f, relative

View File

@@ -1,7 +0,0 @@
import runs_on
@runs_on.windows
def test(codeql, csharp, cwd, subst_drive):
drive = subst_drive(cwd / "code")
codeql.database.create(source_root=drive)

View File

@@ -714,7 +714,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
) and ) and
model = "" model = ""
or or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model) nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
} }

View File

@@ -34,8 +34,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CsharpDataFlow>
class SinkBase = Void; class SinkBase = Void;
class FlowSummaryCallBase = Void;
predicate neutralElement(SummarizedCallableBase c, string kind, string provenance, boolean isExact) { predicate neutralElement(SummarizedCallableBase c, string kind, string provenance, boolean isExact) {
interpretNeutral(c, kind, provenance, isExact) interpretNeutral(c, kind, provenance, isExact)
} }
@@ -203,10 +201,6 @@ private module TypesInput implements Impl::Private::TypesInputSig {
} }
private module StepsInput implements Impl::Private::StepsInputSig { private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable sc) { DataFlowCall getACall(Public::SummarizedCallable sc) {
sc = viableCallable(result).asSummarizedCallable() sc = viableCallable(result).asSummarizedCallable()
} }

View File

@@ -171,7 +171,7 @@ private module Cached {
) and ) and
model = "" model = ""
or or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model) nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
} }
} }

View File

@@ -186,6 +186,13 @@ private Expr aspWrittenValue(AspInlineMember m) {
m.getMember().(Callable).canReturn(result) m.getMember().(Callable).canReturn(result)
} }
private string makeUrl(Location l) {
exists(string path, int sl, int sc, int el, int ec |
l.hasLocationInfo(path, sl, sc, el, ec) and
result = "file://" + path + ":" + sl + ":" + sc + ":" + el + ":" + ec
)
}
/** /**
* A sink for writes to properties that are accessed in ASP pages. * A sink for writes to properties that are accessed in ASP pages.
* *
@@ -201,7 +208,10 @@ private class AspxCodeSink extends Sink {
AspxCodeSink() { this.getExpr() = aspWrittenValue(inline) } AspxCodeSink() { this.getExpr() = aspWrittenValue(inline) }
override string explanation() { result = "member is accessed inline in an ASPX page" } override string explanation() {
result =
"member is [[\"accessed inline\"|\"" + makeUrl(inline.getLocation()) + "\"]] in an ASPX page"
}
} }
/** A sink for the output stream associated with a `HttpListenerResponse`. */ /** A sink for the output stream associated with a `HttpListenerResponse`. */

View File

@@ -69,26 +69,6 @@ The CodeQL library for Java and Kotlin analysis exposes the following extensible
The extensible predicates are populated using the models defined in data extension files. The extensible predicates are populated using the models defined in data extension files.
Specifying types in Java and Kotlin models
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Nested and inner classes** are denoted by joining the enclosing type and the nested type with a dollar sign (``$``), for example ``Outer$Inner``. This applies both to the type column and to nested types in a signature. For example, the ``Level`` enum nested inside the ``Logger`` interface, nested inside the ``System`` class, is written as ``System$Logger$Level``:
.. code-block:: yaml
- ["java.lang", "System$Logger", True, "log", "(System$Logger$Level,String)", "", "Argument[1]", "log-injection", "manual"]
**Generics** are erased, so type parameters are removed:
- In the type column, leave out any type parameters, so ``List<E>`` becomes ``List``.
- In the signature, replace each type parameter with its upper bound, or ``Object`` if it has none. So ``T`` from ``<T>`` becomes ``Object``, and ``T`` from ``<T extends Number>`` becomes ``Number``.
For example, ``forEach`` on ``Iterable<T>`` takes a ``Consumer<? super T>`` argument, so the type is ``Iterable`` and the signature is ``(Consumer)``:
.. code-block:: yaml
- ["java.lang", "Iterable", True, "forEach", "(Consumer)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
Examples of custom model definitions Examples of custom model definitions
------------------------------------ ------------------------------------

View File

@@ -123,7 +123,7 @@ k8s.io/api/core,,,10,,,,,,,,,,,,,,,,,,,,,,,10,
k8s.io/apimachinery/pkg/runtime,,,47,,,,,,,,,,,,,,,,,,,,,,,47, k8s.io/apimachinery/pkg/runtime,,,47,,,,,,,,,,,,,,,,,,,,,,,47,
k8s.io/klog,90,,,,,,90,,,,,,,,,,,,,,,,,,,, k8s.io/klog,90,,,,,,90,,,,,,,,,,,,,,,,,,,,
launchpad.net/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,,, launchpad.net/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,,,
log,43,,16,,,,43,,,,,,,,,,,,,,,,,,,16, log,40,,3,,,,40,,,,,,,,,,,,,,,,,,,3,
math/big,,,1,,,,,,,,,,,,,,,,,,,,,,,1, math/big,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
mime,,,14,,,,,,,,,,,,,,,,,,,,,,,14, mime,,,14,,,,,,,,,,,,,,,,,,,,,,,14,
net,2,16,100,,,,,,1,,,,,,,,1,,,,,,,16,,100, net,2,16,100,,,,,,1,,,,,,,,1,,,,,,,16,,100,
1 package sink source summary sink:command-injection sink:credentials-key sink:jwt sink:log-injection sink:nosql-injection sink:path-injection sink:regex-use[0] sink:regex-use[1] sink:regex-use[c] sink:request-forgery sink:request-forgery[TCP Addr + Port] sink:sql-injection sink:url-redirection sink:url-redirection[0] sink:url-redirection[receiver] sink:xpath-injection source:commandargs source:database source:environment source:file source:remote source:stdin summary:taint summary:value
123 k8s.io/apimachinery/pkg/runtime 47 47
124 k8s.io/klog 90 90
125 launchpad.net/xmlpath 2 2
126 log 43 40 16 3 43 40 16 3
127 math/big 1 1
128 mime 14 14
129 net 2 16 100 1 1 16 100

View File

@@ -32,7 +32,7 @@ Go framework & library support
`Revel <http://revel.github.io/>`_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",46,20,4 `Revel <http://revel.github.io/>`_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",46,20,4
`SendGrid <https://github.com/sendgrid/sendgrid-go>`_,``github.com/sendgrid/sendgrid-go*``,,1, `SendGrid <https://github.com/sendgrid/sendgrid-go>`_,``github.com/sendgrid/sendgrid-go*``,,1,
`Squirrel <https://github.com/Masterminds/squirrel>`_,"``github.com/Masterminds/squirrel*``, ``github.com/lann/squirrel*``, ``gopkg.in/Masterminds/squirrel``",81,,96 `Squirrel <https://github.com/Masterminds/squirrel>`_,"``github.com/Masterminds/squirrel*``, ``github.com/lann/squirrel*``, ``gopkg.in/Masterminds/squirrel``",81,,96
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``, ``weak``",52,625,127 `Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``, ``weak``",52,612,124
`XORM <https://xorm.io>`_,"``github.com/go-xorm/xorm*``, ``xorm.io/xorm*``",,,68 `XORM <https://xorm.io>`_,"``github.com/go-xorm/xorm*``, ``xorm.io/xorm*``",,,68
`XPath <https://github.com/antchfx/xpath>`_,``github.com/antchfx/xpath*``,,,4 `XPath <https://github.com/antchfx/xpath>`_,``github.com/antchfx/xpath*``,,,4
`appleboy/gin-jwt <https://github.com/appleboy/gin-jwt>`_,``github.com/appleboy/gin-jwt*``,,,1 `appleboy/gin-jwt <https://github.com/appleboy/gin-jwt>`_,``github.com/appleboy/gin-jwt*``,,,1
@@ -74,5 +74,5 @@ Go framework & library support
`xpathparser <https://github.com/santhosh-tekuri/xpathparser>`_,``github.com/santhosh-tekuri/xpathparser*``,,,2 `xpathparser <https://github.com/santhosh-tekuri/xpathparser>`_,``github.com/santhosh-tekuri/xpathparser*``,,,2
`yaml <https://gopkg.in/yaml.v3>`_,``gopkg.in/yaml*``,,9, `yaml <https://gopkg.in/yaml.v3>`_,``gopkg.in/yaml*``,,9,
`zap <https://go.uber.org/zap>`_,``go.uber.org/zap*``,,11,33 `zap <https://go.uber.org/zap>`_,``go.uber.org/zap*``,,11,33
Totals,,688,1085,1580 Totals,,688,1072,1577

View File

@@ -1,3 +0,0 @@
package main
func main() {}

View File

@@ -1 +0,0 @@
| file://Z:/main.go:0:0:0:0 | Z:/main.go | relative |

View File

@@ -1,5 +0,0 @@
import go
from File f, string relative
where if exists(f.getRelativePath()) then relative = "relative" else relative = ""
select f, relative

View File

@@ -1,7 +0,0 @@
import runs_on
@runs_on.windows
def test(codeql, go, cwd, subst_drive):
drive = subst_drive(cwd / "code")
codeql.database.create(command="go build main.go", source_root=drive)

View File

@@ -141,7 +141,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
any(FunctionModel m).flowStep(nodeFrom, nodeTo) and any(FunctionModel m).flowStep(nodeFrom, nodeTo) and
model = "FunctionModel" model = "FunctionModel"
or or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model) nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
} }

View File

@@ -31,8 +31,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::GoDataFlow> {
class SinkBase = Void; class SinkBase = Void;
class FlowSummaryCallBase = Void;
predicate callableFromSource(SummarizedCallableBase c) { exists(c.getFuncDef()) } predicate callableFromSource(SummarizedCallableBase c) { exists(c.getFuncDef()) }
predicate neutralElement( predicate neutralElement(
@@ -115,10 +113,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::GoDataFlow> {
private import Make<Location, DataFlowImplSpecific::GoDataFlow, Input> as Impl private import Make<Location, DataFlowImplSpecific::GoDataFlow, Input> as Impl
private module StepsInput implements Impl::Private::StepsInputSig { private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable sc) { DataFlowCall getACall(Public::SummarizedCallable sc) {
exists(DataFlow::CallNode call | exists(DataFlow::CallNode call |
call.asExpr() = result and call.asExpr() = result and

View File

@@ -109,8 +109,8 @@ private predicate localAdditionalForwardTaintStep(
or or
any(AdditionalTaintStep a).step(pred, succ) and model = "AdditionalTaintStep" any(AdditionalTaintStep a).step(pred, succ) and model = "AdditionalTaintStep"
or or
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred, FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(DataFlowPrivate::FlowSummaryNode)
succ.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model) .getSummaryNode(), succ.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
} }
/** /**

View File

@@ -188,8 +188,6 @@ org.apache.hadoop.hive.ql.metadata,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,
org.apache.hc.client5.http.async.methods,84,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,84,,,,,,,,,,,,,,,,,, org.apache.hc.client5.http.async.methods,84,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,84,,,,,,,,,,,,,,,,,,
org.apache.hc.client5.http.classic.methods,37,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,,,, org.apache.hc.client5.http.classic.methods,37,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,,,,
org.apache.hc.client5.http.fluent,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,,,,,,, org.apache.hc.client5.http.fluent,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,,,,,,,
org.apache.hc.client5.http.protocol,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
org.apache.hc.client5.http.utils,,,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,
org.apache.hc.core5.benchmark,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,, org.apache.hc.core5.benchmark,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
org.apache.hc.core5.http,73,2,45,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,72,,,,,,,,,,,,,,,,2,45, org.apache.hc.core5.http,73,2,45,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,72,,,,,,,,,,,,,,,,2,45,
1 package sink source summary sink:bean-validation sink:command-injection sink:credentials-key sink:credentials-password sink:credentials-username sink:encryption-iv sink:encryption-salt sink:environment-injection sink:file-content-store sink:fragment-injection sink:groovy-injection sink:hostname-verification sink:html-injection sink:information-leak sink:intent-redirection sink:jexl-injection sink:jndi-injection sink:js-injection sink:ldap-injection sink:log-injection sink:mvel-injection sink:notification sink:ognl-injection sink:path-injection sink:path-injection[read] sink:pending-intents sink:regex-use sink:regex-use[-1] sink:regex-use[0] sink:regex-use[] sink:regex-use[f-1] sink:regex-use[f1] sink:regex-use[f] sink:request-forgery sink:response-splitting sink:sql-injection sink:template-injection sink:trust-boundary-violation sink:unsafe-deserialization sink:url-forward sink:url-redirection sink:xpath-injection sink:xslt-injection source:android-external-storage-dir source:commandargs source:contentprovider source:database source:environment source:file source:remote summary:taint summary:value
188 org.apache.hc.client5.http.async.methods 84 84
189 org.apache.hc.client5.http.classic.methods 37 37
190 org.apache.hc.client5.http.fluent 19 19
org.apache.hc.client5.http.protocol 1 1
org.apache.hc.client5.http.utils 7 7
191 org.apache.hc.core5.benchmark 1 1
192 org.apache.hc.core5.function 1 1
193 org.apache.hc.core5.http 73 2 45 1 72 2 45

View File

@@ -40,6 +40,6 @@ Java framework & library support
`Spring <https://spring.io/>`_,``org.springframework.*``,46,494,143,26,,28,14,,35 `Spring <https://spring.io/>`_,``org.springframework.*``,46,494,143,26,,28,14,,35
`Thymeleaf <https://www.thymeleaf.org/>`_,``org.thymeleaf``,,2,2,,,,,, `Thymeleaf <https://www.thymeleaf.org/>`_,``org.thymeleaf``,,2,2,,,,,,
`jOOQ <https://www.jooq.org/>`_,``org.jooq``,,,1,,,1,,, `jOOQ <https://www.jooq.org/>`_,``org.jooq``,,,1,,,1,,,
Others,"``actions.osgi``, ``antlr``, ``ch.ethz.ssh2``, ``cn.hutool.core.codec``, ``com.alibaba.com.caucho.hessian.io``, ``com.alibaba.druid.sql``, ``com.alibaba.fastjson2``, ``com.amazonaws.auth``, ``com.auth0.jwt.algorithms``, ``com.azure.identity``, ``com.caucho.burlap.io``, ``com.caucho.hessian.io``, ``com.cedarsoftware.util.io``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.esotericsoftware.yamlbeans``, ``com.hubspot.jinjava``, ``com.jcraft.jsch``, ``com.microsoft.sqlserver.jdbc``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2``, ``com.sshtools.j2ssh.authentication``, ``com.sun.crypto.provider``, ``com.sun.jndi.ldap``, ``com.sun.net.httpserver``, ``com.sun.net.ssl``, ``com.sun.rowset``, ``com.sun.security.auth.module``, ``com.sun.security.ntlm``, ``com.sun.security.sasl.digest``, ``com.thoughtworks.xstream``, ``com.trilead.ssh2``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``hudson``, ``io.jsonwebtoken``, ``io.undertow.server.handlers.resource``, ``javafx.scene.web``, ``jenkins``, ``jodd.json``, ``liquibase.database.jvm``, ``liquibase.statement.core``, ``net.lingala.zip4j``, ``net.schmizz.sshj``, ``net.sf.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.acegisecurity``, ``org.antlr.runtime``, ``org.apache.avro``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.exec``, ``org.apache.commons.fileupload``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.lang``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.cxf.catalog``, ``org.apache.cxf.common.classloader``, ``org.apache.cxf.common.jaxb``, ``org.apache.cxf.common.logging``, ``org.apache.cxf.configuration.jsse``, ``org.apache.cxf.helpers``, ``org.apache.cxf.resource``, ``org.apache.cxf.staxutils``, ``org.apache.cxf.tools.corba.utils``, ``org.apache.cxf.tools.util``, ``org.apache.cxf.transform``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hadoop.hive.ql.exec``, ``org.apache.hadoop.hive.ql.metadata``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hc.client5.http.protocol``, ``org.apache.hc.client5.http.utils``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.ibatis.mapping``, ``org.apache.log4j``, ``org.apache.shiro.authc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.shiro.mgt``, ``org.apache.sshd.client.session``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.codehaus.cargo.container.installer``, ``org.dom4j``, ``org.exolab.castor.xml``, ``org.fusesource.leveldbjni``, ``org.geogebra.web.full.main``, ``org.gradle.api.file``, ``org.ho.yaml``, ``org.influxdb``, ``org.jabsorb``, ``org.jboss.vfs``, ``org.jdbi.v3.core``, ``org.jenkins.ui.icon``, ``org.jenkins.ui.symbol``, ``org.keycloak.models.map.storage``, ``org.kohsuke.stapler``, ``org.lastaflute.web``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.owasp.esapi``, ``org.pac4j.jwt.config.encryption``, ``org.pac4j.jwt.config.signature``, ``org.scijava.log``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.libs.ws``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``software.amazon.awssdk.transfer.s3.model``, ``sun.jvmstat.perfdata.monitor.protocol.local``, ``sun.jvmstat.perfdata.monitor.protocol.rmi``, ``sun.misc``, ``sun.net.ftp``, ``sun.net.www.protocol.http``, ``sun.security.acl``, ``sun.security.jgss.krb5``, ``sun.security.krb5``, ``sun.security.pkcs``, ``sun.security.pkcs11``, ``sun.security.provider``, ``sun.security.ssl``, ``sun.security.x509``, ``sun.tools.jconsole``",127,6042,775,148,6,14,18,,186 Others,"``actions.osgi``, ``antlr``, ``ch.ethz.ssh2``, ``cn.hutool.core.codec``, ``com.alibaba.com.caucho.hessian.io``, ``com.alibaba.druid.sql``, ``com.alibaba.fastjson2``, ``com.amazonaws.auth``, ``com.auth0.jwt.algorithms``, ``com.azure.identity``, ``com.caucho.burlap.io``, ``com.caucho.hessian.io``, ``com.cedarsoftware.util.io``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.esotericsoftware.yamlbeans``, ``com.hubspot.jinjava``, ``com.jcraft.jsch``, ``com.microsoft.sqlserver.jdbc``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2``, ``com.sshtools.j2ssh.authentication``, ``com.sun.crypto.provider``, ``com.sun.jndi.ldap``, ``com.sun.net.httpserver``, ``com.sun.net.ssl``, ``com.sun.rowset``, ``com.sun.security.auth.module``, ``com.sun.security.ntlm``, ``com.sun.security.sasl.digest``, ``com.thoughtworks.xstream``, ``com.trilead.ssh2``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``hudson``, ``io.jsonwebtoken``, ``io.undertow.server.handlers.resource``, ``javafx.scene.web``, ``jenkins``, ``jodd.json``, ``liquibase.database.jvm``, ``liquibase.statement.core``, ``net.lingala.zip4j``, ``net.schmizz.sshj``, ``net.sf.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.acegisecurity``, ``org.antlr.runtime``, ``org.apache.avro``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.exec``, ``org.apache.commons.fileupload``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.lang``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.cxf.catalog``, ``org.apache.cxf.common.classloader``, ``org.apache.cxf.common.jaxb``, ``org.apache.cxf.common.logging``, ``org.apache.cxf.configuration.jsse``, ``org.apache.cxf.helpers``, ``org.apache.cxf.resource``, ``org.apache.cxf.staxutils``, ``org.apache.cxf.tools.corba.utils``, ``org.apache.cxf.tools.util``, ``org.apache.cxf.transform``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hadoop.hive.ql.exec``, ``org.apache.hadoop.hive.ql.metadata``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.ibatis.mapping``, ``org.apache.log4j``, ``org.apache.shiro.authc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.shiro.mgt``, ``org.apache.sshd.client.session``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.codehaus.cargo.container.installer``, ``org.dom4j``, ``org.exolab.castor.xml``, ``org.fusesource.leveldbjni``, ``org.geogebra.web.full.main``, ``org.gradle.api.file``, ``org.ho.yaml``, ``org.influxdb``, ``org.jabsorb``, ``org.jboss.vfs``, ``org.jdbi.v3.core``, ``org.jenkins.ui.icon``, ``org.jenkins.ui.symbol``, ``org.keycloak.models.map.storage``, ``org.kohsuke.stapler``, ``org.lastaflute.web``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.owasp.esapi``, ``org.pac4j.jwt.config.encryption``, ``org.pac4j.jwt.config.signature``, ``org.scijava.log``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.libs.ws``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``software.amazon.awssdk.transfer.s3.model``, ``sun.jvmstat.perfdata.monitor.protocol.local``, ``sun.jvmstat.perfdata.monitor.protocol.rmi``, ``sun.misc``, ``sun.net.ftp``, ``sun.net.www.protocol.http``, ``sun.security.acl``, ``sun.security.jgss.krb5``, ``sun.security.krb5``, ``sun.security.pkcs``, ``sun.security.pkcs11``, ``sun.security.provider``, ``sun.security.ssl``, ``sun.security.x509``, ``sun.tools.jconsole``",127,6034,775,148,6,14,18,,186
Totals,,382,26411,2707,421,16,137,33,1,415 Totals,,382,26403,2707,421,16,137,33,1,415

View File

@@ -1,4 +0,0 @@
class Test {
public static void main(String[] args) {
}
}

View File

@@ -1 +0,0 @@
fun main() {}

View File

@@ -1,5 +0,0 @@
| file://:0:0:0:0 | | |
| file://:0:0:0:0 | | |
| file://Z:/Test.class:0:0:0:0 | Test | relative |
| file://Z:/test1.java:0:0:0:0 | test1 | relative |
| file://Z:/test2.kt:0:0:0:0 | test2 | relative |

View File

@@ -1,9 +0,0 @@
import java
from File f, string relative
where
not f.getURL().matches("file:///modules/%") and
not f.getURL().matches("file:///!unknown-binary-location/kotlin/%") and
not f.getURL().matches("%/ql/java/kotlin-extractor/%") and
if exists(f.getRelativePath()) then relative = "relative" else relative = ""
select f, relative

View File

@@ -1,7 +0,0 @@
import runs_on
@runs_on.windows
def test(codeql, java, cwd, subst_drive):
drive = subst_drive(cwd / "code")
codeql.database.create(command=["javac test1.java", "kotlinc test2.kt"], source_root=drive)

View File

@@ -1,10 +1,4 @@
extensions: extensions:
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["org.apache.hc.client5.http.protocol", "RedirectLocations", True, "add", "(URI)", "", "Argument[0]", "Argument[this].Element", "value", "hq-manual"]
- addsTo: - addsTo:
pack: codeql/java-all pack: codeql/java-all
extensible: neutralModel extensible: neutralModel

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["org.apache.hc.client5.http.protocol", "RedirectLocations", True, "add", "(URI)", "", "Argument[0]", "Argument[this].Element", "value", "hq-manual"]

View File

@@ -247,8 +247,8 @@ private predicate simpleLocalFlowStep0(Node node1, Node node2, string model) {
or or
cloneStep(node1, node2) and model = "CloneStep" cloneStep(node1, node2) and model = "CloneStep"
or or
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1, node2.(FlowSummaryNode).getSummaryNode(), FlowSummaryImpl::Private::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
true, model) node2.(FlowSummaryNode).getSummaryNode(), true, model)
} }
/** /**

View File

@@ -41,8 +41,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::JavaDataFlow> {
class SinkBase = Void; class SinkBase = Void;
class FlowSummaryCallBase = Void;
predicate neutralElement( predicate neutralElement(
Input::SummarizedCallableBase c, string kind, string provenance, boolean isExact Input::SummarizedCallableBase c, string kind, string provenance, boolean isExact
) { ) {
@@ -146,10 +144,6 @@ private module TypesInput implements Impl::Private::TypesInputSig {
} }
private module StepsInput implements Impl::Private::StepsInputSig { private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable sc) { DataFlowCall getACall(Public::SummarizedCallable sc) {
sc = viableCallable(result).asSummarizedCallable() sc = viableCallable(result).asSummarizedCallable()
} }

View File

@@ -145,8 +145,8 @@ private module Cached {
) )
) )
or or
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, FlowSummaryImpl::Private::Steps::summaryLocalStep(src.(DataFlowPrivate::FlowSummaryNode)
sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model) .getSummaryNode(), sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
} }
/** /**

View File

@@ -234,3 +234,8 @@ subpaths
| use.kt:9:14:9:25 | taint(...) : Closeable | use.kt:9:31:9:36 | it : Closeable | use.kt:9:33:9:34 | it : Closeable | use.kt:9:14:9:36 | use(...) | | use.kt:9:14:9:25 | taint(...) : Closeable | use.kt:9:31:9:36 | it : Closeable | use.kt:9:33:9:34 | it : Closeable | use.kt:9:14:9:36 | use(...) |
| with.kt:7:19:7:30 | taint(...) : String | with.kt:7:33:7:40 | $this$with : String | with.kt:7:35:7:38 | this : String | with.kt:7:14:7:40 | with(...) | | with.kt:7:19:7:30 | taint(...) : String | with.kt:7:33:7:40 | $this$with : String | with.kt:7:35:7:38 | this : String | with.kt:7:14:7:40 | with(...) |
testFailures testFailures
| test.kt:28:14:28:21 | getSecond(...) | Unexpected result: hasTaintFlow=a |
| test.kt:35:14:35:27 | component1(...) | Unexpected result: hasTaintFlow=d |
| test.kt:41:14:41:22 | getSecond(...) | Unexpected result: hasTaintFlow=e |
| test.kt:53:14:53:24 | getDuration(...) | Unexpected result: hasTaintFlow=f |
| test.kt:58:14:58:29 | component2(...) | Unexpected result: hasTaintFlow=g |

View File

@@ -25,20 +25,20 @@ class Test {
val p = Pair(taint("a"), "") val p = Pair(taint("a"), "")
sink(p) // $ hasTaintFlow=a sink(p) // $ hasTaintFlow=a
sink(p.component1()) // $ hasTaintFlow=a sink(p.component1()) // $ hasTaintFlow=a
sink(p.second) // $ SPURIOUS: hasTaintFlow=a sink(p.second)
sink(taint("b").capitalize()) // $ hasTaintFlow=b sink(taint("b").capitalize()) // $ hasTaintFlow=b
sink(taint("c").replaceFirstChar { _ -> 'x' }) // $ hasTaintFlow=c sink(taint("c").replaceFirstChar { _ -> 'x' }) // $ hasTaintFlow=c
val t = Triple("", taint("d"), "") val t = Triple("", taint("d"), "")
sink(t) // $ hasTaintFlow=d sink(t) // $ hasTaintFlow=d
sink(t.component1()) // $ SPURIOUS: hasTaintFlow=d sink(t.component1())
sink(t.second) // $ hasTaintFlow=d sink(t.second) // $ hasTaintFlow=d
val p1 = taint("e") to "" val p1 = taint("e") to ""
sink(p1) // $ hasTaintFlow=e sink(p1) // $ hasTaintFlow=e
sink(p1.component1()) // $ hasTaintFlow=e sink(p1.component1()) // $ hasTaintFlow=e
sink(p1.second) // $ SPURIOUS: hasTaintFlow=e sink(p1.second)
val l = p.toList() val l = p.toList()
sink(l) // $ hasTaintFlow=a sink(l) // $ hasTaintFlow=a
@@ -50,12 +50,12 @@ class Test {
val tv = TimedValue(taint("f"), Duration.parse("")) val tv = TimedValue(taint("f"), Duration.parse(""))
sink(tv) // $ hasTaintFlow=f sink(tv) // $ hasTaintFlow=f
sink(tv.component1()) // $ hasTaintFlow=f sink(tv.component1()) // $ hasTaintFlow=f
sink(tv.duration) // $ SPURIOUS: hasTaintFlow=f sink(tv.duration)
val mg0 = MatchGroup(taint("g"), IntRange(0, 10)) val mg0 = MatchGroup(taint("g"), IntRange(0, 10))
sink(mg0) // $ hasTaintFlow=g sink(mg0) // $ hasTaintFlow=g
sink(mg0.value) // $ hasTaintFlow=g sink(mg0.value) // $ hasTaintFlow=g
sink(mg0.component2()) // $ SPURIOUS: hasTaintFlow=g sink(mg0.component2())
val iv = IndexedValue<String>(5, taint("h")) val iv = IndexedValue<String>(5, taint("h"))
sink(iv) // $ hasTaintFlow=h sink(iv) // $ hasTaintFlow=h

View File

@@ -234,3 +234,8 @@ subpaths
| use.kt:9:14:9:25 | taint(...) : Closeable | use.kt:9:31:9:36 | it : Closeable | use.kt:9:33:9:34 | it : Closeable | use.kt:9:14:9:36 | use(...) | | use.kt:9:14:9:25 | taint(...) : Closeable | use.kt:9:31:9:36 | it : Closeable | use.kt:9:33:9:34 | it : Closeable | use.kt:9:14:9:36 | use(...) |
| with.kt:7:19:7:30 | taint(...) : String | with.kt:7:33:7:40 | $this$with : String | with.kt:7:35:7:38 | this : String | with.kt:7:14:7:40 | with(...) | | with.kt:7:19:7:30 | taint(...) : String | with.kt:7:33:7:40 | $this$with : String | with.kt:7:35:7:38 | this : String | with.kt:7:14:7:40 | with(...) |
testFailures testFailures
| test.kt:28:14:28:21 | getSecond(...) | Unexpected result: hasTaintFlow=a |
| test.kt:35:14:35:27 | component1(...) | Unexpected result: hasTaintFlow=d |
| test.kt:41:14:41:22 | getSecond(...) | Unexpected result: hasTaintFlow=e |
| test.kt:53:14:53:24 | getDuration(...) | Unexpected result: hasTaintFlow=f |
| test.kt:58:14:58:29 | component2(...) | Unexpected result: hasTaintFlow=g |

View File

@@ -25,20 +25,20 @@ class Test {
val p = Pair(taint("a"), "") val p = Pair(taint("a"), "")
sink(p) // $ hasTaintFlow=a sink(p) // $ hasTaintFlow=a
sink(p.component1()) // $ hasTaintFlow=a sink(p.component1()) // $ hasTaintFlow=a
sink(p.second) // $ SPURIOUS: hasTaintFlow=a sink(p.second)
sink(taint("b").capitalize()) // $ hasTaintFlow=b sink(taint("b").capitalize()) // $ hasTaintFlow=b
sink(taint("c").replaceFirstChar { _ -> 'x' }) // $ hasTaintFlow=c sink(taint("c").replaceFirstChar { _ -> 'x' }) // $ hasTaintFlow=c
val t = Triple("", taint("d"), "") val t = Triple("", taint("d"), "")
sink(t) // $ hasTaintFlow=d sink(t) // $ hasTaintFlow=d
sink(t.component1()) // $ SPURIOUS: hasTaintFlow=d sink(t.component1())
sink(t.second) // $ hasTaintFlow=d sink(t.second) // $ hasTaintFlow=d
val p1 = taint("e") to "" val p1 = taint("e") to ""
sink(p1) // $ hasTaintFlow=e sink(p1) // $ hasTaintFlow=e
sink(p1.component1()) // $ hasTaintFlow=e sink(p1.component1()) // $ hasTaintFlow=e
sink(p1.second) // $ SPURIOUS: hasTaintFlow=e sink(p1.second)
val l = p.toList() val l = p.toList()
sink(l) // $ hasTaintFlow=a sink(l) // $ hasTaintFlow=a
@@ -50,12 +50,12 @@ class Test {
val tv = TimedValue(taint("f"), Duration.parse("")) val tv = TimedValue(taint("f"), Duration.parse(""))
sink(tv) // $ hasTaintFlow=f sink(tv) // $ hasTaintFlow=f
sink(tv.component1()) // $ hasTaintFlow=f sink(tv.component1()) // $ hasTaintFlow=f
sink(tv.duration) // $ SPURIOUS: hasTaintFlow=f sink(tv.duration)
val mg0 = MatchGroup(taint("g"), IntRange(0, 10)) val mg0 = MatchGroup(taint("g"), IntRange(0, 10))
sink(mg0) // $ hasTaintFlow=g sink(mg0) // $ hasTaintFlow=g
sink(mg0.value) // $ hasTaintFlow=g sink(mg0.value) // $ hasTaintFlow=g
sink(mg0.component2()) // $ SPURIOUS: hasTaintFlow=g sink(mg0.component2())
val iv = IndexedValue<String>(5, taint("h")) val iv = IndexedValue<String>(5, taint("h"))
sink(iv) // $ hasTaintFlow=h sink(iv) // $ hasTaintFlow=h

View File

@@ -13,7 +13,8 @@ predicate taintFlowUpdate(DataFlow::ParameterNode p1, DataFlow::ParameterNode p2
} }
predicate summaryStep(FlowSummaryNode src, FlowSummaryNode sink) { predicate summaryStep(FlowSummaryNode src, FlowSummaryNode sink) {
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink.getSummaryNode(), false, _) or FlowSummaryImpl::Private::Steps::summaryLocalStep(src.getSummaryNode(), sink.getSummaryNode(),
false, _) or
FlowSummaryImpl::Private::Steps::summaryReadStep(src.getSummaryNode(), _, sink.getSummaryNode()) or FlowSummaryImpl::Private::Steps::summaryReadStep(src.getSummaryNode(), _, sink.getSummaryNode()) or
FlowSummaryImpl::Private::Steps::summaryStoreStep(src.getSummaryNode(), _, sink.getSummaryNode()) FlowSummaryImpl::Private::Steps::summaryStoreStep(src.getSummaryNode(), _, sink.getSummaryNode())
} }

View File

@@ -1 +0,0 @@
function interesting() { }

View File

@@ -1,2 +0,0 @@
| file://Z:/main.js:0:0:0:0 | Z:/main.js | relative |
| file://Z:/test.ts:0:0:0:0 | Z:/test.ts | relative |

View File

@@ -1,7 +0,0 @@
import javascript
from File f, string relative
where
not f.getURL().matches("%/target/intree/%") and
if exists(f.getRelativePath()) then relative = "relative" else relative = ""
select f, relative

View File

@@ -1,7 +0,0 @@
import runs_on
@runs_on.windows
def test(codeql, javascript, cwd, subst_drive):
drive = subst_drive(cwd / "code")
codeql.database.create(source_root=drive)

View File

@@ -1212,8 +1212,8 @@ private predicate valuePreservingStep(Node node1, Node node2) {
or or
node2 = FlowSteps::getThrowTarget(node1) node2 = FlowSteps::getThrowTarget(node1)
or or
FlowSummaryPrivate::Steps::summaryLocalStep(node1, node2.(FlowSummaryNode).getSummaryNode(), true, FlowSummaryPrivate::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
_) // TODO: preserve 'model' node2.(FlowSummaryNode).getSummaryNode(), true, _) // TODO: preserve 'model'
} }
predicate knownSourceModel(Node sink, string model) { none() } predicate knownSourceModel(Node sink, string model) { none() }

View File

@@ -142,10 +142,6 @@ string encodeArgumentPosition(ArgumentPosition pos) {
ReturnKind getStandardReturnValueKind() { result = MkNormalReturnKind() and Stage::ref() } ReturnKind getStandardReturnValueKind() { result = MkNormalReturnKind() and Stage::ref() }
private module FlowSummaryStepInput implements Private::StepsInputSig { private module FlowSummaryStepInput implements Private::StepsInputSig {
Private::SummaryNode getSummaryNode(DataFlow::Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
overlay[global] overlay[global]
DataFlowCall getACall(SummarizedCallable sc) { DataFlowCall getACall(SummarizedCallable sc) {
exists(LibraryCallable callable | callable = sc | exists(LibraryCallable callable | callable = sc |

View File

@@ -12,8 +12,8 @@ cached
predicate defaultAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { predicate defaultAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
TaintTracking::AdditionalTaintStep::step(node1, node2) TaintTracking::AdditionalTaintStep::step(node1, node2)
or or
FlowSummaryPrivate::Steps::summaryLocalStep(node1, node2.(FlowSummaryNode).getSummaryNode(), FlowSummaryPrivate::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
false, _) // TODO: preserve 'model' parameter node2.(FlowSummaryNode).getSummaryNode(), false, _) // TODO: preserve 'model' parameter
or or
// Convert steps out of array elements to plain taint steps // Convert steps out of array elements to plain taint steps
FlowSummaryPrivate::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), FlowSummaryPrivate::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(),

View File

@@ -3,7 +3,6 @@ private import DataFlowImplSpecific
private import codeql.dataflow.DataFlow as SharedDataFlow private import codeql.dataflow.DataFlow as SharedDataFlow
private import codeql.dataflow.TaintTracking as SharedTaintTracking private import codeql.dataflow.TaintTracking as SharedTaintTracking
private import codeql.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import codeql.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import codeql.util.Void
module JSDataFlow implements SharedDataFlow::InputSig<Location> { module JSDataFlow implements SharedDataFlow::InputSig<Location> {
import Private import Private
@@ -29,8 +28,6 @@ module JSFlowSummary implements FlowSummaryImpl::InputSig<Location, JSDataFlow>
private import semmle.javascript.dataflow.internal.FlowSummaryPrivate as FlowSummaryPrivate private import semmle.javascript.dataflow.internal.FlowSummaryPrivate as FlowSummaryPrivate
import FlowSummaryPrivate import FlowSummaryPrivate
class FlowSummaryCallBase = Void;
overlay[local] overlay[local]
predicate callableFromSource(SummarizedCallableBase c) { none() } predicate callableFromSource(SummarizedCallableBase c) { none() }

View File

@@ -36,8 +36,6 @@ private module Input implements InputSig<Location, PythonDataFlow> {
// parameter, but dataflow-consistency queries should _not_ complain about there not // parameter, but dataflow-consistency queries should _not_ complain about there not
// being a post-update node for the synthetic `**kwargs` parameter. // being a post-update node for the synthetic `**kwargs` parameter.
n instanceof SynthDictSplatParameterNode n instanceof SynthDictSplatParameterNode
or
Private::Conversions::readStep(n, _, _)
} }
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) { predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {

View File

@@ -54,7 +54,6 @@ ql/python/ql/src/Metrics/NumberOfStatements.ql
ql/python/ql/src/Metrics/TransitiveImports.ql ql/python/ql/src/Metrics/TransitiveImports.ql
ql/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql ql/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql
ql/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql ql/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql
ql/python/ql/src/Security/CWE-1427/UserPromptInjection.ql
ql/python/ql/src/Security/CWE-798/HardcodedCredentials.ql ql/python/ql/src/Security/CWE-798/HardcodedCredentials.ql
ql/python/ql/src/Statements/C_StyleParentheses.ql ql/python/ql/src/Statements/C_StyleParentheses.ql
ql/python/ql/src/Statements/DocStrings.ql ql/python/ql/src/Statements/DocStrings.ql
@@ -88,6 +87,7 @@ ql/python/ql/src/experimental/Security/CWE-079/EmailXss.ql
ql/python/ql/src/experimental/Security/CWE-091/XsltInjection.ql ql/python/ql/src/experimental/Security/CWE-091/XsltInjection.ql
ql/python/ql/src/experimental/Security/CWE-094/Js2Py.ql ql/python/ql/src/experimental/Security/CWE-094/Js2Py.ql
ql/python/ql/src/experimental/Security/CWE-1236/CsvInjection.ql ql/python/ql/src/experimental/Security/CWE-1236/CsvInjection.ql
ql/python/ql/src/experimental/Security/CWE-1427/PromptInjection.ql
ql/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql ql/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql
ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql

View File

@@ -17,7 +17,6 @@ ql/python/ql/src/Security/CWE-1004/NonHttpOnlyCookie.ql
ql/python/ql/src/Security/CWE-113/HeaderInjection.ql ql/python/ql/src/Security/CWE-113/HeaderInjection.ql
ql/python/ql/src/Security/CWE-116/BadTagFilter.ql ql/python/ql/src/Security/CWE-116/BadTagFilter.ql
ql/python/ql/src/Security/CWE-1275/SameSiteNoneCookie.ql ql/python/ql/src/Security/CWE-1275/SameSiteNoneCookie.ql
ql/python/ql/src/Security/CWE-1427/SystemPromptInjection.ql
ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql
ql/python/ql/src/Security/CWE-215/FlaskDebug.ql ql/python/ql/src/Security/CWE-215/FlaskDebug.ql
ql/python/ql/src/Security/CWE-285/PamAuthorization.ql ql/python/ql/src/Security/CWE-285/PamAuthorization.ql

View File

@@ -111,7 +111,6 @@ ql/python/ql/src/Security/CWE-113/HeaderInjection.ql
ql/python/ql/src/Security/CWE-116/BadTagFilter.ql ql/python/ql/src/Security/CWE-116/BadTagFilter.ql
ql/python/ql/src/Security/CWE-117/LogInjection.ql ql/python/ql/src/Security/CWE-117/LogInjection.ql
ql/python/ql/src/Security/CWE-1275/SameSiteNoneCookie.ql ql/python/ql/src/Security/CWE-1275/SameSiteNoneCookie.ql
ql/python/ql/src/Security/CWE-1427/SystemPromptInjection.ql
ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql
ql/python/ql/src/Security/CWE-215/FlaskDebug.ql ql/python/ql/src/Security/CWE-215/FlaskDebug.ql
ql/python/ql/src/Security/CWE-285/PamAuthorization.ql ql/python/ql/src/Security/CWE-285/PamAuthorization.ql

View File

@@ -21,7 +21,6 @@ ql/python/ql/src/Security/CWE-113/HeaderInjection.ql
ql/python/ql/src/Security/CWE-116/BadTagFilter.ql ql/python/ql/src/Security/CWE-116/BadTagFilter.ql
ql/python/ql/src/Security/CWE-117/LogInjection.ql ql/python/ql/src/Security/CWE-117/LogInjection.ql
ql/python/ql/src/Security/CWE-1275/SameSiteNoneCookie.ql ql/python/ql/src/Security/CWE-1275/SameSiteNoneCookie.ql
ql/python/ql/src/Security/CWE-1427/SystemPromptInjection.ql
ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql
ql/python/ql/src/Security/CWE-215/FlaskDebug.ql ql/python/ql/src/Security/CWE-215/FlaskDebug.ql
ql/python/ql/src/Security/CWE-285/PamAuthorization.ql ql/python/ql/src/Security/CWE-285/PamAuthorization.ql

View File

@@ -1 +0,0 @@
print(0)

View File

@@ -1 +0,0 @@
| code/main.py:0:0:0:0 | code/main.py | |

View File

@@ -1,5 +0,0 @@
import python
from File f, string relative
where if exists(f.getRelativePath()) then relative = "relative" else relative = ""
select f, relative

View File

@@ -1,7 +0,0 @@
import runs_on
@runs_on.windows
def test(codeql, python, cwd, subst_drive):
drive = subst_drive(cwd / "code")
codeql.database.create(source_root=drive)

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added prompt-injection sink models (`system-prompt-injection` and `user-prompt-injection` kinds) for the `openai`, `agents`, `anthropic`, `google-genai`, `openrouter` and `langchain` frameworks.

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
- Temporarily disabled the `instanceFieldStep` disjunct of the internal `TypeTrackingInput::levelStepCall` predicate, which was introduced in 7.2.0 and caused catastrophic query slowdowns on some OOP-heavy Python codebases (e.g. `mypy` and `dask`).

View File

@@ -1794,28 +1794,3 @@ module Cryptography {
import ConceptsShared::Cryptography import ConceptsShared::Cryptography
} }
/**
* A data-flow node that prompts an AI model.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `AIPrompt::Range` instead.
*/
class AIPrompt extends DataFlow::Node instanceof AIPrompt::Range {
/** Gets an input that is used as AI prompt. */
DataFlow::Node getAPrompt() { result = super.getAPrompt() }
}
/** Provides a class for modeling new AI prompting mechanisms. */
module AIPrompt {
/**
* A data-flow node that prompts an AI model.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `AIPrompt` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets an input that is used as AI prompt. */
abstract DataFlow::Node getAPrompt();
}
}

View File

@@ -529,7 +529,7 @@ predicate simpleLocalFlowStepForTypetracking(Node nodeFrom, Node nodeTo) {
} }
private predicate summaryLocalStep(Node nodeFrom, Node nodeTo, string model) { private predicate summaryLocalStep(Node nodeFrom, Node nodeTo, string model) {
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model) nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
} }
@@ -753,7 +753,7 @@ predicate jumpStepNotSharedWithTypeTracker(Node nodeFrom, Node nodeTo) {
* As of 2024-04-02 the type-tracking library only supports precise content, so there is * As of 2024-04-02 the type-tracking library only supports precise content, so there is
* no reason to include steps for list content right now. * no reason to include steps for list content right now.
*/ */
predicate storeStepCommon(Node nodeFrom, Content c, Node nodeTo) { predicate storeStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
tupleStoreStep(nodeFrom, c, nodeTo) tupleStoreStep(nodeFrom, c, nodeTo)
or or
dictStoreStep(nodeFrom, c, nodeTo) dictStoreStep(nodeFrom, c, nodeTo)
@@ -767,8 +767,7 @@ predicate storeStepCommon(Node nodeFrom, Content c, Node nodeTo) {
* Holds if data can flow from `nodeFrom` to `nodeTo` via an assignment to * Holds if data can flow from `nodeFrom` to `nodeTo` via an assignment to
* content `c`. * content `c`.
*/ */
predicate storeStep(Node nodeFrom, ContentSet cs, Node nodeTo) { predicate storeStep(Node nodeFrom, ContentSet c, Node nodeTo) {
exists(Content c | cs = singleton(c) |
storeStepCommon(nodeFrom, c, nodeTo) storeStepCommon(nodeFrom, c, nodeTo)
or or
listStoreStep(nodeFrom, c, nodeTo) listStoreStep(nodeFrom, c, nodeTo)
@@ -781,6 +780,9 @@ predicate storeStep(Node nodeFrom, ContentSet cs, Node nodeTo) {
or or
any(Orm::AdditionalOrmSteps es).storeStep(nodeFrom, c, nodeTo) any(Orm::AdditionalOrmSteps es).storeStep(nodeFrom, c, nodeTo)
or or
FlowSummaryImpl::Private::Steps::summaryStoreStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), c,
nodeTo.(FlowSummaryNode).getSummaryNode())
or
synthStarArgsElementParameterNodeStoreStep(nodeFrom, c, nodeTo) synthStarArgsElementParameterNodeStoreStep(nodeFrom, c, nodeTo)
or or
synthDictSplatArgumentNodeStoreStep(nodeFrom, c, nodeTo) synthDictSplatArgumentNodeStoreStep(nodeFrom, c, nodeTo)
@@ -788,10 +790,6 @@ predicate storeStep(Node nodeFrom, ContentSet cs, Node nodeTo) {
yieldStoreStep(nodeFrom, c, nodeTo) yieldStoreStep(nodeFrom, c, nodeTo)
or or
VariableCapture::storeStep(nodeFrom, c, nodeTo) VariableCapture::storeStep(nodeFrom, c, nodeTo)
)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), cs,
nodeTo.(FlowSummaryNode).getSummaryNode())
} }
/** /**
@@ -987,7 +985,7 @@ predicate attributeStoreStep(Node nodeFrom, AttributeContent c, Node nodeTo) {
/** /**
* Subset of `readStep` that should be shared with type-tracking. * Subset of `readStep` that should be shared with type-tracking.
*/ */
predicate readStepCommon(Node nodeFrom, Content c, Node nodeTo) { predicate readStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
subscriptReadStep(nodeFrom, c, nodeTo) subscriptReadStep(nodeFrom, c, nodeTo)
or or
iterableUnpackingReadStep(nodeFrom, c, nodeTo) iterableUnpackingReadStep(nodeFrom, c, nodeTo)
@@ -996,8 +994,7 @@ predicate readStepCommon(Node nodeFrom, Content c, Node nodeTo) {
/** /**
* Holds if data can flow from `nodeFrom` to `nodeTo` via a read of content `c`. * Holds if data can flow from `nodeFrom` to `nodeTo` via a read of content `c`.
*/ */
predicate readStep(Node nodeFrom, ContentSet cs, Node nodeTo) { predicate readStep(Node nodeFrom, ContentSet c, Node nodeTo) {
exists(Content c | cs = singleton(c) |
readStepCommon(nodeFrom, c, nodeTo) readStepCommon(nodeFrom, c, nodeTo)
or or
matchReadStep(nodeFrom, c, nodeTo) matchReadStep(nodeFrom, c, nodeTo)
@@ -1006,15 +1003,12 @@ predicate readStep(Node nodeFrom, ContentSet cs, Node nodeTo) {
or or
attributeReadStep(nodeFrom, c, nodeTo) attributeReadStep(nodeFrom, c, nodeTo)
or or
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), c,
nodeTo.(FlowSummaryNode).getSummaryNode())
or
synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo) synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo)
or or
VariableCapture::readStep(nodeFrom, c, nodeTo) VariableCapture::readStep(nodeFrom, c, nodeTo)
)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), cs,
nodeTo.(FlowSummaryNode).getSummaryNode())
or
Conversions::readStep(nodeFrom, cs, nodeTo)
} }
/** Data flows from a sequence to a subscript of the sequence. */ /** Data flows from a sequence to a subscript of the sequence. */
@@ -1070,77 +1064,30 @@ predicate attributeReadStep(Node nodeFrom, AttributeContent c, AttrRead nodeTo)
nodeTo.accesses(nodeFrom, c.getAttribute()) nodeTo.accesses(nodeFrom, c.getAttribute())
} }
module Conversions {
private import semmle.python.Concepts
predicate decoderReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
exists(Decoding decoding |
nodeFrom = decoding.getAnInput() and
nodeTo = decoding.getOutput()
) and
c.isAnyTupleOrDictionaryElement()
}
predicate encoderReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
exists(Encoding encoding |
nodeFrom = encoding.getAnInput() and
nodeTo = encoding.getOutput()
) and
c.isAnyTupleOrDictionaryElement()
}
predicate formatReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
// % formatting
exists(BinaryExprNode fmt | fmt = nodeTo.asCfgNode() |
fmt.getOp() instanceof Mod and
fmt.getRight() = nodeFrom.asCfgNode()
) and
c.isAnyTupleElement()
or
// format_map
// see https://docs.python.org/3/library/stdtypes.html#str.format_map
nodeTo.(MethodCallNode).calls(_, "format_map") and
nodeTo.(MethodCallNode).getArg(0) = nodeFrom and
c.isAnyDictionaryElement()
}
predicate readStep(Node nodeFrom, ContentSet c, Node nodeTo) {
decoderReadStep(nodeFrom, c, nodeTo)
or
encoderReadStep(nodeFrom, c, nodeTo)
or
formatReadStep(nodeFrom, c, nodeTo)
}
}
/** /**
* Holds if values stored inside content `c` are cleared at node `n`. For example, * Holds if values stored inside content `c` are cleared at node `n`. For example,
* any value stored inside `f` is cleared at the pre-update node associated with `x` * any value stored inside `f` is cleared at the pre-update node associated with `x`
* in `x.f = newValue`. * in `x.f = newValue`.
*/ */
predicate clearsContent(Node n, ContentSet cs) { predicate clearsContent(Node n, ContentSet c) {
exists(Content c | cs = singleton(c) |
matchClearStep(n, c) matchClearStep(n, c)
or or
attributeClearStep(n, c) attributeClearStep(n, c)
or or
dictClearStep(n, c) dictClearStep(n, c)
or or
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
or
dictSplatParameterNodeClearStep(n, c) dictSplatParameterNodeClearStep(n, c)
or or
VariableCapture::clearsContent(n, c) VariableCapture::clearsContent(n, c)
)
or
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), cs)
} }
/** /**
* Holds if the value that is being tracked is expected to be stored inside content `c` * Holds if the value that is being tracked is expected to be stored inside content `c`
* at node `n`. * at node `n`.
*/ */
predicate expectsContent(Node n, ContentSet c) { predicate expectsContent(Node n, ContentSet c) { none() }
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
}
/** /**
* Holds if values stored inside attribute `c` are cleared at node `n`. * Holds if values stored inside attribute `c` are cleared at node `n`.
@@ -1251,65 +1198,12 @@ predicate allowParameterReturnInSelf(ParameterNode p) {
) )
} }
bindingset[s]
private string getFirstChar(string s) {
result =
min(int i, string c |
c = s.charAt(i) and c != "_"
or
c = "" and i = s.length()
|
c order by i
)
}
private string getAttributeContentFirstChar(AttributeContent ac) {
result = getFirstChar(ac.getAttribute())
}
private string getDictionaryElementContentKeyFirstChar(DictionaryElementContent dec) {
result = getFirstChar(dec.getKey())
}
private newtype TContentApprox =
TListElementContentApprox() or
TSetElementContentApprox() or
TTupleElementContentApprox() or
TDictionaryElementContentApprox(string first) {
first = "" // for `TDictionaryElementAnyContent`
or
first = getDictionaryElementContentKeyFirstChar(_)
} or
TAttributeContentApprox(string first) { first = getAttributeContentFirstChar(_) } or
TCapturedVariableContentApprox()
/** An approximated `Content`. */ /** An approximated `Content`. */
class ContentApprox extends TContentApprox { class ContentApprox = Unit;
/** Gets a textual representation of this element. */
string toString() { result = "" }
}
/** Gets an approximated value for content `c`. */ /** Gets an approximated value for content `c`. */
ContentApprox getContentApprox(Content c) { pragma[inline]
c = TListElementContent() and ContentApprox getContentApprox(Content c) { any() }
result = TListElementContentApprox()
or
c = TSetElementContent() and
result = TSetElementContentApprox()
or
c = TTupleElementContent(_) and
result = TTupleElementContentApprox()
or
result = TDictionaryElementContentApprox(getDictionaryElementContentKeyFirstChar(c))
or
c = TDictionaryElementAnyContent() and
result = TDictionaryElementContentApprox("")
or
result = TAttributeContentApprox(getAttributeContentFirstChar(c))
or
c = TCapturedVariableContent(_) and
result = TCapturedVariableContentApprox()
}
/** Helper for `.getEnclosingCallable`. */ /** Helper for `.getEnclosingCallable`. */
DataFlowCallable getCallableScope(Scope s) { DataFlowCallable getCallableScope(Scope s) {

View File

@@ -898,78 +898,19 @@ class CapturedVariableContent extends Content, TCapturedVariableContent {
override string getMaDRepresentation() { none() } override string getMaDRepresentation() { none() }
} }
/**
* An entity that represents a set of `Content`s.
*
* Most `ContentSet`s are singletons (i.e. they consist of a single `Content`),
* but `AnyDictionaryElement` and `AnyTupleElement` act as wildcards on the
* read side: a read at such a `ContentSet` matches any specific dictionary
* key / tuple index store, as well as (for dictionaries) the
* "unknown-bucket" Content `DictionaryElementAnyContent`.
*
* Keeping these as wildcard `ContentSet`s (rather than enumerating one
* `ContentSet` per key/index) keeps the dataflow `readSetEx` relation small
* when implicit reads are used (e.g. at sinks via `defaultImplicitTaintRead`).
*/
private newtype TContentSet =
TSingletonContent(Content c) or
TAnyTupleElement() or
TAnyDictionaryElement() or
TAnyTupleOrDictionaryElement()
/** /**
* An entity that represents a set of `Content`s. * An entity that represents a set of `Content`s.
* *
* The set may be interpreted differently depending on whether it is * The set may be interpreted differently depending on whether it is
* stored into (`getAStoreContent`) or read from (`getAReadContent`). * stored into (`getAStoreContent`) or read from (`getAReadContent`).
*/ */
class ContentSet extends TContentSet { class ContentSet instanceof Content {
/** Holds if this content set is the singleton `{c}`. */
predicate isSingleton(Content c) { this = TSingletonContent(c) }
/** Holds if this content set is the wildcard for all tuple elements. */
predicate isAnyTupleElement() { this = TAnyTupleElement() }
/** Holds if this content set is the wildcard for all dictionary elements. */
predicate isAnyDictionaryElement() { this = TAnyDictionaryElement() }
/** Holds if this content set is the wildcard for all tuple elements or dictionary elements. */
predicate isAnyTupleOrDictionaryElement() { this = TAnyTupleOrDictionaryElement() }
/** Gets a content that may be stored into when storing into this set. */ /** Gets a content that may be stored into when storing into this set. */
Content getAStoreContent() { this = TSingletonContent(result) } Content getAStoreContent() { result = this }
/** Gets a content that may be read from when reading from this set. */ /** Gets a content that may be read from when reading from this set. */
Content getAReadContent() { Content getAReadContent() { result = this }
this = TSingletonContent(result)
or
// Wildcard expansion: a read at "any tuple element" matches a store at any
// specific tuple index. (Stores always target a specific index, so we don't
// need a `TupleElementAnyContent` Content kind here.)
this = TAnyTupleElement() and result instanceof TupleElementContent
or
this = TAnyDictionaryElement() and
(result instanceof DictionaryElementContent or result instanceof DictionaryElementAnyContent)
or
this = TAnyTupleOrDictionaryElement() and
(
result instanceof TupleElementContent or
result instanceof DictionaryElementContent or
result instanceof DictionaryElementAnyContent
)
}
/** Gets a textual representation of this content set. */ /** Gets a textual representation of this content set. */
string toString() { string toString() { result = super.toString() }
exists(Content c | this = TSingletonContent(c) | result = c.toString())
or
this = TAnyTupleElement() and result = "Any tuple element"
or
this = TAnyDictionaryElement() and result = "Any dictionary element"
or
this = TAnyTupleOrDictionaryElement() and result = "Any tuple or dictionary element"
} }
}
/** Gets the singleton `ContentSet` wrapping the `Content` `c`. */
ContentSet singleton(Content c) { result = TSingletonContent(c) }

View File

@@ -20,8 +20,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
class SinkBase = Void; class SinkBase = Void;
class FlowSummaryCallBase = Void;
predicate callableFromSource(SummarizedCallableBase c) { none() } predicate callableFromSource(SummarizedCallableBase c) { none() }
ArgumentPosition callbackSelfParameterPosition() { result.isLambdaSelf() } ArgumentPosition callbackSelfParameterPosition() { result.isLambdaSelf() }
@@ -68,33 +66,23 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
} }
string encodeContent(ContentSet cs, string arg) { string encodeContent(ContentSet cs, string arg) {
exists(Content c | cs.isSingleton(c) | cs = TListElementContent() and result = "ListElement" and arg = ""
c = TListElementContent() and result = "ListElement" and arg = ""
or or
c = TSetElementContent() and result = "SetElement" and arg = "" cs = TSetElementContent() and result = "SetElement" and arg = ""
or or
exists(int index | exists(int index |
c = TTupleElementContent(index) and result = "TupleElement" and arg = index.toString() cs = TTupleElementContent(index) and result = "TupleElement" and arg = index.toString()
) )
or or
exists(string key | exists(string key |
c = TDictionaryElementContent(key) and result = "DictionaryElement" and arg = key cs = TDictionaryElementContent(key) and result = "DictionaryElement" and arg = key
) )
or or
c = TDictionaryElementAnyContent() and result = "DictionaryElementAny" and arg = "" cs = TDictionaryElementAnyContent() and result = "DictionaryElementAny" and arg = ""
or or
exists(string attr | c = TAttributeContent(attr) and result = "Attribute" and arg = attr) exists(string attr | cs = TAttributeContent(attr) and result = "Attribute" and arg = attr)
)
or
cs.isAnyTupleElement() and result = "AnyTupleElement" and arg = ""
or
cs.isAnyDictionaryElement() and result = "AnyDictionaryElement" and arg = ""
or
cs.isAnyTupleOrDictionaryElement() and result = "AnyTupleOrDictionaryElement" and arg = ""
} }
string encodeWithContent(ContentSet c, string arg) { result = "With" + encodeContent(c, arg) }
bindingset[token] bindingset[token]
ParameterPosition decodeUnknownParameterPosition(AccessPath::AccessPathTokenBase token) { ParameterPosition decodeUnknownParameterPosition(AccessPath::AccessPathTokenBase token) {
// needed to support `Argument[x..y]` ranges // needed to support `Argument[x..y]` ranges
@@ -113,10 +101,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
private import Make<Location, DataFlowImplSpecific::PythonDataFlow, Input> as Impl private import Make<Location, DataFlowImplSpecific::PythonDataFlow, Input> as Impl
private module StepsInput implements Impl::Private::StepsInputSig { private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
overlay[global] overlay[global]
DataFlowCall getACall(Public::SummarizedCallable sc) { DataFlowCall getACall(Public::SummarizedCallable sc) {
result = result =
@@ -155,29 +139,27 @@ module Private {
predicate withContent = SC::withContent/1; predicate withContent = SC::withContent/1;
/** Gets a summary component that represents a list element. */ /** Gets a summary component that represents a list element. */
SummaryComponent listElement() { result = content(singleton(any(ListElementContent c))) } SummaryComponent listElement() { result = content(any(ListElementContent c)) }
/** Gets a summary component that represents a set element. */ /** Gets a summary component that represents a set element. */
SummaryComponent setElement() { result = content(singleton(any(SetElementContent c))) } SummaryComponent setElement() { result = content(any(SetElementContent c)) }
/** Gets a summary component that represents a tuple element. */ /** Gets a summary component that represents a tuple element. */
SummaryComponent tupleElement(int index) { SummaryComponent tupleElement(int index) {
exists(TupleElementContent c | c.getIndex() = index and result = content(singleton(c))) exists(TupleElementContent c | c.getIndex() = index and result = content(c))
} }
/** Gets a summary component that represents a dictionary element. */ /** Gets a summary component that represents a dictionary element. */
SummaryComponent dictionaryElement(string key) { SummaryComponent dictionaryElement(string key) {
exists(DictionaryElementContent c | c.getKey() = key and result = content(singleton(c))) exists(DictionaryElementContent c | c.getKey() = key and result = content(c))
} }
/** Gets a summary component that represents a dictionary element at any key. */ /** Gets a summary component that represents a dictionary element at any key. */
SummaryComponent dictionaryElementAny() { SummaryComponent dictionaryElementAny() { result = content(any(DictionaryElementAnyContent c)) }
result = content(singleton(any(DictionaryElementAnyContent c)))
}
/** Gets a summary component that represents an attribute element. */ /** Gets a summary component that represents an attribute element. */
SummaryComponent attribute(string attr) { SummaryComponent attribute(string attr) {
exists(AttributeContent c | c.getAttribute() = attr and result = content(singleton(c))) exists(AttributeContent c | c.getAttribute() = attr and result = content(c))
} }
/** Gets a summary component that represents the return value of a call. */ /** Gets a summary component that represents the return value of a call. */

View File

@@ -11,34 +11,12 @@ private import semmle.python.ApiGraphs
*/ */
predicate defaultTaintSanitizer(DataFlow::Node node) { none() } predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
/**
* Holds if default taint tracking should read content `contentSet` implicitly and
* propagate taint from a container to reads of that content.
*/
private predicate defaultTaintReadContent(DataFlow::ContentSet contentSet) {
// Tuple and dictionary content is precise, so use wildcard content sets to avoid
// blowing up the size of `Stage1::readSetEx` (otherwise this predicate would
// expand to one row per (node, distinct key or index) and the framework's
// read-set relation grows quadratically). `ContentSet.getAReadContent` expands
// these wildcards back to the specific contents when matching against stores.
contentSet.isAnyTupleOrDictionaryElement()
or
// List and set element content is already imprecise, so no wildcard expansion is
// needed.
contentSet.getAStoreContent() instanceof DataFlow::ListElementContent
or
contentSet.getAStoreContent() instanceof DataFlow::SetElementContent
}
/** /**
* Holds if default `TaintTracking::Configuration`s should allow implicit reads * Holds if default `TaintTracking::Configuration`s should allow implicit reads
* of `c` at sinks and inputs to additional taint steps. * of `c` at sinks and inputs to additional taint steps.
*/ */
bindingset[node] bindingset[node]
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
exists(node) and
defaultTaintReadContent(c)
}
private module Cached { private module Cached {
/** /**
@@ -80,8 +58,10 @@ private module Cached {
) and ) and
model = "" model = ""
or or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom
nodeTo.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model) .(DataFlowPrivate::FlowSummaryNode)
.getSummaryNode(), nodeTo.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false,
model)
} }
} }
@@ -148,6 +128,11 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
nodeFrom.getNode() = object and nodeFrom.getNode() = object and
method_name in ["partition", "rpartition", "rsplit", "split", "splitlines"] method_name in ["partition", "rpartition", "rsplit", "split", "splitlines"]
or or
// Iterable[str] -> str
// TODO: check if these should be handled differently in regards to content
method_name = "join" and
nodeFrom.getNode() = call.getArg(0)
or
// Mapping[str, Any] -> str // Mapping[str, Any] -> str
method_name = "format_map" and method_name = "format_map" and
nodeFrom.getNode() = call.getArg(0) nodeFrom.getNode() = call.getArg(0)
@@ -176,21 +161,32 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
} }
/** /**
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to reading * Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to containers
* content from containers (lists/sets/dictionaries/tuples): subscripts, iteration, * (lists/sets/dictionaries): literals, constructor invocation, methods. Note that this
* constructor invocation, methods. * is currently very imprecise, as an example, since we model `dict.get`, we treat any
* `<tainted object>.get(<arg>)` will be tainted, whether it's true or not.
*/ */
predicate containerStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { predicate containerStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
exists(DataFlow::ContentSet contentSet | // construction by literal
DataFlowPrivate::readStep(nodeFrom, contentSet, nodeTo) and //
exists(DataFlow::Content c | c = contentSet.getAReadContent() | // TODO: once we have proper flow-summary modeling, we might not need this step any
c instanceof DataFlow::TupleElementContent or // longer -- but there needs to be a matching read-step for the store-step, and we
c instanceof DataFlow::DictionaryElementContent or // don't provide that right now.
c instanceof DataFlow::DictionaryElementAnyContent or DataFlowPrivate::listStoreStep(nodeFrom, _, nodeTo)
c instanceof DataFlow::ListElementContent or or
c instanceof DataFlow::SetElementContent DataFlowPrivate::setStoreStep(nodeFrom, _, nodeTo)
) or
) DataFlowPrivate::tupleStoreStep(nodeFrom, _, nodeTo)
or
DataFlowPrivate::dictStoreStep(nodeFrom, _, nodeTo)
or
// comprehension, so there is taint-flow from `x` in `[x for x in xs]` to the
// resulting list of the list-comprehension.
//
// TODO: once we have proper flow-summary modeling, we might not need this step any
// longer -- but there needs to be a matching read-step for the store-step, and we
// don't provide that right now.
DataFlowPrivate::yieldStoreStep(nodeFrom, _, nodeTo)
} }
/** /**

View File

@@ -255,7 +255,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
// is only fed set/list content) // is only fed set/list content)
not nodeFrom instanceof DataFlowPublic::IterableElementNode not nodeFrom instanceof DataFlowPublic::IterableElementNode
or or
TypeTrackerSummaryFlow::basicStoreStep(nodeFrom, nodeTo, DataFlowPublic::singleton(content)) TypeTrackerSummaryFlow::basicStoreStep(nodeFrom, nodeTo, content)
} }
/** /**
@@ -286,15 +286,14 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
nodeFrom.asCfgNode() instanceof SequenceNode nodeFrom.asCfgNode() instanceof SequenceNode
) )
or or
TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, DataFlowPublic::singleton(content)) TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, content)
} }
/** /**
* Holds if the `loadContent` of `nodeFrom` is stored in the `storeContent` of `nodeTo`. * Holds if the `loadContent` of `nodeFrom` is stored in the `storeContent` of `nodeTo`.
*/ */
predicate loadStoreStep(Node nodeFrom, Node nodeTo, Content loadContent, Content storeContent) { predicate loadStoreStep(Node nodeFrom, Node nodeTo, Content loadContent, Content storeContent) {
TypeTrackerSummaryFlow::basicLoadStoreStep(nodeFrom, nodeTo, TypeTrackerSummaryFlow::basicLoadStoreStep(nodeFrom, nodeTo, loadContent, storeContent)
DataFlowPublic::singleton(loadContent), DataFlowPublic::singleton(storeContent))
} }
/** /**

View File

@@ -1,58 +0,0 @@
/**
* Provides classes modeling security-relevant aspects of the `anthropic` package.
* See https://github.com/anthropics/anthropic-sdk-python.
*
* Structurally typed sinks (the `system` field) are modeled via Models as Data:
* python/ql/lib/semmle/python/frameworks/anthropic.model.yml
*
* This file retains only role-filtered message sinks that require inspecting a
* sibling `role` key, which MaD cannot express.
*/
private import python
private import semmle.python.ApiGraphs
/** Provides classes modeling prompt-injection sinks of the `anthropic` package. */
module Anthropic {
/** Gets a reference to an `anthropic.Anthropic` client instance. */
private API::Node classRef() {
result = API::moduleImport("anthropic").getMember(["Anthropic", "AsyncAnthropic"]).getReturn()
}
/** Gets the message dictionaries passed to `messages.create`/`messages.stream` (stable and beta). */
private API::Node messageElement() {
exists(API::Node create |
create = classRef().getMember("messages").getMember(["create", "stream"])
or
create = classRef().getMember("beta").getMember("messages").getMember(["create", "stream"])
|
result = create.getKeywordParameter("messages").getASubscript()
)
}
/**
* Gets role-filtered system/assistant message content sinks that MaD cannot express.
*/
API::Node getSystemOrAssistantPromptNode() {
exists(API::Node msg |
msg = messageElement() and
msg.getSubscript("role").getAValueReachingSink().asExpr().(StringLiteral).getText() =
["system", "assistant"]
|
result = msg.getSubscript("content")
)
}
/**
* Gets role-filtered user message content sinks that MaD cannot express.
*/
API::Node getUserPromptNode() {
exists(API::Node msg |
msg = messageElement() and
not msg.getSubscript("role").getAValueReachingSink().asExpr().(StringLiteral).getText() =
["system", "assistant"]
|
result = msg.getSubscript("content")
)
}
}

View File

@@ -1,58 +0,0 @@
/**
* Provides classes modeling security-relevant aspects of the `google-genai` package.
* See https://github.com/googleapis/python-genai.
*
* Structurally typed sinks (`system_instruction`, `contents`, etc.) are modeled via
* Models as Data: python/ql/lib/semmle/python/frameworks/google-genai.model.yml
*
* This file retains only role-filtered content sinks that require inspecting a
* sibling `role` key, which MaD cannot express.
*/
private import python
private import semmle.python.ApiGraphs
/** Provides classes modeling prompt-injection sinks of the `google-genai` package. */
module GoogleGenAI {
/** Gets a reference to a `google.genai.Client` instance. */
private API::Node clientRef() {
result = API::moduleImport("google").getMember("genai").getMember("Client").getReturn()
}
/** Gets the content dictionaries passed to `models.generate_content`/`generate_content_stream`. */
private API::Node contentElement() {
result =
clientRef()
.getMember("models")
.getMember(["generate_content", "generate_content_stream"])
.getKeywordParameter("contents")
.getASubscript()
}
/**
* Gets role-filtered system/model content sinks that MaD cannot express.
* Gemini uses the "model" role instead of "assistant".
*/
API::Node getSystemOrAssistantPromptNode() {
exists(API::Node msg |
msg = contentElement() and
msg.getSubscript("role").getAValueReachingSink().asExpr().(StringLiteral).getText() =
["system", "model"]
|
result = msg.getSubscript("parts").getASubscript().getSubscript("text")
)
}
/**
* Gets role-filtered user content sinks that MaD cannot express.
*/
API::Node getUserPromptNode() {
exists(API::Node msg |
msg = contentElement() and
not msg.getSubscript("role").getAValueReachingSink().asExpr().(StringLiteral).getText() =
["system", "model"]
|
result = msg.getSubscript("parts").getASubscript().getSubscript("text")
)
}
}

View File

@@ -1,165 +0,0 @@
/**
* Provides classes modeling security-relevant aspects of the `openai` Agents SDK package.
* See https://github.com/openai/openai-agents-python.
* As well as the regular openai python interface.
* See https://github.com/openai/openai-python.
*
* Structurally typed sinks (instructions, prompt, input, etc.) are modeled via
* Models as Data: python/ql/lib/semmle/python/frameworks/openai.model.yml and
* python/ql/lib/semmle/python/frameworks/agent.model.yml
*
* This file retains only role-filtered message sinks that require inspecting a
* sibling `role` key, which MaD cannot express.
*/
private import python
private import semmle.python.ApiGraphs
/** Holds if `msg` is a message dictionary with a privileged (system/developer/assistant) role. */
private predicate isSystemOrDevMessage(API::Node msg) {
msg.getSubscript("role").getAValueReachingSink().asExpr().(StringLiteral).getText() =
["system", "developer", "assistant"]
}
/**
* Provides models for the agents SDK (instances of the `agents.Runner` class etc).
*
* See https://github.com/openai/openai-agents-python.
*/
module AgentSdk {
/** Gets a reference to the `agents.Runner` class. */
API::Node classRef() { result = API::moduleImport("agents").getMember("Runner") }
/** Gets a reference to the `run` members. */
API::Node runMembers() { result = classRef().getMember(["run", "run_sync", "run_streamed"]) }
/** Gets a reference to the `input` argument of a `Runner.run` call. */
private API::Node runInput() {
result = runMembers().getKeywordParameter("input")
or
result = runMembers().getParameter(1)
}
/**
* Gets role-filtered system/developer/assistant message content sinks that
* MaD cannot express.
*/
API::Node getSystemOrAssistantPromptNode() {
exists(API::Node msg |
msg = runInput().getASubscript() and
isSystemOrDevMessage(msg)
|
result = msg.getSubscript("content")
)
}
/**
* Gets role-filtered user message content sinks that MaD cannot express.
* The string-input case is handled via MaD (agent.model.yml).
*/
API::Node getUserPromptNode() {
exists(API::Node msg |
msg = runInput().getASubscript() and
not isSystemOrDevMessage(msg)
|
result = msg.getSubscript("content")
)
}
}
/**
* Provides models for the OpenAI client (instances of the `openai.OpenAI` class).
*
* See https://github.com/openai/openai-python.
*/
module OpenAI {
/** Gets a reference to an `openai.OpenAI` client instance. */
API::Node classRef() {
result =
API::moduleImport("openai").getMember(["OpenAI", "AsyncOpenAI", "AzureOpenAI"]).getReturn()
}
/** Gets the message dictionaries passed to `chat.completions.create`. */
private API::Node chatMessage() {
result =
classRef()
.getMember("chat")
.getMember("completions")
.getMember("create")
.getKeywordParameter("messages")
.getASubscript()
}
/** Gets the message dictionaries passed as a list to `responses.create`. */
private API::Node responsesMessage() {
result =
classRef()
.getMember("responses")
.getMember("create")
.getKeywordParameter("input")
.getASubscript()
}
/** Gets the content sink of a message dictionary, including the `text` of structured content. */
private API::Node messageContent(API::Node msg) {
result = msg.getSubscript("content")
or
result = msg.getSubscript("content").getASubscript().getSubscript("text")
}
/** Gets the `beta.threads.messages.create` call (Assistants API thread messages). */
private API::Node threadMessageCreate() {
result =
classRef().getMember("beta").getMember("threads").getMember("messages").getMember("create")
}
/** Holds if the `role` keyword of thread-message `call` is a privileged (assistant) role. */
private predicate threadRoleIsAssistant(API::Node call) {
call.getKeywordParameter("role").getAValueReachingSink().asExpr().(StringLiteral).getText() =
"assistant"
}
/**
* Gets role-filtered system/developer/assistant message content sinks that
* MaD cannot express.
*/
API::Node getSystemOrAssistantPromptNode() {
exists(API::Node msg | msg = [chatMessage(), responsesMessage()] and isSystemOrDevMessage(msg) |
result = messageContent(msg)
)
or
exists(API::Node call | call = threadMessageCreate() and threadRoleIsAssistant(call) |
result = call.getKeywordParameter("content")
)
}
/**
* Gets role-filtered user message content sinks that MaD cannot express.
* The string-input case is handled via MaD (openai.model.yml).
*/
API::Node getUserPromptNode() {
exists(API::Node msg |
msg = [chatMessage(), responsesMessage()] and not isSystemOrDevMessage(msg)
|
result = messageContent(msg)
)
or
exists(API::Node call | call = threadMessageCreate() and not threadRoleIsAssistant(call) |
result = call.getKeywordParameter("content")
)
or
// realtime conversation items, role cannot be statically resolved in general
result =
classRef()
.getMember("realtime")
.getMember("connect")
.getReturn()
.getMember("conversation")
.getMember("item")
.getMember("create")
.getKeywordParameter("item")
.getSubscript("content")
.getASubscript()
.getSubscript("text")
}
}

View File

@@ -1,60 +0,0 @@
/**
* Provides classes modeling security-relevant aspects of the OpenRouter Python SDK.
* See https://openrouter.ai/docs.
*
* This file retains only role-filtered message sinks that require inspecting a
* sibling `role` key, which MaD cannot express.
*/
private import python
private import semmle.python.ApiGraphs
/** Holds if `msg` is a message dictionary with a privileged (system/developer/assistant) role. */
private predicate isSystemOrDevMessage(API::Node msg) {
msg.getSubscript("role").getAValueReachingSink().asExpr().(StringLiteral).getText() =
["system", "developer", "assistant"]
}
/** Provides classes modeling prompt-injection sinks of the `openrouter` package. */
module OpenRouter {
/** Gets a reference to an `openrouter.OpenRouter` client instance. */
private API::Node clientRef() {
result = API::moduleImport("openrouter").getMember("OpenRouter").getReturn()
}
/** Gets the message dictionaries passed to `chat.send`. */
private API::Node chatMessage() {
result =
clientRef()
.getMember("chat")
.getMember("send")
.getKeywordParameter("messages")
.getASubscript()
}
/** Gets the content sink of a message dictionary, including the `text` of structured content. */
private API::Node messageContent(API::Node msg) {
result = msg.getSubscript("content")
or
result = msg.getSubscript("content").getASubscript().getSubscript("text")
}
/**
* Gets role-filtered system/developer/assistant message content sinks that
* MaD cannot express.
*/
API::Node getSystemOrAssistantPromptNode() {
exists(API::Node msg | msg = chatMessage() and isSystemOrDevMessage(msg) |
result = messageContent(msg)
)
}
/**
* Gets role-filtered user message content sinks that MaD cannot express.
*/
API::Node getUserPromptNode() {
exists(API::Node msg | msg = chatMessage() and not isSystemOrDevMessage(msg) |
result = messageContent(msg)
)
}
}

View File

@@ -4199,9 +4199,11 @@ module StdlibPrivate {
// The positional argument contains a mapping. // The positional argument contains a mapping.
// TODO: these values can be overwritten by keyword arguments // TODO: these values can be overwritten by keyword arguments
// - dict mapping // - dict mapping
input = "Argument[0].WithAnyDictionaryElement" and exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
output = "ReturnValue" and input = "Argument[0].DictionaryElement[" + key + "]" and
output = "ReturnValue.DictionaryElement[" + key + "]" and
preservesValue = true preservesValue = true
)
or or
// - list-of-pairs mapping // - list-of-pairs mapping
input = "Argument[0].ListElement.TupleElement[1]" and input = "Argument[0].ListElement.TupleElement[1]" and
@@ -4238,10 +4240,11 @@ module StdlibPrivate {
or or
input = "Argument[0].SetElement" input = "Argument[0].SetElement"
or or
input = "Argument[0].AnyTupleElement" exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[0].TupleElement[" + i.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and ) and
// Element content is mutated into list element content
output = "ReturnValue.ListElement" and output = "ReturnValue.ListElement" and
preservesValue = true preservesValue = true
or or
@@ -4262,13 +4265,17 @@ module StdlibPrivate {
} }
override predicate propagatesFlow(string input, string output, boolean preservesValue) { override predicate propagatesFlow(string input, string output, boolean preservesValue) {
input = "Argument[0].WithAnyTupleElement" and exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
output = "ReturnValue" and input = "Argument[0].TupleElement[" + i.toString() + "]" and
output = "ReturnValue.TupleElement[" + i.toString() + "]" and
preservesValue = true preservesValue = true
)
or or
input = "Argument[0].ListElement" and // TODO: We need to also translate iterable content such as list element
// but we currently lack TupleElementAny
input = "Argument[0]" and
output = "ReturnValue" and output = "ReturnValue" and
preservesValue = true preservesValue = false
} }
} }
@@ -4288,7 +4295,9 @@ module StdlibPrivate {
or or
input = "Argument[0].SetElement" input = "Argument[0].SetElement"
or or
input = "Argument[0].AnyTupleElement" exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[0].TupleElement[" + i.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and ) and
output = "ReturnValue.SetElement" and output = "ReturnValue.SetElement" and
@@ -4334,7 +4343,9 @@ module StdlibPrivate {
or or
input = "Argument[0].SetElement" input = "Argument[0].SetElement"
or or
input = "Argument[0].AnyTupleElement" exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[0].TupleElement[" + i.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and ) and
output = "ReturnValue.ListElement" and output = "ReturnValue.ListElement" and
@@ -4362,7 +4373,9 @@ module StdlibPrivate {
or or
content = "SetElement" content = "SetElement"
or or
content = "AnyTupleElement" exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
content = "TupleElement[" + i.toString() + "]"
)
| |
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
input = "Argument[0]." + content and input = "Argument[0]." + content and
@@ -4392,7 +4405,9 @@ module StdlibPrivate {
or or
input = "Argument[0].SetElement" input = "Argument[0].SetElement"
or or
input = "Argument[0].AnyTupleElement" exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[0].TupleElement[" + i.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and ) and
output = "ReturnValue.ListElement" and output = "ReturnValue.ListElement" and
@@ -4420,7 +4435,9 @@ module StdlibPrivate {
or or
input = "Argument[0].SetElement" input = "Argument[0].SetElement"
or or
input = "Argument[0].AnyTupleElement" exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[0].TupleElement[" + i.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and ) and
output = "ReturnValue" and output = "ReturnValue" and
@@ -4452,7 +4469,9 @@ module StdlibPrivate {
// We reduce generality slightly by not tracking tuple contents on list arguments beyond the first, for performance. // We reduce generality slightly by not tracking tuple contents on list arguments beyond the first, for performance.
// TODO: Once we have TupleElementAny, this generality can be increased. // TODO: Once we have TupleElementAny, this generality can be increased.
i = 0 and i = 0 and
input = "Argument[1].AnyTupleElement" exists(DataFlow::TupleElementContent tc, int j | j = tc.getIndex() |
input = "Argument[1].TupleElement[" + j.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and ) and
output = "Argument[0].Parameter[" + i.toString() + "]" and output = "Argument[0].Parameter[" + i.toString() + "]" and
@@ -4481,7 +4500,9 @@ module StdlibPrivate {
or or
input = "Argument[1].SetElement" input = "Argument[1].SetElement"
or or
input = "Argument[1].AnyTupleElement" exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[1].TupleElement[" + i.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and ) and
(output = "Argument[0].Parameter[0]" or output = "ReturnValue.ListElement") and (output = "Argument[0].Parameter[0]" or output = "ReturnValue.ListElement") and
@@ -4505,7 +4526,9 @@ module StdlibPrivate {
or or
input = "Argument[0].SetElement" input = "Argument[0].SetElement"
or or
input = "Argument[0].AnyTupleElement" exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[0].TupleElement[" + i.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and ) and
output = "ReturnValue.ListElement.TupleElement[1]" and output = "ReturnValue.ListElement.TupleElement[1]" and
@@ -4530,7 +4553,12 @@ module StdlibPrivate {
or or
input = "Argument[" + i.toString() + "].SetElement" input = "Argument[" + i.toString() + "].SetElement"
or or
input = "Argument[" + i.toString() + "].AnyTupleElement" // We reduce generality slightly by not tracking tuple contents on arguments beyond the first two, for performance.
// TODO: Once we have TupleElementAny, this generality can be increased.
i in [0 .. 1] and
exists(DataFlow::TupleElementContent tc, int j | j = tc.getIndex() |
input = "Argument[" + i.toString() + "].TupleElement[" + j.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and ) and
output = "ReturnValue.ListElement.TupleElement[" + i.toString() + "]" and output = "ReturnValue.ListElement.TupleElement[" + i.toString() + "]" and
@@ -4553,6 +4581,12 @@ module StdlibPrivate {
override DataFlow::ArgumentNode getACallback() { none() } override DataFlow::ArgumentNode getACallback() { none() }
override predicate propagatesFlow(string input, string output, boolean preservesValue) { override predicate propagatesFlow(string input, string output, boolean preservesValue) {
exists(DataFlow::Content c |
input = "Argument[self]." + c.getMaDRepresentation() and
output = "ReturnValue." + c.getMaDRepresentation() and
preservesValue = true
)
or
input = "Argument[self]" and input = "Argument[self]" and
output = "ReturnValue" and output = "ReturnValue" and
preservesValue = true preservesValue = true
@@ -4708,10 +4742,12 @@ module StdlibPrivate {
override DataFlow::ArgumentNode getACallback() { none() } override DataFlow::ArgumentNode getACallback() { none() }
override predicate propagatesFlow(string input, string output, boolean preservesValue) { override predicate propagatesFlow(string input, string output, boolean preservesValue) {
input = "Argument[self].AnyDictionaryElement" and exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
input = "Argument[self].DictionaryElement[" + key + "]" and
output = "ReturnValue.TupleElement[1]" and output = "ReturnValue.TupleElement[1]" and
preservesValue = true preservesValue = true
// TODO: put `key` into "ReturnValue.TupleElement[0]" // TODO: put `key` into "ReturnValue.TupleElement[0]"
)
} }
} }
@@ -4790,9 +4826,11 @@ module StdlibPrivate {
} }
override predicate propagatesFlow(string input, string output, boolean preservesValue) { override predicate propagatesFlow(string input, string output, boolean preservesValue) {
input = "Argument[self].AnyDictionaryElement" and exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
input = "Argument[self].DictionaryElement[" + key + "]" and
output = "ReturnValue.ListElement" and output = "ReturnValue.ListElement" and
preservesValue = true preservesValue = true
)
or or
input = "Argument[self]" and input = "Argument[self]" and
output = "ReturnValue" and output = "ReturnValue" and
@@ -4839,9 +4877,11 @@ module StdlibPrivate {
} }
override predicate propagatesFlow(string input, string output, boolean preservesValue) { override predicate propagatesFlow(string input, string output, boolean preservesValue) {
input = "Argument[self].AnyDictionaryElement" and exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
input = "Argument[self].DictionaryElement[" + key + "]" and
output = "ReturnValue.ListElement.TupleElement[1]" and output = "ReturnValue.ListElement.TupleElement[1]" and
preservesValue = true preservesValue = true
)
or or
// TODO: Add the keys to output list // TODO: Add the keys to output list
input = "Argument[self]" and input = "Argument[self]" and
@@ -4930,26 +4970,6 @@ module StdlibPrivate {
} }
} }
/** A flow summary for `str.join`. */
class StrJoinSummary extends SummarizedCallable::Range {
StrJoinSummary() { this = "str.join" }
override DataFlow::CallCfgNode getACall() { result.(DataFlow::MethodCallNode).calls(_, "join") }
override DataFlow::ArgumentNode getACallback() {
result.(DataFlow::AttrRead).getAttributeName() = "join"
}
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
(
// For code like `" ".join([name])`
input = "Argument[0,iterable:].ListElement" and
preservesValue = true
) and
output = "ReturnValue"
}
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// asyncio // asyncio
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@@ -3,13 +3,4 @@ extensions:
pack: codeql/python-all pack: codeql/python-all
extensible: sinkModel extensible: sinkModel
data: data:
# Agent instructions, handoff descriptions and tool descriptions are system-level prompts - ['agents', 'Member[Agent].Argument[instructions:]', 'prompt-injection']
- ['agents', 'Member[Agent].Argument[instructions:]', 'system-prompt-injection']
- ['agents', 'Member[Agent].Argument[handoff_description:]', 'system-prompt-injection']
- ['agents', 'Member[Agent].ReturnValue.Member[as_tool].Argument[1,tool_description:]', 'system-prompt-injection']
- ['agents', 'Member[FunctionTool].Argument[description:]', 'system-prompt-injection']
# The `@function_tool` decorator's explicit description override is a model-facing instruction
- ['agents', 'Member[function_tool].Argument[description_override:]', 'system-prompt-injection']
# The input passed to a run is user-level content
- ['agents', 'Member[Runner].Member[run,run_sync,run_streamed].Argument[1]', 'user-prompt-injection']
- ['agents', 'Member[Runner].Member[run,run_sync,run_streamed].Argument[input:]', 'user-prompt-injection']

View File

@@ -3,18 +3,12 @@ extensions:
pack: codeql/python-all pack: codeql/python-all
extensible: sinkModel extensible: sinkModel
data: data:
# The `system` field is a system-level prompt - ['Anthropic', 'Member[messages].Member[create].Argument[system:]', 'prompt-injection']
- ['Anthropic', 'Member[messages].Member[create,stream].Argument[system:]', 'system-prompt-injection'] - ['Anthropic', 'Member[messages].Member[stream].Argument[system:]', 'prompt-injection']
- ['Anthropic', 'Member[messages].Member[create,stream].Argument[system:].ListElement.DictionaryElement[text]', 'system-prompt-injection'] - ['Anthropic', 'Member[beta].Member[messages].Member[create].Argument[system:]', 'prompt-injection']
- ['Anthropic', 'Member[beta].Member[messages].Member[create,stream].Argument[system:]', 'system-prompt-injection'] - ['Anthropic', 'Member[messages].Member[create].Argument[messages:].ListElement.DictionaryElement[content]', 'prompt-injection']
- ['Anthropic', 'Member[beta].Member[messages].Member[create,stream].Argument[system:].ListElement.DictionaryElement[text]', 'system-prompt-injection'] - ['Anthropic', 'Member[messages].Member[stream].Argument[messages:].ListElement.DictionaryElement[content]', 'prompt-injection']
# The managed agents `system` field is a system-level prompt - ['Anthropic', 'Member[beta].Member[messages].Member[create].Argument[messages:].ListElement.DictionaryElement[content]', 'prompt-injection']
- ['Anthropic', 'Member[beta].Member[agents].Member[create,update].Argument[system:]', 'system-prompt-injection']
# A tool description is a model-facing instruction
- ['Anthropic', 'Member[messages].Member[create,stream].Argument[tools:].ListElement.DictionaryElement[description]', 'system-prompt-injection']
- ['Anthropic', 'Member[beta].Member[messages].Member[create,stream].Argument[tools:].ListElement.DictionaryElement[description]', 'system-prompt-injection']
# The legacy Text Completions API `prompt` is user-level content
- ['Anthropic', 'Member[completions].Member[create].Argument[prompt:]', 'user-prompt-injection']
- addsTo: - addsTo:
pack: codeql/python-all pack: codeql/python-all

View File

@@ -1,25 +0,0 @@
extensions:
- addsTo:
pack: codeql/python-all
extensible: sinkModel
data:
# `system_instruction` on the generation config is a system-level prompt
- ['google', 'Member[genai].Member[types].Member[GenerateContentConfig].Argument[system_instruction:]', 'system-prompt-injection']
# The Live API connect config carries a system instruction
- ['google', 'Member[genai].Member[types].Member[LiveConnectConfig].Argument[system_instruction:]', 'system-prompt-injection']
# Cached content carries a system instruction and user content
- ['google', 'Member[genai].Member[types].Member[CreateCachedContentConfig].Argument[system_instruction:]', 'system-prompt-injection']
# A tool/function declaration description is a model-facing instruction
- ['google', 'Member[genai].Member[types].Member[FunctionDeclaration].Argument[description:]', 'system-prompt-injection']
- ['google', 'Member[genai].Member[types].Member[CreateCachedContentConfig].Argument[contents:]', 'user-prompt-injection']
# User-level content
- ['GoogleGenAI', 'Member[models].Member[generate_content,generate_content_stream].Argument[contents:]', 'user-prompt-injection']
- ['GoogleGenAI', 'Member[models].Member[generate_images,generate_videos,edit_image].Argument[prompt:]', 'user-prompt-injection']
- ['GoogleGenAI', 'Member[chats].Member[create].ReturnValue.Member[send_message,send_message_stream].Argument[0]', 'user-prompt-injection']
- ['GoogleGenAI', 'Member[chats].Member[create].ReturnValue.Member[send_message,send_message_stream].Argument[message:]', 'user-prompt-injection']
- addsTo:
pack: codeql/python-all
extensible: typeModel
data:
- ['GoogleGenAI', 'google', 'Member[genai].Member[Client].ReturnValue']

View File

@@ -1,59 +0,0 @@
extensions:
- addsTo:
pack: codeql/python-all
extensible: sinkModel
data:
# Message constructors. The first positional argument or the `content` keyword
# carries the message text.
- ['langchain_core', 'Member[messages].Member[SystemMessage].Argument[0]', 'system-prompt-injection']
- ['langchain_core', 'Member[messages].Member[SystemMessage].Argument[content:]', 'system-prompt-injection']
- ['langchain', 'Member[schema].Member[SystemMessage].Argument[0]', 'system-prompt-injection']
- ['langchain', 'Member[schema].Member[SystemMessage].Argument[content:]', 'system-prompt-injection']
- ['langchain_core', 'Member[messages].Member[HumanMessage].Argument[0]', 'user-prompt-injection']
- ['langchain_core', 'Member[messages].Member[HumanMessage].Argument[content:]', 'user-prompt-injection']
- ['langchain', 'Member[schema].Member[HumanMessage].Argument[0]', 'user-prompt-injection']
- ['langchain', 'Member[schema].Member[HumanMessage].Argument[content:]', 'user-prompt-injection']
# Invoking a chat model with user input.
- ['LangChainChatModel', 'Member[invoke,stream,predict,call].Argument[0]', 'user-prompt-injection']
- ['LangChainChatModel', 'Member[batch].Argument[0].ListElement', 'user-prompt-injection']
- ['LangChainChatModel', 'Member[generate].Argument[0].ListElement.ListElement', 'user-prompt-injection']
# Prompt templates. User input embedded directly into a template.
- ['langchain_core', 'Member[prompts].Member[PromptTemplate].Instance.Member[format].Argument[any-named]', 'user-prompt-injection']
# Legacy `LLMChain` and `AgentExecutor` take the user input in the `input` field.
- ['LangChainLLMChain', 'Member[invoke].Argument[0].DictionaryElement[input]', 'user-prompt-injection']
- ['LangChainLLMChain', 'Member[run].Argument[0]', 'user-prompt-injection']
- ['LangChainAgentExecutor', 'Member[invoke].Argument[0].DictionaryElement[input]', 'user-prompt-injection']
# The `system_prompt` passed to `create_agent` is a system-level prompt.
- ['langchain', 'Member[agents].Member[create_agent].Argument[system_prompt:]', 'system-prompt-injection']
# The messages passed to a `create_agent` graph are user-level content.
- ['LangChainAgent', 'Member[invoke,stream].Argument[0].DictionaryElement[messages].ListElement.DictionaryElement[content]', 'user-prompt-injection']
# A tool description is a model-facing instruction.
- ['langchain_core', 'Member[tools].Member[Tool].Argument[2,description:]', 'system-prompt-injection']
- ['langchain_core', 'Member[tools].Member[Tool].Member[from_function].Argument[2,description:]', 'system-prompt-injection']
- ['langchain_core', 'Member[tools].Member[StructuredTool].Argument[description:]', 'system-prompt-injection']
- ['langchain_core', 'Member[tools].Member[StructuredTool].Member[from_function].Argument[description:]', 'system-prompt-injection']
- ['langchain_core', 'Member[tools].Member[tool].Argument[description:]', 'system-prompt-injection']
- addsTo:
pack: codeql/python-all
extensible: typeModel
data:
- ['LangChainChatModel', 'langchain_openai', 'Member[ChatOpenAI,AzureChatOpenAI].ReturnValue']
- ['LangChainChatModel', 'langchain_anthropic', 'Member[ChatAnthropic].ReturnValue']
- ['LangChainChatModel', 'langchain_google_genai', 'Member[ChatGoogleGenerativeAI].ReturnValue']
- ['LangChainChatModel', 'langchain_mistralai', 'Member[ChatMistralAI].ReturnValue']
- ['LangChainChatModel', 'langchain_groq', 'Member[ChatGroq].ReturnValue']
- ['LangChainChatModel', 'langchain_cohere', 'Member[ChatCohere].ReturnValue']
- ['LangChainChatModel', 'langchain_ollama', 'Member[ChatOllama].ReturnValue']
- ['LangChainChatModel', 'langchain_aws', 'Member[ChatBedrock,ChatBedrockConverse].ReturnValue']
- ['LangChainChatModel', 'langchain_fireworks', 'Member[ChatFireworks].ReturnValue']
- ['LangChainChatModel', 'langchain_together', 'Member[ChatTogether].ReturnValue']
- ['LangChainChatModel', 'langchain_xai', 'Member[ChatXAI].ReturnValue']
- ['LangChainChatModel', 'langchain', 'Member[chat_models].Member[init_chat_model].ReturnValue']
- ['LangChainLLMChain', 'langchain', 'Member[chains].Member[LLMChain].ReturnValue']
- ['LangChainLLMChain', 'langchain_classic', 'Member[chains].Member[LLMChain].ReturnValue']
- ['LangChainAgentExecutor', 'langchain', 'Member[agents].Member[AgentExecutor].ReturnValue']
- ['LangChainAgentExecutor', 'langchain_classic', 'Member[agents].Member[AgentExecutor].ReturnValue']
- ['LangChainAgentExecutor', 'langchain', 'Member[agents].Member[AgentExecutor].Member[from_agent_and_tools].ReturnValue']
- ['LangChainAgentExecutor', 'langchain_classic', 'Member[agents].Member[AgentExecutor].Member[from_agent_and_tools].ReturnValue']
- ['LangChainAgent', 'langchain', 'Member[agents].Member[create_agent].ReturnValue']

View File

@@ -1,6 +0,0 @@
extensions:
- addsTo:
pack: codeql/python-all
extensible: summaryModel
data:
- ['lxml', 'Member[etree].Member[fromstringlist]', 'Argument[0,strings:].ListElement', 'ReturnValue', 'taint']

View File

@@ -3,24 +3,10 @@ extensions:
pack: codeql/python-all pack: codeql/python-all
extensible: sinkModel extensible: sinkModel
data: data:
# System-level prompts and instructions - ['OpenAI', 'Member[beta].Member[assistants].Member[create].Argument[instructions:]', 'prompt-injection']
- ['OpenAI', 'Member[responses].Member[create].Argument[instructions:]', 'system-prompt-injection'] - ['OpenAI', 'Member[chat].Member[completions].Member[create].Argument[messages:].ListElement.DictionaryElement[content]', 'prompt-injection']
- ['OpenAI', 'Member[beta].Member[assistants].Member[create].Argument[instructions:]', 'system-prompt-injection'] - ['OpenAI', 'Member[responses].Member[create].Argument[instructions:]', 'prompt-injection']
- ['OpenAI', 'Member[beta].Member[assistants].Member[update].Argument[instructions:]', 'system-prompt-injection'] - ['OpenAI', 'Member[responses].Member[create].Argument[input:]', 'prompt-injection']
- ['OpenAI', 'Member[beta].Member[threads].Member[runs].Member[create].Argument[instructions:]', 'system-prompt-injection']
- ['OpenAI', 'Member[beta].Member[threads].Member[runs].Member[create].Argument[additional_instructions:]', 'system-prompt-injection']
# The default system instructions for a realtime session
- ['OpenAI', 'Member[beta].Member[realtime].Member[sessions].Member[create].Argument[instructions:]', 'system-prompt-injection']
# A tool/function description is a model-facing instruction
- ['OpenAI', 'Member[chat].Member[completions].Member[create].Argument[tools:].ListElement.DictionaryElement[function].DictionaryElement[description]', 'system-prompt-injection']
- ['OpenAI', 'Member[responses].Member[create].Argument[tools:].ListElement.DictionaryElement[description]', 'system-prompt-injection']
# User-level prompts
- ['OpenAI', 'Member[responses].Member[create].Argument[input:]', 'user-prompt-injection']
- ['OpenAI', 'Member[completions].Member[create].Argument[prompt:]', 'user-prompt-injection']
- ['OpenAI', 'Member[images].Member[generate,edit].Argument[prompt:]', 'user-prompt-injection']
- ['OpenAI', 'Member[audio].Member[transcriptions,translations].Member[create].Argument[prompt:]', 'user-prompt-injection']
# Sora video generation prompts are user-level content
- ['OpenAI', 'Member[videos].Member[create,create_and_poll,edit,remix,extend].Argument[prompt:]', 'user-prompt-injection']
- addsTo: - addsTo:
pack: codeql/python-all pack: codeql/python-all

View File

@@ -1,22 +0,0 @@
extensions:
- addsTo:
pack: codeql/python-all
extensible: sinkModel
data:
# `responses.send` instructions is a system-level prompt; input is user content
- ['OpenRouter', 'Member[responses].Member[send].Argument[instructions:]', 'system-prompt-injection']
- ['OpenRouter', 'Member[responses].Member[send].Argument[input:]', 'user-prompt-injection']
# A tool/function description passed to `chat.send` is a model-facing instruction
- ['OpenRouter', 'Member[chat].Member[send].Argument[tools:].ListElement.DictionaryElement[function].DictionaryElement[description]', 'system-prompt-injection']
# Embeddings input is user-level content
- ['OpenRouter', 'Member[embeddings].Member[generate].Argument[input:]', 'user-prompt-injection']
# Image, video and speech generation prompts are user-level content
- ['OpenRouter', 'Member[images].Member[generate].Argument[prompt:]', 'user-prompt-injection']
- ['OpenRouter', 'Member[video_generation].Member[generate].Argument[prompt:]', 'user-prompt-injection']
- ['OpenRouter', 'Member[tts].Member[create_speech].Argument[input:]', 'user-prompt-injection']
- addsTo:
pack: codeql/python-all
extensible: typeModel
data:
- ['OpenRouter', 'openrouter', 'Member[OpenRouter].ReturnValue']

View File

@@ -1,6 +0,0 @@
extensions:
- addsTo:
pack: codeql/python-all
extensible: summaryModel
data:
- ['xml', 'Member[etree].Member[fromstringlist]', 'Argument[0,strings:].ListElement', 'ReturnValue', 'taint']

View File

@@ -1,91 +0,0 @@
/**
* Provides default sources, sinks and sanitizers for detecting
* "system prompt injection"
* vulnerabilities, as well as extension points for adding your own.
*/
import python
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.BarrierGuards
private import semmle.python.frameworks.data.ModelsAsData
private import semmle.python.frameworks.OpenAI
private import semmle.python.frameworks.Anthropic
private import semmle.python.frameworks.GoogleGenAI
private import semmle.python.frameworks.OpenRouter
/**
* Provides default sources, sinks and sanitizers for detecting
* "system prompt injection"
* vulnerabilities, as well as extension points for adding your own.
*/
module SystemPromptInjection {
/**
* A data flow source for "system prompt injection" vulnerabilities.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for "system prompt injection" vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A sanitizer for "system prompt injection" vulnerabilities.
*/
abstract class Sanitizer extends DataFlow::Node { }
/**
* An active threat-model source, considered as a flow source.
*/
private class ActiveThreatModelSourceAsSource extends Source, ActiveThreatModelSource { }
/**
* A prompt to an AI model, considered as a flow sink.
*/
class AIPromptAsSink extends Sink {
AIPromptAsSink() { this = any(AIPrompt p).getAPrompt() }
}
private class SinkFromModel extends Sink {
SinkFromModel() { this = ModelOutput::getASinkNode("system-prompt-injection").asSink() }
}
private class PromptContentSink extends Sink {
PromptContentSink() {
this = OpenAI::getSystemOrAssistantPromptNode().asSink()
or
this = AgentSdk::getSystemOrAssistantPromptNode().asSink()
or
this = Anthropic::getSystemOrAssistantPromptNode().asSink()
or
this = GoogleGenAI::getSystemOrAssistantPromptNode().asSink()
or
this = OpenRouter::getSystemOrAssistantPromptNode().asSink()
}
}
/**
* Content placed in a message with `role: "user"` is not a system prompt
* injection vector; it is intended user-role content.
*
* This prevents false positives when user input and system prompts are
* combined in the same message list and taint would otherwise propagate to
* the system message.
*/
private class UserRoleMessageContentBarrier extends Sanitizer {
UserRoleMessageContentBarrier() {
exists(API::Node msg |
msg.getSubscript("role").getAValueReachingSink().asExpr().(StringLiteral).getText() = "user"
|
this = msg.getSubscript("content").asSink()
)
}
}
/**
* A comparison with a constant, considered as a sanitizer-guard.
*/
class ConstCompareAsSanitizerGuard extends Sanitizer, ConstCompareBarrier { }
}

View File

@@ -1,25 +0,0 @@
/**
* Provides a taint-tracking configuration for detecting "system prompt injection" vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `SystemPromptInjection::Configuration` is needed, otherwise
* `SystemPromptInjectionCustomizations` should be imported instead.
*/
private import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import SystemPromptInjectionCustomizations::SystemPromptInjection
private module SystemPromptInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof Source }
predicate isSink(DataFlow::Node node) { node instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate observeDiffInformedIncrementalMode() { any() }
}
/** Global taint-tracking for detecting "system prompt injection" vulnerabilities. */
module SystemPromptInjectionFlow = TaintTracking::Global<SystemPromptInjectionConfig>;

View File

@@ -1,25 +0,0 @@
/**
* Provides a taint-tracking configuration for detecting "user prompt injection" vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `UserPromptInjection::Configuration` is needed, otherwise
* `UserPromptInjectionCustomizations` should be imported instead.
*/
private import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import UserPromptInjectionCustomizations::UserPromptInjection
private module UserPromptInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof Source }
predicate isSink(DataFlow::Node node) { node instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate observeDiffInformedIncrementalMode() { any() }
}
/** Global taint-tracking for detecting "user prompt injection" vulnerabilities. */
module UserPromptInjectionFlow = TaintTracking::Global<UserPromptInjectionConfig>;

View File

@@ -1,48 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>If user-controlled data is included in a system prompt or the description of tools for an agentic system, an attacker can manipulate the instructions
that govern the AI model's behavior, bypassing intended restrictions and potentially causing sensitive
data leaks or unintended operations.
</p>
</overview>
<recommendation>
<p>Do not include user input in system-level or developer-level prompts or tool descriptions. Use methods meant for user input or messages with a "user" role to provide user content or context to the AI model.
If user input must influence the system prompt or tool description, validate it against a fixed allowlist of permitted values.</p>
</recommendation>
<example>
<p>In the following example, a user-controlled value is inserted directly into a system-level prompt
without validation, allowing an attacker to manipulate the AI's behavior.</p>
<sample src="examples/prompt-injection.py" />
<p>One way to fix this is to provide the user-controlled value in a message with the "user" role,
rather than including it in the system prompt. The model then treats it as user content instead of
as a trusted instruction.</p>
<sample src="examples/prompt-injection_fixed_user_role.py" />
<p>Alternatively, if the user input must influence the system prompt, validate it against a fixed
allowlist of permitted values before including it in the prompt.</p>
<sample src="examples/prompt-injection_fixed.py" />
</example>
<example>
<p>Prompt injection is not limited to system prompts. In the following example, which uses an agentic
framework, a user-controlled value is included in the description of a tool that is exposed to the
model. An attacker can use this to manipulate the model's behavior in the same way.</p>
<sample src="examples/tool-description-injection.py" />
<p>The fix keeps the tool description as a fixed, trusted string and passes the user-controlled topic
as part of the user input instead, so the model treats it as user content rather than as a trusted
instruction.</p>
<sample src="examples/tool-description-injection_fixed.py" />
</example>
<references>
<li>OWASP: <a href="https://genai.owasp.org/llmrisk/llm01-prompt-injection/">LLM01: Prompt Injection</a>.</li>
<li>MITRE CWE: <a href="https://cwe.mitre.org/data/definitions/1427.html">CWE-1427: Improper Neutralization of Input Used for LLM Prompting</a>.</li>
</references>
</qhelp>

View File

@@ -1,21 +0,0 @@
/**
* @name System prompt injection
* @description Untrusted input flowing into a system prompt, developer prompt, or tool description
* of an AI model may allow an attacker to manipulate the model's behavior.
* @kind path-problem
* @problem.severity error
* @security-severity 7.8
* @precision high
* @id py/system-prompt-injection
* @tags security
* external/cwe/cwe-1427
*/
import python
import semmle.python.security.dataflow.SystemPromptInjectionQuery
import SystemPromptInjectionFlow::PathGraph
from SystemPromptInjectionFlow::PathNode source, SystemPromptInjectionFlow::PathNode sink
where SystemPromptInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This system prompt depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -1,47 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>If untrusted input is included in a user-role prompt sent to an AI model, an attacker can inject
instructions that manipulate the model's behavior. This is known as <i>indirect prompt injection</i>
when the malicious content arrives through data the model processes, or <i>direct prompt injection</i>
when the attacker controls the prompt directly.</p>
<p>Unlike system prompt injection, user prompt injection targets the user-role messages. Although
user messages are expected to carry user input, passing unsanitized data directly into structured
prompt templates can still allow an attacker to override intended instructions, extract sensitive
context, or trigger unintended tool calls.</p>
</overview>
<recommendation>
<p>To mitigate user prompt injection:</p>
<ul>
<li>Ensure that all data flowing into user input is intended and necessary for the purpose of the AI system.</li>
<li>Ensure the system prompt clearly describes the purpose, scope and boundaries of the AI system. Instruct the system to deny input that falls outside these boundaries.</li>
<li>If creating a prompt out of multiple user-controlled values, assume that each of them can be malicious. Ensure the range of possible values is restricted and validated.
For example, if a prompt includes a question and the intended language to respond in, validate that the language is one of the supported options.</li>
<li>Consider using guardrails on the input like the OpenAI guardrails library to enforce constraints and prevent malicious content from being processed.</li>
<li>Apply output filtering to detect and block responses that indicate prompt injection attempts.</li>
</ul>
</recommendation>
<example>
<p>In the following example, user-controlled data is inserted directly into a user-role prompt
without any validation, allowing an attacker to inject arbitrary instructions.</p>
<sample src="examples/user-prompt-injection.py" />
<p>The following example applies multiple mitigations together, and only includes data that is
necessary for the task in the prompt: the value that selects behavior (the response language) is
validated against a fixed allowlist before it is used, and the system prompt clearly describes the
assistant's scope and instructs it to ignore embedded instructions.</p>
<sample src="examples/user-prompt-injection_fixed.py" />
</example>
<references>
<li>OWASP: <a href="https://genai.owasp.org/llmrisk/llm01-prompt-injection/">LLM01: Prompt Injection</a>.</li>
<li>MITRE CWE: <a href="https://cwe.mitre.org/data/definitions/1427.html">CWE-1427: Improper Neutralization of Input Used for LLM Prompting</a>.</li>
</references>
</qhelp>

View File

@@ -1,21 +0,0 @@
/**
* @name User prompt injection
* @description Untrusted input flowing into a user-role prompt of an AI model
* may allow an attacker to manipulate the model's behavior.
* @kind path-problem
* @problem.severity warning
* @security-severity 5.0
* @precision low
* @id py/user-prompt-injection
* @tags security
* external/cwe/cwe-1427
*/
import python
import semmle.python.security.dataflow.UserPromptInjectionQuery
import UserPromptInjectionFlow::PathGraph
from UserPromptInjectionFlow::PathNode source, UserPromptInjectionFlow::PathNode sink
where UserPromptInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This prompt construction depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -1,27 +0,0 @@
from flask import Flask, request
from openai import OpenAI
app = Flask(__name__)
client = OpenAI()
@app.get("/chat")
def chat():
persona = request.args.get("persona")
# BAD: user input is used directly in a system-level prompt
response = client.chat.completions.create(
model="gpt-4.1",
messages=[
{
"role": "system",
"content": "You are a helpful assistant. Act as a " + persona,
},
{
"role": "user",
"content": request.args.get("message"),
},
],
)
return response

Some files were not shown because too many files have changed in this diff Show More