Merge pull request #22061 from MathiasVP/mad-write-through-model

Shared: Support flow summaries from `ReturnValue`s
This commit is contained in:
Mathias Vorreiter Pedersen
2026-07-02 12:38:44 +01:00
committed by GitHub
37 changed files with 329 additions and 63 deletions

View File

@@ -6,6 +6,7 @@ private import cpp as Cpp
private import codeql.dataflow.internal.FlowSummaryImpl
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.DataFlowNodes
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.dataflow.ExternalFlow
@@ -20,8 +21,22 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
class SinkBase = Void;
class FlowSummaryCallBase = CallInstruction;
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) }
ReturnKind getStandardReturnValueKind() { result = getReturnValueKind("") }
@@ -30,6 +45,10 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
arg = repeatStars(result.(NormalReturnKind).getIndirectionIndex())
}
ParameterPosition getFlowSummaryParameterPosition(ReturnKind rk) {
result = TFlowSummaryPosition(rk)
}
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }
string encodeArgumentPosition(ArgumentPosition pos) { result = pos.toString() }
@@ -114,10 +133,22 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
private import Make<Location, DataFlowImplSpecific::CppDataFlow, Input> as Impl
private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable 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() }
Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) { none() }

View File

@@ -1534,12 +1534,8 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
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() {
result.asSummarizedCallable() = this.getSummarizedCallable()
result = FlowSummaryImpl::Private::getEnclosingCallable(this.getSummaryNode())
}
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }

View File

