2
2
* @name Missing return-value check for a 'scanf'-like function
3
3
* @description Failing to check that a call to 'scanf' actually writes to an
4
4
* output variable can lead to unexpected behavior at reading time.
5
- * @kind problem
5
+ * @kind path- problem
6
6
* @problem.severity warning
7
7
* @security-severity 7.5
8
8
* @precision medium
@@ -20,6 +20,7 @@ import semmle.code.cpp.dataflow.new.DataFlow::DataFlow
20
20
import semmle.code.cpp.ir.IR
21
21
import semmle.code.cpp.ir.ValueNumbering
22
22
import ScanfChecks
23
+ import ScanfToUseFlow:: PathGraph
23
24
24
25
/**
25
26
* Holds if `n` represents an uninitialized stack-allocated variable, or a
@@ -118,10 +119,13 @@ module ScanfToUseFlow = Global<ScanfToUseConfig>;
118
119
* Holds if `source` is the `index`'th argument to the `scanf`-like call `call`, and `sink` is
119
120
* a dataflow node that represents the expression `e`.
120
121
*/
121
- predicate hasFlow ( Node source , ScanfFunctionCall call , int index , Node sink , Expr e ) {
122
- isSource ( call , index , source , _) and
123
- ScanfToUseFlow:: flow ( source , sink ) and
124
- isSink ( sink , e )
122
+ predicate flowPath (
123
+ ScanfToUseFlow:: PathNode source , ScanfFunctionCall call , int index , ScanfToUseFlow:: PathNode sink ,
124
+ Expr e
125
+ ) {
126
+ isSource ( call , index , source .getNode ( ) , _) and
127
+ ScanfToUseFlow:: flowPath ( source , sink ) and
128
+ isSink ( sink .getNode ( ) , e )
125
129
}
126
130
127
131
/**
@@ -143,9 +147,12 @@ int getMinimumGuardConstant(ScanfFunctionCall call, int index) {
143
147
* Holds the access to `e` isn't guarded by a check that ensures that `call` returned
144
148
* at least `minGuard`.
145
149
*/
146
- predicate hasNonGuardedAccess ( ScanfFunctionCall call , Expr e , int minGuard ) {
150
+ predicate hasNonGuardedAccess (
151
+ ScanfToUseFlow:: PathNode source , ScanfFunctionCall call , ScanfToUseFlow:: PathNode sink , Expr e ,
152
+ int minGuard
153
+ ) {
147
154
exists ( int index |
148
- hasFlow ( _ , call , index , _ , e ) and
155
+ flowPath ( source , call , index , sink , e ) and
149
156
minGuard = getMinimumGuardConstant ( call , index )
150
157
|
151
158
not exists ( int value |
@@ -173,9 +180,11 @@ BasicBlock blockGuardedBy(int value, string op, ScanfFunctionCall call) {
173
180
)
174
181
}
175
182
176
- from ScanfFunctionCall call , Expr e , int minGuard
177
- where hasNonGuardedAccess ( call , e , minGuard )
178
- select e ,
183
+ from
184
+ ScanfToUseFlow:: PathNode source , ScanfToUseFlow:: PathNode sink , ScanfFunctionCall call , Expr e ,
185
+ int minGuard
186
+ where hasNonGuardedAccess ( source , call , sink , e , minGuard )
187
+ select e , source , sink ,
179
188
"This variable is read, but may not have been written. " +
180
189
"It should be guarded by a check that the $@ returns at least " + minGuard + "." , call ,
181
190
call .toString ( )
0 commit comments