mirror of
https://github.com/github/codeql.git
synced 2026-07-02 18:15:33 +02:00
Merge pull request #22061 from MathiasVP/mad-write-through-model
Shared: Support flow summaries from `ReturnValue`s
This commit is contained in:
@@ -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() }
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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 | * ... |
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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() }
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user