@@ -561,6 +561,21 @@ 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. */
class ParameterPosition = Position;
@@ -616,6 +631,18 @@ class IndirectionPosition extends Position, TIndirectionPosition {
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 =
TDirectPosition(int argumentIndex) {
exists(any(CallInstruction c).getArgument(argumentIndex))
@@ -634,7 +661,8 @@ newtype TPosition =
p = f.getParameter(argumentIndex) and
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1]
)
}
} or
TFlowSummaryPosition(ReturnKind rk) { FlowSummaryImpl::Private::relevantFlowSummaryPosition(rk) }
private newtype TReturnKind =
TNormalReturnKind(int indirectionIndex) {

View File

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

View File

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

View File

@@ -53,14 +53,17 @@ models
| 52 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 53 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 54 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 55 | Summary: ; TemplateClass1; true; templateFunction2<U,V>; (U,V); ; Argument[1]; ReturnValue; value; manual |
| 56 | Summary: ; TemplateClass1<T>; false; templateFunction<U>; (T,U); ; Argument[0]; ReturnValue; value; manual |
| 57 | Summary: ; TemplateClass2<T,U>; true; function; (U,T); ; Argument[1]; ReturnValue; value; manual |
| 58 | Summary: Azure::Core::IO; BodyStream; true; Read; ; ; Argument[-1]; Argument[*0]; taint; manual |
| 59 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; taint; manual |
| 60 | Summary: Azure::Core::IO; BodyStream; true; ReadToEnd; ; ; Argument[-1]; ReturnValue.Element; taint; manual |
| 61 | Summary: Azure; Nullable; true; Value; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
| 62 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
| 55 | Summary: ; MyString; true; operator[]; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
| 56 | Summary: ; MyString; true; operator[]; ; ; ReturnValue[*]; Argument[-1]; taint; manual |
| 57 | Summary: ; ReverseFlow; true; get_ptr; ; ; ReturnValue[*]; Argument[-1].Field[ReverseFlow::value]; value; manual |
| 58 | Summary: ; TemplateClass1; true; templateFunction2<U,V>; (U,V); ; Argument[1]; ReturnValue; value; manual |
| 59 | Summary: ; TemplateClass1<T>; false; templateFunction<U>; (T,U); ; Argument[0]; ReturnValue; value; manual |
| 60 | Summary: ; TemplateClass2<T,U>; true; function; (U,T); ; Argument[1]; ReturnValue; value; manual |
| 61 | Summary: Azure::Core::IO; BodyStream; true; Read; ; ; Argument[-1]; Argument[*0]; taint; manual |
| 62 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; 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
| 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 |
@@ -69,16 +72,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: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:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:62 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:65 |
| 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: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:257:5:257:8 | *resp | azure.cpp:257:16:257:21 | Read output argument | provenance | MaD:58 |
| azure.cpp:257:5:257:8 | *resp | azure.cpp:257:16:257:21 | Read output argument | provenance | MaD:61 |
| 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:59 |
| azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument | provenance | MaD:62 |
| 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:60 |
| azure.cpp:266:38:266:41 | *resp | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | MaD:63 |
| 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:267:10:267:12 | vec [element] | azure.cpp:267:10:267:12 | vec | provenance | |
@@ -94,10 +97,10 @@ edges
| 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: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:60 |
| 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: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:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:61 |
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:64 |
| 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:63:289:65 | call to Value | azure.cpp:289:63:289:65 | call to Value | provenance | |
@@ -159,27 +162,27 @@ edges
| 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: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:56 |
| test.cpp:134:45:134:45 | x | test.cpp:134:13:134:43 | call to templateFunction | provenance | MaD:59 |
| 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: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:26:148:26 | x | test.cpp:148:10:148:27 | call to function | provenance | MaD:57 |
| test.cpp:148:26:148:26 | x | test.cpp:148:10:148:27 | call to function | provenance | MaD:60 |
| 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: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:26:157:26 | x | test.cpp:157:13:157:20 | call to function | provenance | MaD:57 |
| test.cpp:157:26:157:26 | x | test.cpp:157:13:157:20 | call to function | provenance | MaD:60 |
| 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: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:55 |
| test.cpp:165:69:165:69 | x | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | MaD:58 |
| 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: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: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:55 |
| test.cpp:172:51:172:51 | x | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | MaD:58 |
| 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:14:186:22 | call to ymlSource | test.cpp:186:2:186:24 | ... = ... | provenance | Src:MaD:25 |
@@ -192,6 +195,18 @@ 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: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: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:24:8:24:11 | * ... | provenance | |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:27:36:27:38 | *cmd | provenance | |
@@ -470,6 +485,20 @@ 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:35:200:36 | *& ... [myField] | semmle.label | *& ... [myField] |
| 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:24:8:24:11 | * ... | semmle.label | * ... |

View File

@@ -23,4 +23,7 @@ extensions:
- ["", "TemplateClass1", True, "templateFunction2<U,V>", "(U,V)", "", "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_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,3 +21,5 @@
| test.cpp:173:10:173:10 | y | test-sink |
| test.cpp:188:10:188: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,6 +15,8 @@
| test.cpp:170:10:170:18 | 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: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:34:17:34:38 | *call to GetEnvironmentStringsA | local |
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local |

View File

@@ -199,4 +199,28 @@ void test_fully_qualified_field_test_2() {
s.myField = ymlSource();
int x = read_field_from_struct_2(&s);
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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -529,7 +529,7 @@ predicate simpleLocalFlowStepForTypetracking(Node nodeFrom, Node nodeTo) {
}
private predicate summaryLocalStep(Node nodeFrom, Node nodeTo, string model) {
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
}

View File

@@ -20,6 +20,8 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
class SinkBase = Void;
class FlowSummaryCallBase = Void;
predicate callableFromSource(SummarizedCallableBase c) { none() }
ArgumentPosition callbackSelfParameterPosition() { result.isLambdaSelf() }
@@ -111,6 +113,10 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
private import Make<Location, DataFlowImplSpecific::PythonDataFlow, Input> as Impl
private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
overlay[global]
DataFlowCall getACall(Public::SummarizedCallable sc) {
result =

View File

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

View File

@@ -198,8 +198,7 @@ module LocalFlow {
FlowSummaryNode nodeFrom, FlowSummaryNode nodeTo, FlowSummaryImpl::Public::SummarizedCallable c,
string model
) {
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.getSummaryNode(),
nodeTo.getSummaryNode(), true, model) and
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo.getSummaryNode(), true, model) and
c = nodeFrom.getSummarizedCallable()
}

View File

@@ -18,6 +18,8 @@ module Input implements InputSig<Location, DataFlowImplSpecific::RubyDataFlow> {
class SinkBase = Void;
class FlowSummaryCallBase = Void;
predicate callableFromSource(SummarizedCallableBase c) { none() }
ArgumentPosition callbackSelfParameterPosition() { result.isLambdaSelf() }
@@ -157,6 +159,10 @@ module Input implements InputSig<Location, DataFlowImplSpecific::RubyDataFlow> {
private import Make<Location, DataFlowImplSpecific::RubyDataFlow, Input> as Impl
private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable sc) {
result.asCall().getAstNode() = sc.(LibraryCallable).getACall()
or

View File

@@ -109,7 +109,7 @@ private module Cached {
) and
model = ""
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
or
any(FlowSteps::AdditionalTaintStep s).step(nodeFrom, nodeTo) and model = "AdditionalTaintStep"

View File

@@ -180,7 +180,7 @@ Expr getPostUpdateReverseStep(Expr e, boolean preservesValue) {
module LocalFlow {
predicate flowSummaryLocalStep(Node nodeFrom, Node nodeTo, string model) {
exists(FlowSummaryImpl::Public::SummarizedCallable c |
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model) and
c = nodeFrom.(FlowSummaryNode).getSummarizedCallable()
)

View File

@@ -11,6 +11,7 @@ private import codeql.rust.dataflow.FlowSummary
private import codeql.rust.dataflow.Ssa
private import codeql.rust.dataflow.internal.ModelsAsData
private import Content
private import Node
predicate encodeContentTupleField(TupleFieldContent c, string arg) {
exists(Addressable a, int pos, string prefix |
@@ -28,9 +29,12 @@ predicate encodeContentStructField(StructFieldContent c, string arg) {
module Input implements InputSig<Location, RustDataFlow> {
private import codeql.rust.frameworks.stdlib.Stdlib
private import codeql.util.Void
class SummarizedCallableBase = Function;
class FlowSummaryCallBase = Void;
predicate callableFromSource(SummarizedCallableBase c) { c.fromSource() }
abstract private class SourceSinkBase extends AstNode {
@@ -144,6 +148,10 @@ module Input implements InputSig<Location, RustDataFlow> {
private import Make<Location, RustDataFlow, Input> as Impl
module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(RustDataFlow::Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable sc) { result.asCall().getStaticTarget() = sc }
/** Gets the argument of `source` described by `sc`, if any. */

View File

@@ -83,7 +83,7 @@ module RustTaintTrackingGen<DataFlowImpl::RustDataFlowInputSig I> implements
pred.(Node::PostUpdateNode).getPreUpdateNode().asExpr(), _, succ, _)
)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(Node::FlowSummaryNode).getSummaryNode(),
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred,
succ.(Node::FlowSummaryNode).getSummaryNode(), false, model)
}

View File

@@ -54,6 +54,24 @@ signature module InputSig<LocationSig Location, DF::InputSig<Location> Lang> {
none()
}
/**
* A base class of calls that are candidates for flow summary modeling.
*/
class FlowSummaryCallBase {
string toString();
}
/** Gets a call that targets summarized callable `sc`. */
default FlowSummaryCallBase getASourceCall(SummarizedCallableBase sc) { none() }
/** Gets the callable corresponding to summarized callable `c`. */
default Lang::DataFlowCallable getSummarizedCallableAsDataFlowCallable(SummarizedCallableBase c) {
none()
}
/** Gets the enclosing callable of `call`. */
default Lang::DataFlowCallable getSourceCallEnclosingCallable(FlowSummaryCallBase call) { none() }
/** Gets the parameter position representing a callback itself, if any. */
default Lang::ArgumentPosition callbackSelfParameterPosition() { none() }
@@ -74,6 +92,9 @@ signature module InputSig<LocationSig Location, DF::InputSig<Location> Lang> {
result = getStandardReturnValueKind()
}
/** Gets the parameter position corresponding to a flow-summary return kind `rk`, if any. */
default Lang::ParameterPosition getFlowSummaryParameterPosition(Lang::ReturnKind rk) { none() }
/** Gets the textual representation of parameter position `pos` used in MaD. */
string encodeParameterPosition(Lang::ParameterPosition pos);
@@ -660,6 +681,10 @@ module Make<
s.length() = 1 and
s.head() instanceof TArgumentSummaryComponent
or
// ReturnValue.*
s.length() = 1 and
s.head() instanceof TReturnSummaryComponent
or
// Argument[n].ReturnValue.*
s.length() = 2 and
s.head() instanceof TReturnSummaryComponent and
@@ -1137,6 +1162,13 @@ module Make<
outputState(c, s) and s = SummaryComponentStack::argument(_)
}
private predicate relevantFlowSummaryPosition(SummarizedCallable c, ReturnKind rk) {
exists(SummaryComponentStack input |
summary(c, input, _, _, _) and
input = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
)
}
pragma[nomagic]
private predicate sourceOutputStateEntry(
SourceElement source, SummaryComponentStack s, string kind, string model
@@ -1272,6 +1304,12 @@ module Make<
TSummaryParameterNode(SummarizedCallable c, ParameterPosition pos) {
summaryParameterNodeRange(c, pos)
} or
TSummaryReturnArgumentNode(FlowSummaryCallBase call, ReturnKind rk) {
exists(SummarizedCallable sc |
call = getASourceCall(sc) and
relevantFlowSummaryPosition(sc, rk)
)
} or
TSourceOutputNode(SourceElement source, SummaryNodeState state, string kind, string model) {
state.isSourceOutputState(source, _, kind, model)
} or
@@ -1321,6 +1359,40 @@ module Make<
override SinkElement getSinkElement() { none() }
}
private class SummaryReturnArgumentNode extends SummaryNode, TSummaryReturnArgumentNode {
private FlowSummaryCallBase call;
private ReturnKind rk;
SummaryReturnArgumentNode() { this = TSummaryReturnArgumentNode(call, rk) }
override string toString() { result = "[summary] value written to " + rk + " at " + call }
override SummarizedCallable getSummarizedCallable() { none() }
override SourceElement getSourceElement() { none() }
override SinkElement getSinkElement() { none() }
}
/**
* Gets the summary node that represents the argument node used to transfer
* flow into the caller when a value is written to the value returned by
* `call` with kind `rk`.
*/
SummaryNode summaryArgumentNode(FlowSummaryCallBase call, ReturnKind rk) {
result = TSummaryReturnArgumentNode(call, rk)
}
/** Gets the enclosing callable for summary node `sn`. */
DataFlowCallable getEnclosingCallable(SummaryNode sn) {
result = getSummarizedCallableAsDataFlowCallable(sn.getSummarizedCallable())
or
exists(FlowSummaryCallBase call |
sn = TSummaryReturnArgumentNode(call, _) and
result = getSourceCallEnclosingCallable(call)
)
}
class SourceOutputNode extends SummaryNode, TSourceOutputNode {
private SourceElement source_;
private SummaryNodeState state_;
@@ -1427,6 +1499,12 @@ module Make<
SummarizedCallable c, SummaryNodeState state, ParameterPosition pos
) {
state.isInputState(c, SummaryComponentStack::argument(pos))
or
exists(ReturnKind rk |
relevantFlowSummaryPosition(c, rk) and
state.isInputState(c, SummaryComponentStack::return(rk)) and
pos = getFlowSummaryParameterPosition(rk)
)
}
/**
@@ -1560,6 +1638,9 @@ module Make<
)
}
/** Holds if return kind `rk` is a relevant return kind for flow summary modeling. */
predicate relevantFlowSummaryPosition(ReturnKind rk) { relevantFlowSummaryPosition(_, rk) }
/**
* Holds if flow is allowed to pass from the parameter at position `pos` of `c`,
* to a return node, and back out to the parameter.
@@ -1736,9 +1817,15 @@ module Make<
}
signature module StepsInputSig {
/** Gets the summary node represented by data-flow node `n`, if any. */
SummaryNode getSummaryNode(Node n);
/** Gets a call that targets summarized callable `sc`. */
DataFlowCall getACall(SummarizedCallable sc);
/** Gets the out node of kind `rk` for `call`, if any. */
default Node getSourceOutNode(FlowSummaryCallBase call, ReturnKind rk) { none() }
/** Gets the enclosing callable of `source`. */
DataFlowCallable getSourceNodeEnclosingCallable(SourceBase source);
@@ -1765,7 +1852,7 @@ module Make<
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(
private predicate summaryLocalStepImpl(
SummaryNode pred, SummaryNode succ, boolean preservesValue, string model
) {
exists(
@@ -1811,9 +1898,24 @@ module Make<
)
}
/** Holds if there is a local step between data-flow nodes synthesized from a flow summary. */
predicate summaryLocalStep(Node pred, SummaryNode succ, boolean preservesValue, string model) {
exists(SummaryNode predSummary |
predSummary = StepsInput::getSummaryNode(pred) and
summaryLocalStepImpl(predSummary, succ, preservesValue, model)
)
or
exists(FlowSummaryCallBase summaryCall, ReturnKind rk, SummarizedCallable sc |
pred = StepsInput::getSourceOutNode(summaryCall, rk) and
summaryCall = getASourceCall(sc) and
summary(sc, SummaryComponentStack::return(rk), _, preservesValue, model) and
succ = TSummaryReturnArgumentNode(summaryCall, rk)
)
}
/** Holds if the value of `succ` is uniquely determined by the value of `pred`. */
predicate summaryLocalMustFlowStep(SummaryNode pred, SummaryNode succ) {
pred = unique(SummaryNode n1 | summaryLocalStep(n1, succ, true, _))
pred = unique(SummaryNode n1 | summaryLocalStepImpl(n1, succ, true, _))
}
/**
@@ -1935,7 +2037,7 @@ module Make<
or
exists(SummaryNode mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true, _) and
summaryLocalStepImpl(mid, n, true, _) and
if
summaryClearsContent(n, _) or
summaryExpectsContent(n, _)
@@ -1993,7 +2095,7 @@ module Make<
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, true, _)
summaryLocalStepImpl(summaryArgParamRetOut(arg, ret, out, sc), ret, true, _)
)
}
@@ -2006,7 +2108,7 @@ module Make<
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false, _)
summaryLocalStepImpl(summaryArgParamRetOut(arg, ret, out, sc), ret, false, _)
)
}
@@ -2020,7 +2122,7 @@ module Make<
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _, _)
summaryLocalStepImpl(mid, ret, _, _)
)
}
@@ -2033,7 +2135,7 @@ module Make<
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _, _) and
summaryLocalStepImpl(summaryArgParamRetOut(arg, ret, out, sc), mid, _, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -2749,9 +2851,11 @@ module Make<
key = "semmle.label" and val = n.toString()
}
private Node getNode(SummaryNode sn) { sn = StepsInput::getSummaryNode(result) }
private predicate edgesComponent(NodeOrCall a, NodeOrCall b, string value) {
exists(boolean preservesValue |
PrivateSteps::summaryLocalStep(a.asNode(), b.asNode(), preservesValue, _) and
PrivateSteps::summaryLocalStep(getNode(a.asNode()), b.asNode(), preservesValue, _) and
if preservesValue = true then value = "value" else value = "taint"
)
or

View File

@@ -305,7 +305,7 @@ private module Cached {
model = ""
or
// flow through a flow summary (extension of `SummaryModelCsv`)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
}

View File

@@ -20,6 +20,8 @@ module Input implements InputSig<Location, DataFlowImplSpecific::SwiftDataFlow>
class SinkBase = Void;
class FlowSummaryCallBase = Void;
predicate callableFromSource(SummarizedCallableBase c) { c.hasBody() }
ArgumentPosition callbackSelfParameterPosition() { result instanceof ThisArgumentPosition }
@@ -113,6 +115,10 @@ module Input implements InputSig<Location, DataFlowImplSpecific::SwiftDataFlow>
private import Make<Location, DataFlowImplSpecific::SwiftDataFlow, Input> as Impl
private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable sc) { result.asCall().getStaticTarget() = sc }
DataFlowCallable getSourceNodeEnclosingCallable(Input::SourceBase source) { none() }

View File

@@ -76,7 +76,7 @@ private module Cached {
model = ""
or
// flow through a flow summary (extension of `SummaryModelCsv`)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
or
any(AdditionalTaintStep a).step(nodeFrom, nodeTo) and model = "AdditionalTaintStep"