mirror of
https://github.com/github/codeql.git
synced 2026-07-02 18:15:33 +02:00
Compare commits
4 Commits
main
...
copilot/ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e38791976e | ||
|
|
068859d338 | ||
|
|
e34375c0cc | ||
|
|
5079680558 |
@@ -6,7 +6,6 @@ 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
|
||||
@@ -21,22 +20,8 @@ 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("") }
|
||||
@@ -45,10 +30,6 @@ 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() }
|
||||
@@ -133,22 +114,10 @@ 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,8 +1534,12 @@ 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 = FlowSummaryImpl::Private::getEnclosingCallable(this.getSummaryNode())
|
||||
result.asSummarizedCallable() = this.getSummarizedCallable()
|
||||
}
|
||||
|
||||
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }
|
||||
|
||||
@@ -561,21 +561,6 @@ class SummaryArgumentNode extends ArgumentNode, FlowSummaryNode {
|
||||
}
|
||||
}
|
||||
|
||||
/** An argument node that re-enters return output as input to a flow summary. */
|
||||
private class FlowSummaryArgumentNode extends ArgumentNode, FlowSummaryNode {
|
||||
private CallInstruction callInstruction;
|
||||
private ReturnKind rk;
|
||||
|
||||
FlowSummaryArgumentNode() {
|
||||
this.getSummaryNode() = FlowSummaryImpl::Private::summaryArgumentNode(callInstruction, rk)
|
||||
}
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
call.asCallInstruction() = callInstruction and
|
||||
pos = TFlowSummaryPosition(rk)
|
||||
}
|
||||
}
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition = Position;
|
||||
|
||||
@@ -631,18 +616,6 @@ 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))
|
||||
@@ -661,8 +634,7 @@ 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,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ private module Cached {
|
||||
model = ""
|
||||
or
|
||||
// models-as-data summarized flow
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
|
||||
or
|
||||
// object->field conflation for content that is a `TaintInheritingContent`.
|
||||
|
||||
@@ -53,17 +53,14 @@ 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: ; 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 |
|
||||
| 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 |
|
||||
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 |
|
||||
@@ -72,16 +69,16 @@ edges
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | |
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp: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:65 |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:62 |
|
||||
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:253:48:253:60 | *call to GetBodyStream | provenance | Src:MaD:29 |
|
||||
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp: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:61 |
|
||||
| azure.cpp:257:5:257:8 | *resp | azure.cpp:257:16:257:21 | Read output argument | provenance | MaD:58 |
|
||||
| azure.cpp:257:16:257:21 | Read output argument | azure.cpp:258:10:258:16 | * ... | provenance | |
|
||||
| azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument | provenance | MaD:62 |
|
||||
| azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument | provenance | MaD:59 |
|
||||
| azure.cpp:262:23:262:28 | ReadToCount output argument | azure.cpp:263:10:263:16 | * ... | provenance | |
|
||||
| azure.cpp:266:38:266:41 | *resp | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | MaD:63 |
|
||||
| azure.cpp:266:38:266:41 | *resp | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | MaD:60 |
|
||||
| azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | |
|
||||
| azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:267:10:267:12 | vec [element] | provenance | |
|
||||
| azure.cpp:267:10:267:12 | vec [element] | azure.cpp:267:10:267:12 | vec | provenance | |
|
||||
@@ -97,10 +94,10 @@ edges
|
||||
| azure.cpp:278:10:278:13 | body | azure.cpp:278:10:278:13 | body | provenance | |
|
||||
| azure.cpp: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:63 |
|
||||
| azure.cpp:282:21:282:23 | *call to get | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | MaD:60 |
|
||||
| azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:10:282:38 | call to ReadToEnd | provenance | |
|
||||
| azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | |
|
||||
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:64 |
|
||||
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:61 |
|
||||
| azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:24:289:56 | call to GetHeader | provenance | |
|
||||
| azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289: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 | |
|
||||
@@ -162,27 +159,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:59 |
|
||||
| test.cpp:134:45:134:45 | x | test.cpp:134:13:134:43 | call to templateFunction | provenance | MaD:56 |
|
||||
| test.cpp:146:10:146:18 | call to ymlSource | test.cpp:146:10:146:18 | call to ymlSource | provenance | Src:MaD:25 |
|
||||
| test.cpp:146:10:146:18 | call to ymlSource | test.cpp: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:60 |
|
||||
| test.cpp:148:26:148:26 | x | test.cpp:148:10:148:27 | call to function | provenance | MaD:57 |
|
||||
| test.cpp:155:10:155:18 | call to ymlSource | test.cpp:155:10:155:18 | call to ymlSource | provenance | Src:MaD:25 |
|
||||
| test.cpp:155:10:155:18 | call to ymlSource | test.cpp: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:60 |
|
||||
| test.cpp:157:26:157:26 | x | test.cpp:157:13:157:20 | call to function | provenance | MaD:57 |
|
||||
| test.cpp:164:34:164:34 | x | test.cpp:165:69:165:69 | x | provenance | |
|
||||
| test.cpp: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:58 |
|
||||
| test.cpp:165:69:165:69 | x | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | MaD:55 |
|
||||
| test.cpp:170:10:170:18 | call to ymlSource | test.cpp:170:10:170:18 | call to ymlSource | provenance | Src:MaD:25 |
|
||||
| test.cpp:170:10:170:18 | call to ymlSource | test.cpp: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:58 |
|
||||
| test.cpp:172:51:172:51 | x | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | MaD:55 |
|
||||
| test.cpp:186:2:186:2 | *s [post update] [myField] | test.cpp:187:33:187:34 | *& ... [myField] | provenance | |
|
||||
| test.cpp:186:2:186: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 |
|
||||
@@ -195,18 +192,6 @@ edges
|
||||
| test.cpp:200:10:200:33 | call to read_field_from_struct_2 | test.cpp:200:10:200:33 | call to read_field_from_struct_2 | provenance | |
|
||||
| test.cpp:200:10:200:33 | call to read_field_from_struct_2 | test.cpp: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 | |
|
||||
@@ -485,20 +470,6 @@ nodes
|
||||
| test.cpp:200:10:200:33 | call to read_field_from_struct_2 | semmle.label | call to read_field_from_struct_2 |
|
||||
| test.cpp:200: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,7 +23,4 @@ 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"]
|
||||
- ["", "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"]
|
||||
- ["", "", False, "read_field_from_struct_2", "", "", "Argument[*0].Field[MyGlobalStruct::myField]", "ReturnValue", "value", "manual"]
|
||||
@@ -21,5 +21,3 @@
|
||||
| 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,8 +15,6 @@
|
||||
| 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,28 +199,4 @@ 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,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ 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)
|
||||
}
|
||||
@@ -203,10 +201,6 @@ 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,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +186,13 @@ private Expr aspWrittenValue(AspInlineMember m) {
|
||||
m.getMember().(Callable).canReturn(result)
|
||||
}
|
||||
|
||||
private string makeUrl(Location l) {
|
||||
exists(string path, int sl, int sc, int el, int ec |
|
||||
l.hasLocationInfo(path, sl, sc, el, ec) and
|
||||
result = "file://" + path + ":" + sl + ":" + sc + ":" + el + ":" + ec
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink for writes to properties that are accessed in ASP pages.
|
||||
*
|
||||
@@ -201,7 +208,10 @@ private class AspxCodeSink extends Sink {
|
||||
|
||||
AspxCodeSink() { this.getExpr() = aspWrittenValue(inline) }
|
||||
|
||||
override string explanation() { result = "member is accessed inline in an ASPX page" }
|
||||
override string explanation() {
|
||||
result =
|
||||
"member is [[\"accessed inline\"|\"" + makeUrl(inline.getLocation()) + "\"]] in an ASPX page"
|
||||
}
|
||||
}
|
||||
|
||||
/** A sink for the output stream associated with a `HttpListenerResponse`. */
|
||||
|
||||
@@ -19,6 +19,7 @@ go_library(
|
||||
"//go/extractor/dbscheme",
|
||||
"//go/extractor/diagnostics",
|
||||
"//go/extractor/srcarchive",
|
||||
"//go/extractor/subst",
|
||||
"//go/extractor/toolchain",
|
||||
"//go/extractor/trap",
|
||||
"//go/extractor/util",
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/github/codeql-go/extractor/dbscheme"
|
||||
"github.com/github/codeql-go/extractor/diagnostics"
|
||||
"github.com/github/codeql-go/extractor/srcarchive"
|
||||
"github.com/github/codeql-go/extractor/subst"
|
||||
"github.com/github/codeql-go/extractor/toolchain"
|
||||
"github.com/github/codeql-go/extractor/trap"
|
||||
"github.com/github/codeql-go/extractor/util"
|
||||
@@ -764,9 +765,9 @@ func normalizedPath(ast *ast.File, fset *token.FileSet) string {
|
||||
file := fset.File(ast.Package).Name()
|
||||
path, err := filepath.EvalSymlinks(file)
|
||||
if err != nil {
|
||||
return file
|
||||
path = file
|
||||
}
|
||||
return path
|
||||
return subst.ResolvePath(path)
|
||||
}
|
||||
|
||||
// extractFile extracts AST information for the given file
|
||||
|
||||
12
go/extractor/subst/BUILD.bazel
generated
Normal file
12
go/extractor/subst/BUILD.bazel
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
load("@rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "subst",
|
||||
srcs = [
|
||||
"subst.go",
|
||||
"subst_other.go",
|
||||
"subst_windows.go",
|
||||
],
|
||||
importpath = "github.com/github/codeql-go/extractor/subst",
|
||||
visibility = ["//go:__subpackages__"],
|
||||
)
|
||||
30
go/extractor/subst/subst.go
Normal file
30
go/extractor/subst/subst.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package subst
|
||||
|
||||
// ResolvePath resolves subst'd drive letters in a full path.
|
||||
// If the path starts with a subst'd drive letter, replaces it with the backing path.
|
||||
// Otherwise returns the path unchanged.
|
||||
func ResolvePath(path string) string {
|
||||
return resolvePath(path, ResolveDrive)
|
||||
}
|
||||
|
||||
func resolvePath(path string, resolveDrive func(string) string) string {
|
||||
if len(path) < 3 {
|
||||
return path
|
||||
}
|
||||
if path[1] != ':' {
|
||||
return path
|
||||
}
|
||||
if path[2] != '\\' && path[2] != '/' {
|
||||
return path
|
||||
}
|
||||
c := path[0]
|
||||
if !((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
|
||||
return path
|
||||
}
|
||||
|
||||
resolved := resolveDrive(path[:3])
|
||||
if resolved == "" {
|
||||
return path
|
||||
}
|
||||
return resolved + path[2:]
|
||||
}
|
||||
6
go/extractor/subst/subst_other.go
Normal file
6
go/extractor/subst/subst_other.go
Normal file
@@ -0,0 +1,6 @@
|
||||
//go:build !windows
|
||||
|
||||
package subst
|
||||
|
||||
// ResolveDrive is a no-op on non-Windows platforms.
|
||||
func ResolveDrive(driveRoot string) string { return "" }
|
||||
67
go/extractor/subst/subst_windows.go
Normal file
67
go/extractor/subst/subst_windows.go
Normal file
@@ -0,0 +1,67 @@
|
||||
//go:build windows
|
||||
|
||||
package subst
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
dll *syscall.DLL
|
||||
procResolve *syscall.Proc
|
||||
procFree *syscall.Proc
|
||||
available bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
dist := os.Getenv("CODEQL_DIST")
|
||||
if dist == "" {
|
||||
return
|
||||
}
|
||||
dllPath := filepath.Join(dist, "tools", "win64", "canonicalize.dll")
|
||||
d, err := syscall.LoadDLL(dllPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p, err := d.FindProc("resolve_subst_u8")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
f, _ := d.FindProc("resolve_subst_free_u8")
|
||||
dll = d
|
||||
procResolve = p
|
||||
procFree = f
|
||||
available = true
|
||||
}
|
||||
|
||||
// ResolveDrive resolves a subst'd drive root (e.g. "X:\") to its backing path.
|
||||
// Returns "" if the drive is not subst'd or on error.
|
||||
func ResolveDrive(driveRoot string) string {
|
||||
if !available {
|
||||
return ""
|
||||
}
|
||||
driveBytes := append([]byte(driveRoot), 0)
|
||||
ret, _, _ := procResolve.Call(uintptr(unsafe.Pointer(&driveBytes[0])))
|
||||
if ret == 0 {
|
||||
return ""
|
||||
}
|
||||
result := goString((*byte)(unsafe.Pointer(ret)))
|
||||
if procFree != nil {
|
||||
procFree.Call(ret)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func goString(p *byte) string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
var n int
|
||||
for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ {
|
||||
ptr = unsafe.Add(ptr, 1)
|
||||
}
|
||||
return string(unsafe.Slice(p, n))
|
||||
}
|
||||
@@ -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,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::GoDataFlow> {
|
||||
|
||||
class SinkBase = Void;
|
||||
|
||||
class FlowSummaryCallBase = Void;
|
||||
|
||||
predicate callableFromSource(SummarizedCallableBase c) { exists(c.getFuncDef()) }
|
||||
|
||||
predicate neutralElement(
|
||||
@@ -115,10 +113,6 @@ 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,
|
||||
succ.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(DataFlowPrivate::FlowSummaryNode)
|
||||
.getSummaryNode(), succ.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -188,8 +188,6 @@ org.apache.hadoop.hive.ql.metadata,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.async.methods,84,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,84,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.classic.methods,37,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.fluent,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.protocol,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
org.apache.hc.client5.http.utils,,,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,
|
||||
org.apache.hc.core5.benchmark,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.hc.core5.http,73,2,45,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,72,,,,,,,,,,,,,,,,2,45,
|
||||
|
||||
|
@@ -40,6 +40,6 @@ Java framework & library support
|
||||
`Spring <https://spring.io/>`_,``org.springframework.*``,46,494,143,26,,28,14,,35
|
||||
`Thymeleaf <https://www.thymeleaf.org/>`_,``org.thymeleaf``,,2,2,,,,,,
|
||||
`jOOQ <https://www.jooq.org/>`_,``org.jooq``,,,1,,,1,,,
|
||||
Others,"``actions.osgi``, ``antlr``, ``ch.ethz.ssh2``, ``cn.hutool.core.codec``, ``com.alibaba.com.caucho.hessian.io``, ``com.alibaba.druid.sql``, ``com.alibaba.fastjson2``, ``com.amazonaws.auth``, ``com.auth0.jwt.algorithms``, ``com.azure.identity``, ``com.caucho.burlap.io``, ``com.caucho.hessian.io``, ``com.cedarsoftware.util.io``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.esotericsoftware.yamlbeans``, ``com.hubspot.jinjava``, ``com.jcraft.jsch``, ``com.microsoft.sqlserver.jdbc``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2``, ``com.sshtools.j2ssh.authentication``, ``com.sun.crypto.provider``, ``com.sun.jndi.ldap``, ``com.sun.net.httpserver``, ``com.sun.net.ssl``, ``com.sun.rowset``, ``com.sun.security.auth.module``, ``com.sun.security.ntlm``, ``com.sun.security.sasl.digest``, ``com.thoughtworks.xstream``, ``com.trilead.ssh2``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``hudson``, ``io.jsonwebtoken``, ``io.undertow.server.handlers.resource``, ``javafx.scene.web``, ``jenkins``, ``jodd.json``, ``liquibase.database.jvm``, ``liquibase.statement.core``, ``net.lingala.zip4j``, ``net.schmizz.sshj``, ``net.sf.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.acegisecurity``, ``org.antlr.runtime``, ``org.apache.avro``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.exec``, ``org.apache.commons.fileupload``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.lang``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.cxf.catalog``, ``org.apache.cxf.common.classloader``, ``org.apache.cxf.common.jaxb``, ``org.apache.cxf.common.logging``, ``org.apache.cxf.configuration.jsse``, ``org.apache.cxf.helpers``, ``org.apache.cxf.resource``, ``org.apache.cxf.staxutils``, ``org.apache.cxf.tools.corba.utils``, ``org.apache.cxf.tools.util``, ``org.apache.cxf.transform``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hadoop.hive.ql.exec``, ``org.apache.hadoop.hive.ql.metadata``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hc.client5.http.protocol``, ``org.apache.hc.client5.http.utils``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.ibatis.mapping``, ``org.apache.log4j``, ``org.apache.shiro.authc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.shiro.mgt``, ``org.apache.sshd.client.session``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.codehaus.cargo.container.installer``, ``org.dom4j``, ``org.exolab.castor.xml``, ``org.fusesource.leveldbjni``, ``org.geogebra.web.full.main``, ``org.gradle.api.file``, ``org.ho.yaml``, ``org.influxdb``, ``org.jabsorb``, ``org.jboss.vfs``, ``org.jdbi.v3.core``, ``org.jenkins.ui.icon``, ``org.jenkins.ui.symbol``, ``org.keycloak.models.map.storage``, ``org.kohsuke.stapler``, ``org.lastaflute.web``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.owasp.esapi``, ``org.pac4j.jwt.config.encryption``, ``org.pac4j.jwt.config.signature``, ``org.scijava.log``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.libs.ws``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``software.amazon.awssdk.transfer.s3.model``, ``sun.jvmstat.perfdata.monitor.protocol.local``, ``sun.jvmstat.perfdata.monitor.protocol.rmi``, ``sun.misc``, ``sun.net.ftp``, ``sun.net.www.protocol.http``, ``sun.security.acl``, ``sun.security.jgss.krb5``, ``sun.security.krb5``, ``sun.security.pkcs``, ``sun.security.pkcs11``, ``sun.security.provider``, ``sun.security.ssl``, ``sun.security.x509``, ``sun.tools.jconsole``",127,6042,775,148,6,14,18,,186
|
||||
Totals,,382,26411,2707,421,16,137,33,1,415
|
||||
Others,"``actions.osgi``, ``antlr``, ``ch.ethz.ssh2``, ``cn.hutool.core.codec``, ``com.alibaba.com.caucho.hessian.io``, ``com.alibaba.druid.sql``, ``com.alibaba.fastjson2``, ``com.amazonaws.auth``, ``com.auth0.jwt.algorithms``, ``com.azure.identity``, ``com.caucho.burlap.io``, ``com.caucho.hessian.io``, ``com.cedarsoftware.util.io``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.esotericsoftware.yamlbeans``, ``com.hubspot.jinjava``, ``com.jcraft.jsch``, ``com.microsoft.sqlserver.jdbc``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2``, ``com.sshtools.j2ssh.authentication``, ``com.sun.crypto.provider``, ``com.sun.jndi.ldap``, ``com.sun.net.httpserver``, ``com.sun.net.ssl``, ``com.sun.rowset``, ``com.sun.security.auth.module``, ``com.sun.security.ntlm``, ``com.sun.security.sasl.digest``, ``com.thoughtworks.xstream``, ``com.trilead.ssh2``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``hudson``, ``io.jsonwebtoken``, ``io.undertow.server.handlers.resource``, ``javafx.scene.web``, ``jenkins``, ``jodd.json``, ``liquibase.database.jvm``, ``liquibase.statement.core``, ``net.lingala.zip4j``, ``net.schmizz.sshj``, ``net.sf.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.acegisecurity``, ``org.antlr.runtime``, ``org.apache.avro``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.exec``, ``org.apache.commons.fileupload``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.lang``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.cxf.catalog``, ``org.apache.cxf.common.classloader``, ``org.apache.cxf.common.jaxb``, ``org.apache.cxf.common.logging``, ``org.apache.cxf.configuration.jsse``, ``org.apache.cxf.helpers``, ``org.apache.cxf.resource``, ``org.apache.cxf.staxutils``, ``org.apache.cxf.tools.corba.utils``, ``org.apache.cxf.tools.util``, ``org.apache.cxf.transform``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hadoop.hive.ql.exec``, ``org.apache.hadoop.hive.ql.metadata``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.ibatis.mapping``, ``org.apache.log4j``, ``org.apache.shiro.authc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.shiro.mgt``, ``org.apache.sshd.client.session``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.codehaus.cargo.container.installer``, ``org.dom4j``, ``org.exolab.castor.xml``, ``org.fusesource.leveldbjni``, ``org.geogebra.web.full.main``, ``org.gradle.api.file``, ``org.ho.yaml``, ``org.influxdb``, ``org.jabsorb``, ``org.jboss.vfs``, ``org.jdbi.v3.core``, ``org.jenkins.ui.icon``, ``org.jenkins.ui.symbol``, ``org.keycloak.models.map.storage``, ``org.kohsuke.stapler``, ``org.lastaflute.web``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.owasp.esapi``, ``org.pac4j.jwt.config.encryption``, ``org.pac4j.jwt.config.signature``, ``org.scijava.log``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.libs.ws``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``software.amazon.awssdk.transfer.s3.model``, ``sun.jvmstat.perfdata.monitor.protocol.local``, ``sun.jvmstat.perfdata.monitor.protocol.rmi``, ``sun.misc``, ``sun.net.ftp``, ``sun.net.www.protocol.http``, ``sun.security.acl``, ``sun.security.jgss.krb5``, ``sun.security.krb5``, ``sun.security.pkcs``, ``sun.security.pkcs11``, ``sun.security.provider``, ``sun.security.ssl``, ``sun.security.x509``, ``sun.tools.jconsole``",127,6034,775,148,6,14,18,,186
|
||||
Totals,,382,26403,2707,421,16,137,33,1,415
|
||||
|
||||
|
||||
@@ -1242,12 +1242,13 @@ public class FileUtil
|
||||
public static File tryMakeCanonical (File f)
|
||||
{
|
||||
try {
|
||||
return f.getCanonicalFile();
|
||||
f = f.getCanonicalFile();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
Exceptions.ignore(ignored, "Can't log error: Could be too verbose.");
|
||||
return new File(simplifyPath(f));
|
||||
f = new File(simplifyPath(f));
|
||||
}
|
||||
return SubstResolver.resolve(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.semmle.util.files;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* Resolves Windows {@code subst}ed drive letters to their underlying paths. On non-Windows
|
||||
* platforms, or when the native library failed to load, {@link #resolve(File)} is a no-op that
|
||||
* returns its argument unchanged.
|
||||
*/
|
||||
public class SubstResolver {
|
||||
private static final boolean available;
|
||||
|
||||
static {
|
||||
boolean loaded = false;
|
||||
if (File.separatorChar == '\\') {
|
||||
String dist = System.getenv("CODEQL_DIST");
|
||||
if (dist != null && !dist.isEmpty()) {
|
||||
try {
|
||||
Path library = Paths.get(dist).resolve("tools").resolve("win64")
|
||||
.resolve("canonicalize.dll").toAbsolutePath();
|
||||
System.load(library.toString());
|
||||
loaded = true;
|
||||
} catch (RuntimeException | UnsatisfiedLinkError ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
available = loaded;
|
||||
}
|
||||
|
||||
private SubstResolver() {}
|
||||
|
||||
/**
|
||||
* Given a drive root like {@code "X:\\"}, returns the path that drive is
|
||||
* {@code subst}ed to, or {@code null} if the letter isn't a subst mapping.
|
||||
*/
|
||||
private static native String nativeResolveSubst(String driveRoot);
|
||||
|
||||
/**
|
||||
* If {@code f} is an absolute path starting with a {@code subst}ed drive letter, return an
|
||||
* equivalent path with the drive letter replaced by its target. Otherwise return {@code f}
|
||||
* unchanged.
|
||||
*/
|
||||
public static File resolve(File f) {
|
||||
if (!available) {
|
||||
return f;
|
||||
}
|
||||
String path = f.getPath();
|
||||
if (path.length() < 3 || path.charAt(1) != ':') {
|
||||
return f;
|
||||
}
|
||||
char sep = path.charAt(2);
|
||||
if (sep != '\\' && sep != '/') {
|
||||
return f;
|
||||
}
|
||||
if (!isDriveLetter(path.charAt(0))) {
|
||||
return f;
|
||||
}
|
||||
|
||||
String resolved = nativeResolveSubst(path.substring(0, 3));
|
||||
if (resolved == null) {
|
||||
return f;
|
||||
}
|
||||
|
||||
return new File(resolved + path.substring(2));
|
||||
}
|
||||
|
||||
private static boolean isDriveLetter(char c) {
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
public static boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
}
|
||||
@@ -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, node2.(FlowSummaryNode).getSummaryNode(),
|
||||
true, model)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
|
||||
node2.(FlowSummaryNode).getSummaryNode(), true, model)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,8 +41,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::JavaDataFlow> {
|
||||
|
||||
class SinkBase = Void;
|
||||
|
||||
class FlowSummaryCallBase = Void;
|
||||
|
||||
predicate neutralElement(
|
||||
Input::SummarizedCallableBase c, string kind, string provenance, boolean isExact
|
||||
) {
|
||||
@@ -146,10 +144,6 @@ private module TypesInput implements Impl::Private::TypesInputSig {
|
||||
}
|
||||
|
||||
private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
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,
|
||||
sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src.(DataFlowPrivate::FlowSummaryNode)
|
||||
.getSummaryNode(), sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,8 @@ predicate taintFlowUpdate(DataFlow::ParameterNode p1, DataFlow::ParameterNode p2
|
||||
}
|
||||
|
||||
predicate summaryStep(FlowSummaryNode src, FlowSummaryNode sink) {
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink.getSummaryNode(), false, _) or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src.getSummaryNode(), sink.getSummaryNode(),
|
||||
false, _) or
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(src.getSummaryNode(), _, sink.getSummaryNode()) or
|
||||
FlowSummaryImpl::Private::Steps::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, node2.(FlowSummaryNode).getSummaryNode(), true,
|
||||
_) // TODO: preserve 'model'
|
||||
FlowSummaryPrivate::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
|
||||
node2.(FlowSummaryNode).getSummaryNode(), true, _) // TODO: preserve 'model'
|
||||
}
|
||||
|
||||
predicate knownSourceModel(Node sink, string model) { none() }
|
||||
|
||||
@@ -142,10 +142,6 @@ 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, node2.(FlowSummaryNode).getSummaryNode(),
|
||||
false, _) // TODO: preserve 'model' parameter
|
||||
FlowSummaryPrivate::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
|
||||
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,7 +3,6 @@ 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
|
||||
@@ -29,8 +28,6 @@ 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() }
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ No user-facing changes.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added new full SSRF sanitization barrier from the new AntiSSRF library.
|
||||
* Added new full SSRF sanitization barrier from the new AntiSSRF library.
|
||||
* When a guard such as `isSafe(x)` is defined, we now also automatically handle `isSafe(x) == true` and `isSafe(x) != false`.
|
||||
|
||||
## 6.1.1
|
||||
@@ -169,7 +169,7 @@ No user-facing changes.
|
||||
### Minor Analysis Improvements
|
||||
|
||||
- The modelling of Psycopg2 now supports the use of `psycopg2.pool` connection pools for handling database connections.
|
||||
* Removed `lxml` as an XML bomb sink. The underlying libxml2 library now includes [entity reference loop detection](https://github.com/lxml/lxml/blob/f33ac2c2f5f9c4c4c1fc47f363be96db308f2fa6/doc/FAQ.txt#L1077) that prevents XML bomb attacks.
|
||||
* Removed `lxml` as an XML bomb sink. The underlying libxml2 library now includes [entity reference loop detection](https://github.com/lxml/lxml/blob/f33ac2c2f5f9c4c4c1fc47f363be96db308f2fa6/doc/FAQ.txt#L1077) that prevents XML bomb attacks.
|
||||
|
||||
## 4.0.13
|
||||
|
||||
@@ -262,7 +262,7 @@ No user-facing changes.
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The sensitive data library has been improved so that `snake_case` style variable names are recognized more reliably. This may result in more sensitive data being identified, and more results from queries that use the sensitive data library.
|
||||
- Additional taint steps through methods of `lxml.etree.Element` and `lxml.etree.ElementTree` objects from the `lxml` PyPI package have been modeled.
|
||||
- Additional taint steps through methods of `lxml.etree.Element` and `lxml.etree.ElementTree` objects from the `lxml` PyPI package have been modeled.
|
||||
|
||||
## 3.1.0
|
||||
|
||||
@@ -316,7 +316,7 @@ No user-facing changes.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The common sanitizer guard `StringConstCompareBarrier` has been renamed to `ConstCompareBarrier` and expanded to cover comparisons with other constant values such as `None`. This may result in fewer false positive results for several queries.
|
||||
* The common sanitizer guard `StringConstCompareBarrier` has been renamed to `ConstCompareBarrier` and expanded to cover comparisons with other constant values such as `None`. This may result in fewer false positive results for several queries.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
@@ -545,7 +545,7 @@ No user-facing changes.
|
||||
|
||||
### New Features
|
||||
|
||||
* The `DataFlow::StateConfigSig` signature module has gained default implementations for `isBarrier/2` and `isAdditionalFlowStep/4`.
|
||||
* The `DataFlow::StateConfigSig` signature module has gained default implementations for `isBarrier/2` and `isAdditionalFlowStep/4`.
|
||||
Hence it is no longer needed to provide `none()` implementations of these predicates if they are not needed.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
@@ -572,7 +572,7 @@ No user-facing changes.
|
||||
* Deleted many deprecated predicates and classes with uppercase `API`, `HTTP`, `XSS`, `SQL`, etc. in their names. Use the PascalCased versions instead.
|
||||
* Deleted the deprecated `getName()` predicate from the `Container` class, use `getAbsolutePath()` instead.
|
||||
* Deleted many deprecated module names that started with a lowercase letter, use the versions that start with an uppercase letter instead.
|
||||
* Deleted many deprecated predicates in `PointsTo.qll`.
|
||||
* Deleted many deprecated predicates in `PointsTo.qll`.
|
||||
* Deleted many deprecated files from the `semmle.python.security` package.
|
||||
* Deleted the deprecated `BottleRoutePointToExtension` class from `Extensions.qll`.
|
||||
* Type tracking is now aware of flow summaries. This leads to a richer API graph, and may lead to more results in some queries.
|
||||
@@ -729,7 +729,7 @@ No user-facing changes.
|
||||
### Deprecated APIs
|
||||
|
||||
* Some unused predicates in `SsaDefinitions.qll`, `TObject.qll`, `protocols.qll`, and the `pointsto/` folder have been deprecated.
|
||||
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
@@ -748,9 +748,9 @@ No user-facing changes.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
* The utility files previously in the `semmle.python.security.performance` package have been moved to the `semmle.python.security.regexp` package.
|
||||
* The utility files previously in the `semmle.python.security.performance` package have been moved to the `semmle.python.security.regexp` package.
|
||||
The previous files still exist as deprecated aliases.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
@@ -843,9 +843,9 @@ No user-facing changes.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
* Some modules that started with a lowercase letter have been renamed to follow our style-guide.
|
||||
* Some modules that started with a lowercase letter have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -529,7 +529,7 @@ predicate simpleLocalFlowStepForTypetracking(Node nodeFrom, Node nodeTo) {
|
||||
}
|
||||
|
||||
private predicate summaryLocalStep(Node nodeFrom, Node nodeTo, string model) {
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
|
||||
|
||||
class SinkBase = Void;
|
||||
|
||||
class FlowSummaryCallBase = Void;
|
||||
|
||||
predicate callableFromSource(SummarizedCallableBase c) { none() }
|
||||
|
||||
ArgumentPosition callbackSelfParameterPosition() { result.isLambdaSelf() }
|
||||
@@ -113,10 +111,6 @@ 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,8 +80,10 @@ private module Cached {
|
||||
) and
|
||||
model = ""
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
|
||||
nodeTo.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom
|
||||
.(DataFlowPrivate::FlowSummaryNode)
|
||||
.getSummaryNode(), nodeTo.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false,
|
||||
model)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -170,13 +170,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
||||
|
||||
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */
|
||||
predicate levelStepCall(Node nodeFrom, LocalSourceNode nodeTo) {
|
||||
// HOTFIX: `instanceFieldStep` is temporarily disabled (via `and none()`).
|
||||
// It uses `classInstanceTracker(cls)` -- itself a type-tracker run --
|
||||
// from inside `levelStepCall`, creating a structural mutual recursion
|
||||
// that causes catastrophic query slowdowns on some OOP-heavy Python
|
||||
// codebases (e.g. mypy and dask). The `and none()` should be removed
|
||||
// once that recursion is redesigned.
|
||||
instanceFieldStep(nodeFrom, nodeTo) and none()
|
||||
instanceFieldStep(nodeFrom, nodeTo)
|
||||
or
|
||||
inheritedFieldStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ class MyClass2(object):
|
||||
print(self.foo) # $ tracked MISSING: tracked=foo
|
||||
|
||||
instance = MyClass2()
|
||||
print(instance.foo) # $ MISSING: tracked=foo tracked
|
||||
print(instance.foo) # $ tracked MISSING: tracked=foo
|
||||
instance.print_foo() # $ MISSING: tracked=foo
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ class Sub1(Base1):
|
||||
|
||||
sub1 = Sub1()
|
||||
sub1.read_foo()
|
||||
print(sub1.foo) # $ MISSING: tracked=foo tracked
|
||||
print(sub1.foo) # $ tracked MISSING: tracked=foo
|
||||
|
||||
|
||||
# attribute written in a subclass method, read in an inherited base class method
|
||||
@@ -210,7 +210,7 @@ class Sub2(Base2):
|
||||
|
||||
sub2 = Sub2()
|
||||
sub2.read_bar()
|
||||
print(sub2.bar) # $ MISSING: tracked=bar tracked
|
||||
print(sub2.bar) # $ tracked MISSING: tracked=bar
|
||||
|
||||
|
||||
# attribute written in a base class method, read on an instance of the subclass
|
||||
@@ -223,4 +223,4 @@ class Sub3(Base3):
|
||||
pass
|
||||
|
||||
sub3 = Sub3()
|
||||
print(sub3.baz) # $ MISSING: tracked=baz tracked
|
||||
print(sub3.baz) # $ tracked MISSING: tracked=baz
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#select
|
||||
| app.py:23:20:23:24 | ControlFlowNode for query | app.py:20:18:20:21 | ControlFlowNode for name | app.py:23:20:23:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:20:18:20:21 | ControlFlowNode for name | user-provided value |
|
||||
| app.py:30:20:30:24 | ControlFlowNode for query | app.py:27:19:27:22 | ControlFlowNode for name | app.py:30:20:30:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:27:19:27:22 | ControlFlowNode for name | user-provided value |
|
||||
| app.py:37:20:37:24 | ControlFlowNode for query | app.py:34:19:34:22 | ControlFlowNode for name | app.py:37:20:37:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:34:19:34:22 | ControlFlowNode for name | user-provided value |
|
||||
| app.py:44:20:44:24 | ControlFlowNode for query | app.py:41:19:41:22 | ControlFlowNode for name | app.py:44:20:44:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:41:19:41:22 | ControlFlowNode for name | user-provided value |
|
||||
| app.py:51:20:51:24 | ControlFlowNode for query | app.py:48:19:48:22 | ControlFlowNode for name | app.py:51:20:51:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:48:19:48:22 | ControlFlowNode for name | user-provided value |
|
||||
| sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
|
||||
@@ -24,6 +25,8 @@ edges
|
||||
| app.py:21:5:21:9 | ControlFlowNode for query | app.py:23:20:23:24 | ControlFlowNode for query | provenance | |
|
||||
| app.py:27:19:27:22 | ControlFlowNode for name | app.py:28:5:28:9 | ControlFlowNode for query | provenance | |
|
||||
| app.py:28:5:28:9 | ControlFlowNode for query | app.py:30:20:30:24 | ControlFlowNode for query | provenance | |
|
||||
| app.py:34:19:34:22 | ControlFlowNode for name | app.py:35:5:35:9 | ControlFlowNode for query | provenance | |
|
||||
| app.py:35:5:35:9 | ControlFlowNode for query | app.py:37:20:37:24 | ControlFlowNode for query | provenance | |
|
||||
| app.py:41:19:41:22 | ControlFlowNode for name | app.py:42:5:42:9 | ControlFlowNode for query | provenance | |
|
||||
| app.py:42:5:42:9 | ControlFlowNode for query | app.py:44:20:44:24 | ControlFlowNode for query | provenance | |
|
||||
| app.py:48:19:48:22 | ControlFlowNode for name | app.py:49:5:49:9 | ControlFlowNode for query | provenance | |
|
||||
@@ -51,6 +54,9 @@ nodes
|
||||
| app.py:27:19:27:22 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
|
||||
| app.py:28:5:28:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||
| app.py:30:20:30:24 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||
| app.py:34:19:34:22 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
|
||||
| app.py:35:5:35:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||
| app.py:37:20:37:24 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||
| app.py:41:19:41:22 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
|
||||
| app.py:42:5:42:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||
| app.py:44:20:44:24 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||
|
||||
@@ -31,10 +31,10 @@ async def unsafe2(name: str): # $ Source
|
||||
cursor.close()
|
||||
|
||||
@app.get("/unsafe3/")
|
||||
async def unsafe3(name: str): # $ MISSING: Source
|
||||
async def unsafe3(name: str): # $ Source
|
||||
query = "select * from users where name=" + name
|
||||
cursor = hdb_con3.cursor()
|
||||
cursor.execute(query) # $ MISSING: Alert
|
||||
cursor.execute(query) # $ Alert
|
||||
cursor.close()
|
||||
|
||||
@app.get("/unsafe4/")
|
||||
|
||||
@@ -198,7 +198,8 @@ module LocalFlow {
|
||||
FlowSummaryNode nodeFrom, FlowSummaryNode nodeTo, FlowSummaryImpl::Public::SummarizedCallable c,
|
||||
string model
|
||||
) {
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo.getSummaryNode(), true, model) and
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.getSummaryNode(),
|
||||
nodeTo.getSummaryNode(), true, model) and
|
||||
c = nodeFrom.getSummarizedCallable()
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::RubyDataFlow> {
|
||||
|
||||
class SinkBase = Void;
|
||||
|
||||
class FlowSummaryCallBase = Void;
|
||||
|
||||
predicate callableFromSource(SummarizedCallableBase c) { none() }
|
||||
|
||||
ArgumentPosition callbackSelfParameterPosition() { result.isLambdaSelf() }
|
||||
@@ -159,10 +157,6 @@ 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,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
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,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model) and
|
||||
c = nodeFrom.(FlowSummaryNode).getSummarizedCallable()
|
||||
)
|
||||
|
||||
@@ -11,7 +11,6 @@ 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 |
|
||||
@@ -29,12 +28,9 @@ 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 {
|
||||
@@ -148,10 +144,6 @@ 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,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(Node::FlowSummaryNode).getSummaryNode(),
|
||||
succ.(Node::FlowSummaryNode).getSummaryNode(), false, model)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
multipleResolvedTargets
|
||||
| main.rs:2240:9:2240:31 | ... .my_add(...) |
|
||||
| main.rs:2242:9:2242:29 | ... .my_add(...) |
|
||||
| main.rs:2757:13:2757:17 | x.f() |
|
||||
| main.rs:2223:9:2223:31 | ... .my_add(...) |
|
||||
| main.rs:2225:9:2225:29 | ... .my_add(...) |
|
||||
| main.rs:2740:13:2740:17 | x.f() |
|
||||
| regressions.rs:179:17:179:27 | ... + ... |
|
||||
|
||||
@@ -264,10 +264,6 @@ mod method_non_parametric_trait_impl {
|
||||
}
|
||||
}
|
||||
|
||||
trait MyTrait2<B> {
|
||||
fn m3(self) -> B;
|
||||
}
|
||||
|
||||
trait MyProduct<A, B> {
|
||||
// MyProduct::fst
|
||||
fn fst(self) -> A;
|
||||
@@ -279,10 +275,6 @@ mod method_non_parametric_trait_impl {
|
||||
x.m1() // $ target=m1
|
||||
}
|
||||
|
||||
fn call_trait_m1_trait2_m3<T1, T2: MyTrait<T1>, T3: MyTrait2<T2>>(x: T3) -> T1 {
|
||||
x.m3().m1() // $ target=m1 target=m3
|
||||
}
|
||||
|
||||
impl MyTrait<S1> for MyThing<S1> {
|
||||
// MyThing<S1>::m1
|
||||
fn m1(self) -> S1 {
|
||||
@@ -297,13 +289,6 @@ mod method_non_parametric_trait_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl MyTrait2<MyThing<S1>> for MyThing<S2> {
|
||||
// MyThing<S2>::m3
|
||||
fn m3(self) -> MyThing<S1> {
|
||||
MyThing { a: S1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation where the type parameter `TD` only occurs in the
|
||||
// implemented trait and not the implementing type.
|
||||
impl<TD> MyTrait<TD> for MyThing<S3>
|
||||
@@ -468,8 +453,6 @@ mod method_non_parametric_trait_impl {
|
||||
let thing = MyThing { a: S1 };
|
||||
let i = thing.convert_to(); // $ type=i:S1 target=T::convert_to
|
||||
let j = convert_to(thing); // $ target=convert_to $ MISSING: type=j:S1 -- the blanket implementation `impl<T: MyTrait<S1>> ConvertTo<S1> for T` is currently not included in the constraint analysis
|
||||
|
||||
let x = call_trait_m1_trait2_m3(MyThing { a: S2 }); // $ target=call_trait_m1_trait2_m3 type=x:S1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -54,24 +54,6 @@ 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() }
|
||||
|
||||
@@ -92,9 +74,6 @@ 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);
|
||||
|
||||
@@ -681,10 +660,6 @@ 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
|
||||
@@ -1162,13 +1137,6 @@ 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
|
||||
@@ -1304,12 +1272,6 @@ 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
|
||||
@@ -1359,40 +1321,6 @@ 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_;
|
||||
@@ -1499,12 +1427,6 @@ 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)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1638,9 +1560,6 @@ 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.
|
||||
@@ -1817,15 +1736,9 @@ 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);
|
||||
|
||||
@@ -1852,7 +1765,7 @@ module Make<
|
||||
* Holds if there is a local step from `pred` to `succ`, which is synthesized
|
||||
* from a flow summary.
|
||||
*/
|
||||
private predicate summaryLocalStepImpl(
|
||||
predicate summaryLocalStep(
|
||||
SummaryNode pred, SummaryNode succ, boolean preservesValue, string model
|
||||
) {
|
||||
exists(
|
||||
@@ -1898,24 +1811,9 @@ 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 | summaryLocalStepImpl(n1, succ, true, _))
|
||||
pred = unique(SummaryNode n1 | summaryLocalStep(n1, succ, true, _))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2037,7 +1935,7 @@ module Make<
|
||||
or
|
||||
exists(SummaryNode mid, boolean clearsOrExpectsMid |
|
||||
paramReachesLocal(p, mid, clearsOrExpectsMid) and
|
||||
summaryLocalStepImpl(mid, n, true, _) and
|
||||
summaryLocalStep(mid, n, true, _) and
|
||||
if
|
||||
summaryClearsContent(n, _) or
|
||||
summaryExpectsContent(n, _)
|
||||
@@ -2095,7 +1993,7 @@ module Make<
|
||||
*/
|
||||
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
|
||||
exists(SummaryNode ret |
|
||||
summaryLocalStepImpl(summaryArgParamRetOut(arg, ret, out, sc), ret, true, _)
|
||||
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, true, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2108,7 +2006,7 @@ module Make<
|
||||
*/
|
||||
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
|
||||
exists(SummaryNode ret |
|
||||
summaryLocalStepImpl(summaryArgParamRetOut(arg, ret, out, sc), ret, false, _)
|
||||
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2020,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
|
||||
summaryLocalStepImpl(mid, ret, _, _)
|
||||
summaryLocalStep(mid, ret, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2135,7 +2033,7 @@ module Make<
|
||||
*/
|
||||
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
|
||||
exists(SummaryNode mid, SummaryNode ret |
|
||||
summaryLocalStepImpl(summaryArgParamRetOut(arg, ret, out, sc), mid, _, _) and
|
||||
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _, _) and
|
||||
summaryStoreStep(mid, c, ret)
|
||||
)
|
||||
}
|
||||
@@ -2851,11 +2749,9 @@ 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(getNode(a.asNode()), b.asNode(), preservesValue, _) and
|
||||
PrivateSteps::summaryLocalStep(a.asNode(), b.asNode(), preservesValue, _) and
|
||||
if preservesValue = true then value = "value" else value = "taint"
|
||||
)
|
||||
or
|
||||
|
||||
@@ -1346,14 +1346,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
module MatchingWithEnvironment<MatchingWithEnvironmentInputSig Input> {
|
||||
private import Input
|
||||
|
||||
pragma[nomagic]
|
||||
private TypeParameter getDeclTypeParameter(Declaration decl, TypeArgumentPosition tapos) {
|
||||
exists(TypeParameterPosition tppos |
|
||||
result = decl.getTypeParameter(tppos) and
|
||||
typeArgumentParameterPositionMatch(tapos, tppos)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the type argument at `path` in `a` that corresponds to
|
||||
* the type parameter `tp` in `target`, if any.
|
||||
@@ -1364,11 +1356,11 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
*/
|
||||
bindingset[a, target]
|
||||
pragma[inline_late]
|
||||
Type getTypeArgument(Access a, Declaration target, TypeParameter tp, TypePath path) {
|
||||
exists(TypeArgumentPosition tapos |
|
||||
private Type getTypeArgument(Access a, Declaration target, TypeParameter tp, TypePath path) {
|
||||
exists(TypeArgumentPosition tapos, TypeParameterPosition tppos |
|
||||
result = a.getTypeArgument(tapos, path) and
|
||||
tp = getDeclTypeParameter(target, tapos) and
|
||||
not isPseudoType(result)
|
||||
tp = target.getTypeParameter(tppos) and
|
||||
typeArgumentParameterPositionMatch(tapos, tppos)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1534,35 +1526,42 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
|
||||
private module AccessConstraint {
|
||||
private predicate relevantAccessConstraint(
|
||||
Access a, AccessEnvironment e, Declaration target, TypeParameter constrainedTp,
|
||||
Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath path,
|
||||
TypeMention constraint
|
||||
) {
|
||||
target = a.getTarget(e) and
|
||||
typeParameterHasConstraint(target, constrainedTp, constraint)
|
||||
typeParameterHasConstraint(target, apos, _, path, constraint)
|
||||
}
|
||||
|
||||
private newtype TRelevantAccess =
|
||||
MkRelevantAccess(Access a, AccessEnvironment e, TypeParameter constrainedTp) {
|
||||
relevantAccessConstraint(a, e, _, constrainedTp, _)
|
||||
MkRelevantAccess(Access a, AccessPosition apos, AccessEnvironment e, TypePath path) {
|
||||
relevantAccessConstraint(a, e, _, apos, path, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* If the access `a` for `apos`, environment `e`, and `path` has an inferred type
|
||||
* which type inference requires to satisfy some constraint.
|
||||
*/
|
||||
private class RelevantAccess extends MkRelevantAccess {
|
||||
Access a;
|
||||
AccessPosition apos;
|
||||
AccessEnvironment e;
|
||||
TypeParameter constrainedTp;
|
||||
TypePath path;
|
||||
|
||||
RelevantAccess() { this = MkRelevantAccess(a, e, constrainedTp) }
|
||||
RelevantAccess() { this = MkRelevantAccess(a, apos, e, path) }
|
||||
|
||||
pragma[nomagic]
|
||||
Type getTypeAt(TypePath path) { typeMatch(a, e, _, path, result, constrainedTp) }
|
||||
Type getTypeAt(TypePath suffix) {
|
||||
result = a.getInferredType(e, apos, path.appendInverse(suffix))
|
||||
}
|
||||
|
||||
/** Gets the constraint that this relevant access should satisfy. */
|
||||
TypeMention getConstraint(Declaration target) {
|
||||
relevantAccessConstraint(a, e, target, constrainedTp, result)
|
||||
relevantAccessConstraint(a, e, target, apos, path, result)
|
||||
}
|
||||
|
||||
string toString() {
|
||||
result = a.toString() + ", " + e.toString() + ", " + constrainedTp.toString()
|
||||
result = a.toString() + ", " + apos.toString() + ", " + path.toString()
|
||||
}
|
||||
|
||||
Location getLocation() { result = a.getLocation() }
|
||||
@@ -1578,7 +1577,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
class TypeMatchingContext = Access;
|
||||
|
||||
TypeMatchingContext getTypeMatchingContext(RelevantAccess at) {
|
||||
at = MkRelevantAccess(result, _, _)
|
||||
at = MkRelevantAccess(result, _, _, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1592,32 +1591,41 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
SatisfiesTypeParameterConstraintInput>;
|
||||
|
||||
pragma[nomagic]
|
||||
predicate argSatisfiesConstraintAtTypeParameter(
|
||||
predicate satisfiesConstraintAtTypeParameter(
|
||||
Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix,
|
||||
TypeMention constraint, TypePath pathToTypeParamInConstraint,
|
||||
TypePath pathToTypeParamInSub
|
||||
) {
|
||||
exists(RelevantAccess ra, TypeParameter constrainedTp |
|
||||
ra = MkRelevantAccess(a, e, constrainedTp) and
|
||||
relevantAccessConstraint(a, e, target, constrainedTp, constraint) and
|
||||
exists(RelevantAccess ra |
|
||||
ra = MkRelevantAccess(a, apos, e, prefix) and
|
||||
SatisfiesTypeParameterConstraint::satisfiesConstraintAtTypeParameter(ra, constraint,
|
||||
pathToTypeParamInConstraint, pathToTypeParamInSub) and
|
||||
exists(DeclarationPosition dpos |
|
||||
accessDeclarationPositionMatch(apos, dpos) and
|
||||
constrainedTp = target.getDeclaredType(dpos, prefix)
|
||||
)
|
||||
constraint = ra.getConstraint(target)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate satisfiesConstraint(
|
||||
Access a, AccessEnvironment e, Declaration target, TypeParameter constrainedTp,
|
||||
Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix,
|
||||
TypeMention constraint, TypePath path, Type t
|
||||
) {
|
||||
exists(RelevantAccess ra |
|
||||
ra = MkRelevantAccess(a, e, constrainedTp) and
|
||||
relevantAccessConstraint(a, e, target, constrainedTp, constraint) and
|
||||
SatisfiesTypeParameterConstraint::satisfiesConstraint(ra, constraint, path, t)
|
||||
ra = MkRelevantAccess(a, apos, e, prefix) and
|
||||
SatisfiesTypeParameterConstraint::satisfiesConstraint(ra, constraint, path, t) and
|
||||
constraint = ra.getConstraint(target)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate satisfiesConstraintThrough(
|
||||
Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix,
|
||||
TypeAbstraction abs, TypeMention constraint, TypePath path, Type t
|
||||
) {
|
||||
exists(RelevantAccess ra |
|
||||
ra = MkRelevantAccess(a, apos, e, prefix) and
|
||||
SatisfiesTypeParameterConstraint::satisfiesConstraintThrough(ra, abs, constraint, path,
|
||||
t) and
|
||||
constraint = ra.getConstraint(target)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1636,44 +1644,51 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the type parameter `constrainedTp` applies to `target` and the
|
||||
* constraint `constraint` applies to `constrainedTp`.
|
||||
* Holds if the type parameter `constrainedTp` occurs in the declared type of
|
||||
* `target` at `apos` and `pathToConstrained`, and there is a constraint
|
||||
* `constraint` on `constrainedTp`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate typeParameterHasConstraint(
|
||||
Declaration target, TypeParameter constrainedTp, TypeMention constraint
|
||||
Declaration target, AccessPosition apos, TypeParameter constrainedTp,
|
||||
TypePath pathToConstrained, TypeMention constraint
|
||||
) {
|
||||
constrainedTp = target.getTypeParameter(_) and
|
||||
constraint = getATypeParameterConstraint(constrainedTp, target)
|
||||
exists(DeclarationPosition dpos |
|
||||
accessDeclarationPositionMatch(apos, dpos) and
|
||||
constrainedTp = target.getTypeParameter(_) and
|
||||
constrainedTp = target.getDeclaredType(dpos, pathToConstrained) and
|
||||
constraint = getATypeParameterConstraint(constrainedTp, target)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the type parameter `constrainedTp` applies to `target`, the
|
||||
* constraint `constraint` applies to `constrainedTp`, and type parameter
|
||||
* `tp` occurs at `pathToTp` in `constraint`.
|
||||
* Holds if the declared type of `target` contains a type parameter at
|
||||
* `apos` and `pathToConstrained` that must satisfy `constraint` and `tp`
|
||||
* occurs at `pathToTp` in `constraint`.
|
||||
*
|
||||
* For example, in
|
||||
*
|
||||
* ```csharp
|
||||
* interface IFoo<A> { }
|
||||
* T1 M<T1, T2>(T2 item) where T2 : IFoo<T1> { }
|
||||
* ```
|
||||
*
|
||||
* with the method declaration being the target, we have the following
|
||||
* - `constrainedTp = T2`,
|
||||
* with the method declaration being the target and with `apos`
|
||||
* corresponding to `item`, we have the following
|
||||
* - `pathToConstrained = ""`,
|
||||
* - `tp = T1`,
|
||||
* - `constraint = IFoo`,
|
||||
* - `tp = T1`, and
|
||||
* - `pathToTp = "A"`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate typeParameterConstraintHasTypeParameter(
|
||||
Declaration target, TypeParameter constrainedTp, TypeMention constraint, TypePath pathToTp,
|
||||
TypeParameter tp
|
||||
Declaration target, AccessPosition apos, TypePath pathToConstrained, TypeMention constraint,
|
||||
TypePath pathToTp, TypeParameter tp
|
||||
) {
|
||||
typeParameterHasConstraint(target, constrainedTp, constraint) and
|
||||
tp = target.getTypeParameter(_) and
|
||||
tp = constraint.getTypeAt(pathToTp) and
|
||||
constrainedTp != tp
|
||||
exists(TypeParameter constrainedTp |
|
||||
typeParameterHasConstraint(target, apos, constrainedTp, pathToConstrained, constraint) and
|
||||
tp = target.getTypeParameter(_) and
|
||||
tp = constraint.getTypeAt(pathToTp) and
|
||||
constrainedTp != tp
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1681,9 +1696,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
Access a, AccessEnvironment e, Declaration target, TypePath path, Type t, TypeParameter tp
|
||||
) {
|
||||
not exists(getTypeArgument(a, target, tp, _)) and
|
||||
exists(TypeMention constraint, TypeParameter constrainedTp, TypePath pathToTp |
|
||||
typeParameterConstraintHasTypeParameter(target, constrainedTp, constraint, pathToTp, tp) and
|
||||
AccessConstraint::satisfiesConstraint(a, e, target, constrainedTp, constraint,
|
||||
exists(TypeMention constraint, AccessPosition apos, TypePath pathToTp, TypePath pathToTp2 |
|
||||
typeParameterConstraintHasTypeParameter(target, apos, pathToTp2, constraint, pathToTp, tp) and
|
||||
AccessConstraint::satisfiesConstraint(a, e, target, apos, pathToTp2, constraint,
|
||||
pathToTp.appendInverse(path), t)
|
||||
)
|
||||
}
|
||||
@@ -1766,7 +1781,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
Declaration target, TypePath prefix, TypeMention constraint,
|
||||
TypePath pathToTypeParamInConstraint, TypePath pathToTypeParamInSub
|
||||
|
|
||||
AccessConstraint::argSatisfiesConstraintAtTypeParameter(a, e, target, apos, prefix,
|
||||
AccessConstraint::satisfiesConstraintAtTypeParameter(a, e, target, apos, prefix,
|
||||
constraint, pathToTypeParamInConstraint, pathToTypeParamInSub)
|
||||
|
|
||||
exists(TypePath suffix |
|
||||
@@ -1832,12 +1847,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
*/
|
||||
|
||||
typeMatch(a, e, target, suffix, result, tp) and
|
||||
exists(TypeParameter constrainedTp, DeclarationPosition dpos |
|
||||
typeParameterConstraintHasTypeParameter(target, constrainedTp, constraint, pathToTp,
|
||||
tp) and
|
||||
accessDeclarationPositionMatch(apos, dpos) and
|
||||
constrainedTp = target.getDeclaredType(dpos, _)
|
||||
) and
|
||||
typeParameterConstraintHasTypeParameter(target, apos, _, constraint, pathToTp, tp) and
|
||||
pathToTp = pathToTypeParamInConstraint.appendInverse(mid) and
|
||||
path = prefix.append(pathToTypeParamInSub.append(mid).append(suffix))
|
||||
)
|
||||
|
||||
@@ -305,7 +305,7 @@ private module Cached {
|
||||
model = ""
|
||||
or
|
||||
// flow through a flow summary (extension of `SummaryModelCsv`)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::SwiftDataFlow>
|
||||
|
||||
class SinkBase = Void;
|
||||
|
||||
class FlowSummaryCallBase = Void;
|
||||
|
||||
predicate callableFromSource(SummarizedCallableBase c) { c.hasBody() }
|
||||
|
||||
ArgumentPosition callbackSelfParameterPosition() { result instanceof ThisArgumentPosition }
|
||||
@@ -115,10 +113,6 @@ 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,
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
|
||||
or
|
||||
any(AdditionalTaintStep a).step(nodeFrom, nodeTo) and model = "AdditionalTaintStep"
|
||||
|
||||
Reference in New Issue
Block a user