22 * @name Missing return-value check for a 'scanf'-like function
33 * @description Failing to check that a call to 'scanf' actually writes to an
44 * output variable can lead to unexpected behavior at reading time.
5- * @kind problem
5+ * @kind path- problem
66 * @problem.severity warning
77 * @security-severity 7.5
88 * @precision medium
@@ -20,6 +20,7 @@ import semmle.code.cpp.dataflow.new.DataFlow::DataFlow
2020import semmle.code.cpp.ir.IR
2121import semmle.code.cpp.ir.ValueNumbering
2222import ScanfChecks
23+ import ScanfToUseFlow:: PathGraph
2324
2425/**
2526 * Holds if `n` represents an uninitialized stack-allocated variable, or a
@@ -118,10 +119,13 @@ module ScanfToUseFlow = Global<ScanfToUseConfig>;
118119 * Holds if `source` is the `index`'th argument to the `scanf`-like call `call`, and `sink` is
119120 * a dataflow node that represents the expression `e`.
120121 */
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 )
125129}
126130
127131/**
@@ -143,9 +147,12 @@ int getMinimumGuardConstant(ScanfFunctionCall call, int index) {
143147 * Holds the access to `e` isn't guarded by a check that ensures that `call` returned
144148 * at least `minGuard`.
145149 */
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+ ) {
147154 exists ( int index |
148- hasFlow ( _ , call , index , _ , e ) and
155+ flowPath ( source , call , index , sink , e ) and
149156 minGuard = getMinimumGuardConstant ( call , index )
150157 |
151158 not exists ( int value |
@@ -173,9 +180,11 @@ BasicBlock blockGuardedBy(int value, string op, ScanfFunctionCall call) {
173180 )
174181}
175182
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 ,
179188 "This variable is read, but may not have been written. " +
180189 "It should be guarded by a check that the $@ returns at least " + minGuard + "." , call ,
181190 call .toString ( )
0 commit comments