Skip to content

Commit 9fdee2d

Browse files
committed
C++: Add a 'call' column to 'hasRemoteFlowSource' and 'hasLocalFlowSource' to support modeling of 'scanf_s'.
1 parent 2902a19 commit 9fdee2d

5 files changed

Lines changed: 34 additions & 17 deletions

File tree

cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,27 @@ abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction,
7373
* The standard function `scanf` and its assorted variants
7474
*/
7575
private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction instanceof Scanf {
76-
override predicate hasLocalFlowSource(FunctionOutput output, string description) {
77-
output.isParameterDeref(any(int i | i >= this.getArgsStartPosition())) and
78-
description = "value read by " + this.getName()
76+
override predicate hasLocalFlowSource(Call call, FunctionOutput output, string description) {
77+
exists(ScanfFunctionCall scanfCall, int n | call = scanfCall |
78+
scanfCall.getScanfFunction() = this and
79+
exists(scanfCall.getOutputArgument(n)) and
80+
output.isParameterDeref(this.getNumberOfParameters() + n) and
81+
description = "value read by " + this.getName()
82+
)
7983
}
8084
}
8185

8286
/**
8387
* The standard function `fscanf` and its assorted variants
8488
*/
8589
private class FscanfModel extends ScanfFunctionModel, RemoteFlowSourceFunction instanceof Fscanf {
86-
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
87-
output.isParameterDeref(any(int i | i >= this.getArgsStartPosition())) and
88-
description = "value read by " + this.getName()
90+
override predicate hasRemoteFlowSource(Call call, FunctionOutput output, string description) {
91+
exists(ScanfFunctionCall scanfCall, int n | call = scanfCall |
92+
scanfCall.getScanfFunction() = this and
93+
exists(scanfCall.getOutputArgument(n)) and
94+
output.isParameterDeref(this.getNumberOfParameters() + n) and
95+
description = "value read by " + this.getName()
96+
)
8997
}
9098

9199
override predicate hasSocketInput(FunctionInput input) {

cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@ abstract class RemoteFlowSourceFunction extends Function {
1818
/**
1919
* Holds if remote data described by `description` flows from `output` of a call to this function.
2020
*/
21-
abstract predicate hasRemoteFlowSource(FunctionOutput output, string description);
21+
predicate hasRemoteFlowSource(FunctionOutput output, string description) {
22+
this.hasRemoteFlowSource(_, output, description)
23+
}
24+
25+
predicate hasRemoteFlowSource(Call call, FunctionOutput output, string description) {
26+
call.getTarget() = this and
27+
this.hasRemoteFlowSource(output, description)
28+
}
2229

2330
/**
2431
* Holds if remote data from this source comes from a socket or stream
@@ -35,7 +42,14 @@ abstract class LocalFlowSourceFunction extends Function {
3542
/**
3643
* Holds if data described by `description` flows from `output` of a call to this function.
3744
*/
38-
abstract predicate hasLocalFlowSource(FunctionOutput output, string description);
45+
predicate hasLocalFlowSource(FunctionOutput output, string description) {
46+
this.hasLocalFlowSource(_, output, description)
47+
}
48+
49+
predicate hasLocalFlowSource(Call call, FunctionOutput output, string description) {
50+
call.getTarget() = this and
51+
this.hasLocalFlowSource(output, description)
52+
}
3953
}
4054

4155
/** A library function that sends data over a network connection. */

cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ private class RemoteModelSource extends RemoteFlowSource {
2828

2929
RemoteModelSource() {
3030
exists(CallInstruction call, RemoteFlowSourceFunction func, FunctionOutput output |
31-
call.getStaticCallTarget() = func and
32-
func.hasRemoteFlowSource(output, sourceType) and
31+
func.hasRemoteFlowSource(call.getConvertedResultExpression(), output, sourceType) and
3332
this = callOutput(call, output)
3433
)
3534
}
@@ -46,7 +45,7 @@ private class LocalModelSource extends LocalFlowSource {
4645
LocalModelSource() {
4746
exists(CallInstruction call, LocalFlowSourceFunction func, FunctionOutput output |
4847
call.getStaticCallTarget() = func and
49-
func.hasLocalFlowSource(output, sourceType) and
48+
func.hasLocalFlowSource(call.getConvertedResultExpression(), output, sourceType) and
5049
this = callOutput(call, output)
5150
)
5251
}

cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,7 @@ class ExternalApiDataNode extends DataFlow::Node {
4444
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
4545
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
4646
predicate isSource(DataFlow::Node source) {
47-
exists(RemoteFlowSourceFunction remoteFlow |
48-
remoteFlow = source.asExpr().(Call).getTarget() and
49-
remoteFlow.hasRemoteFlowSource(_, _)
50-
)
47+
any(RemoteFlowSourceFunction remoteFlow).hasRemoteFlowSource(source.asExpr(), _, _)
5148
}
5249

5350
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }

cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,8 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
9494
}
9595

9696
override Expr getDataExpr(Call call) {
97-
call.getTarget() = this and
9897
exists(FunctionOutput output, int arg |
99-
super.hasRemoteFlowSource(output, _) and
98+
super.hasRemoteFlowSource(call, output, _) and
10099
output.isParameterDeref(arg) and
101100
result = call.getArgument(arg)
102101
)

0 commit comments

Comments
 (0)