Skip to content

Commit 9d3bad1

Browse files
committed
fix user data tracking
1 parent e5e5986 commit 9d3bad1

File tree

1 file changed

+47
-47
lines changed

1 file changed

+47
-47
lines changed

cpp/src/security/UnsafeImplicitConversions/UnsafeImplicitConversions.ql

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/**
22
* @name Find all problematic implicit casts
33
* @description Find all implicit casts that may be problematic. That is, casts that may result in unexpected truncation, reinterpretation or widening of values.
4-
* @kind problem
4+
* @kind path-problem
55
* @id tob/cpp/unsafe-implicit-conversions
66
* @tags security
7-
* @problem.severity warning
8-
* @precision medium
7+
* @problem.severity error
8+
* @precision high
99
*/
1010

1111
import cpp
@@ -15,17 +15,16 @@ private import experimental.semmle.code.cpp.rangeanalysis.ExtendedRangeAnalysis
1515
private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisDefinition
1616
private import experimental.semmle.code.cpp.rangeanalysis.RangeAnalysis
1717
private import semmle.code.cpp.ir.IR
18-
private import semmle.code.cpp.ir.ValueNumbering
19-
import semmle.code.cpp.dataflow.new.TaintTracking
20-
import semmle.code.cpp.models.interfaces.FlowSource
18+
private import semmle.code.cpp.ir.dataflow.TaintTracking
19+
private import semmle.code.cpp.security.FlowSources
2120

2221
/**
2322
* Models standard I/O functions that return a length value bounded by their size argument
2423
* with possible -1 error return value
2524
*/
2625
private class LenApproxFunc extends SimpleRangeAnalysisExpr, FunctionCall {
2726
LenApproxFunc() {
28-
this.getTarget().hasName(["recvfrom", "recv", "sendto", "send", "read", "write"])
27+
this.getTarget().hasName(["recvfrom", "recv", "sendto", "send", "read", "write", "readv"])
2928
}
3029

3130
override float getLowerBounds() { result = -1 }
@@ -36,18 +35,19 @@ private class LenApproxFunc extends SimpleRangeAnalysisExpr, FunctionCall {
3635
}
3736

3837
/*
39-
* Uncomment the class below to silent findings that require large strings
40-
* to be passed to strlen to be exploitable.
38+
* Silent findings that require passing large strings to strlen to be exploitable.
39+
* Remove this class to report unsafe implicit conversions from large strlen results
4140
*/
41+
private class StrlenFunAssumption extends SimpleRangeAnalysisExpr, FunctionCall {
42+
StrlenFunAssumption() { this.getTarget().hasName("strlen") }
43+
44+
override float getLowerBounds() { result = 0 }
45+
46+
override float getUpperBounds() { result = 536870912 }
47+
48+
override predicate dependsOnChild(Expr child) { none() }
49+
}
4250

43-
// private class StrlenFunAssumption extends SimpleRangeAnalysisExpr, FunctionCall {
44-
// StrlenFunAssumption() {
45-
// this.getTarget().hasName("strlen")
46-
// }
47-
// override float getLowerBounds() { result = 0 }
48-
// override float getUpperBounds() { result = 536870912 }
49-
// override predicate dependsOnChild(Expr child) { none() }
50-
// }
5151
/**
5252
* Determines if a function's address is taken in the codebase.
5353
* This indicates that the function may be called while
@@ -220,32 +220,33 @@ predicate safeBounds(Expr cast, IntegralType toType) {
220220

221221
/*
222222
* Taint tracking from user-controlled inputs to implicit conversions
223-
* UNUSED: uncomment code below and the code near "select" statement at the bottom of the file
224223
*/
224+
module UserInputToImplicitConversionConfig implements DataFlow::ConfigSig {
225+
predicate isSource(DataFlow::Node source) {
226+
exists(RemoteFlowSourceFunction remoteFlow | remoteFlow = source.asExpr().(Call).getTarget())
227+
or
228+
exists(LocalFlowSourceFunction localFlow | localFlow = source.asExpr().(Call).getTarget())
229+
or
230+
source instanceof RemoteFlowSource
231+
or
232+
source instanceof LocalFlowSource
233+
}
234+
235+
predicate isSink(DataFlow::Node sink) {
236+
exists(IntegralConversion cast |
237+
cast.isImplicit() and
238+
cast.getExpr() = sink.asExpr()
239+
)
240+
}
241+
}
242+
243+
module UserInputToImplicitConversionConfigFlow = TaintTracking::Global<UserInputToImplicitConversionConfig>;
244+
import UserInputToImplicitConversionConfigFlow::PathGraph
225245

226-
// module UnsafeUserInputConversionConfig implements DataFlow::ConfigSig {
227-
// predicate isSource(DataFlow::Node source) {
228-
// exists(RemoteFlowSourceFunction remoteFlow |
229-
// remoteFlow = source.asExpr().(Call).getTarget() and
230-
// remoteFlow.hasRemoteFlowSource(_, _)
231-
// )
232-
// or
233-
// exists(LocalFlowSourceFunction localFlow |
234-
// localFlow = source.asExpr().(Call).getTarget() and
235-
// localFlow.hasLocalFlowSource(_, _)
236-
// )
237-
// }
238-
// predicate isSink(DataFlow::Node sink) {
239-
// exists(IntegralConversion cast |
240-
// cast.isImplicit() and
241-
// cast.getExpr() = sink.asExpr()
242-
// )
243-
// }
244-
// }
245-
// module UnsafeUserInputConversionFlow = TaintTracking::Global<UnsafeUserInputConversionConfig>;
246246
from
247247
IntegralConversion cast, IntegralType fromType, IntegralType toType, Expr castExpr,
248-
string problemType
248+
string problemType, UserInputToImplicitConversionConfigFlow::PathNode source,
249+
UserInputToImplicitConversionConfigFlow::PathNode sink
249250
where
250251
cast.getExpr() = castExpr and
251252
// only implicit conversions
@@ -308,7 +309,7 @@ where
308309
upperBound(secondHandSide) < (typeUpperBound(toType) + typeLowerBound(fromType))
309310
)
310311
) and
311-
// skip unused function
312+
// skip unused functions
312313
(
313314
exists(FunctionCall fc | fc.getTarget() = cast.getEnclosingFunction())
314315
or
@@ -317,10 +318,9 @@ where
317318
cast.getEnclosingFunction().getName() = "main"
318319
or
319320
addressIsTaken(cast.getEnclosingFunction())
320-
)
321-
// UNUSED: Uncomment to report conversions with untrusted inputs only
322-
// and exists(DataFlow::Node source, DataFlow::Node sink |
323-
// castExpr = sink.asExpr() and
324-
// UnsafeUserInputConversionFlow::flow(source, sink)
325-
// )
326-
select cast, "Implicit cast from " + fromType + " to " + toType + " (" + problemType + ")"
321+
) and
322+
// tainted by user-provided data
323+
castExpr = sink.getNode().asExpr() and
324+
UserInputToImplicitConversionConfigFlow::flowPath(source, sink)
325+
select sink.getNode(), source, sink,
326+
"Implicit cast from " + fromType + " to " + toType + " (" + problemType + ")"

0 commit comments

Comments
 (0)