1
1
/**
2
2
* @name Potentially overflowing call to snprintf
3
3
* @description Using the return value from snprintf without proper checks can cause overflow.
4
- *
5
4
* @kind problem
6
5
* @problem.severity warning
7
6
* @precision high
@@ -20,44 +19,44 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
20
19
* true if there is an arithmetic operation on the path that
21
20
* might overflow.
22
21
*/
23
- predicate flowsToExpr (
24
- Expr source , Expr sink , boolean pathMightOverflow ) {
22
+ predicate flowsToExpr ( Expr source , Expr sink , boolean pathMightOverflow ) {
25
23
// Might the current expression overflow?
26
- exists ( boolean otherMightOverflow
27
- | flowsToExprImpl ( source , sink , otherMightOverflow )
28
- | if convertedExprMightOverflow ( sink )
29
- then pathMightOverflow = true
30
- else pathMightOverflow = otherMightOverflow )
24
+ exists ( boolean otherMightOverflow | flowsToExprImpl ( source , sink , otherMightOverflow ) |
25
+ if convertedExprMightOverflow ( sink )
26
+ then pathMightOverflow = true
27
+ else pathMightOverflow = otherMightOverflow
28
+ )
31
29
}
32
30
33
31
/**
34
32
* Implementation of `flowsToExpr`. Does everything except
35
33
* checking whether the current expression might overflow.
36
34
*/
37
- predicate flowsToExprImpl (
38
- Expr source , Expr sink , boolean pathMightOverflow ) {
39
- ( source = sink and pathMightOverflow = false and
40
- source .( FunctionCall ) .getTarget ( ) .( Snprintf ) .returnsFullFormatLength ( ) )
35
+ predicate flowsToExprImpl ( Expr source , Expr sink , boolean pathMightOverflow ) {
36
+ (
37
+ source = sink and
38
+ pathMightOverflow = false and
39
+ source .( FunctionCall ) .getTarget ( ) .( Snprintf ) .returnsFullFormatLength ( )
40
+ )
41
41
or
42
- exists ( RangeSsaDefinition def , LocalScopeVariable v
43
- | flowsToDef ( source , def , v , pathMightOverflow ) and
44
- sink = def .getAUse ( v ) )
42
+ exists ( RangeSsaDefinition def , LocalScopeVariable v |
43
+ flowsToDef ( source , def , v , pathMightOverflow ) and
44
+ sink = def .getAUse ( v )
45
+ )
45
46
or
46
- flowsToExpr (
47
- source , sink .( UnaryArithmeticOperation ) .getOperand ( ) , pathMightOverflow )
47
+ flowsToExpr ( source , sink .( UnaryArithmeticOperation ) .getOperand ( ) , pathMightOverflow )
48
48
or
49
- flowsToExpr (
50
- source , sink .( BinaryArithmeticOperation ) .getAnOperand ( ) , pathMightOverflow )
49
+ flowsToExpr ( source , sink .( BinaryArithmeticOperation ) .getAnOperand ( ) , pathMightOverflow )
51
50
or
52
- flowsToExpr (
53
- source , sink .( Assignment ) .getRValue ( ) , pathMightOverflow )
51
+ flowsToExpr ( source , sink .( Assignment ) .getRValue ( ) , pathMightOverflow )
54
52
or
55
- flowsToExpr (
56
- source , sink .( AssignOperation ) .getLValue ( ) , pathMightOverflow )
53
+ flowsToExpr ( source , sink .( AssignOperation ) .getLValue ( ) , pathMightOverflow )
57
54
or
58
- exists ( FormattingFunctionCall call
59
- | sink = call and
60
- flowsToExpr ( source , call .getArgument ( call .getTarget ( ) .getSizeParameterIndex ( ) ) , pathMightOverflow ) )
55
+ exists ( FormattingFunctionCall call |
56
+ sink = call and
57
+ flowsToExpr ( source , call .getArgument ( call .getTarget ( ) .getSizeParameterIndex ( ) ) ,
58
+ pathMightOverflow )
59
+ )
61
60
}
62
61
63
62
/**
@@ -67,14 +66,14 @@ predicate flowsToExprImpl(
67
66
* on the path that might overflow.
68
67
*/
69
68
predicate flowsToDef (
70
- Expr source , RangeSsaDefinition def , LocalScopeVariable v ,
71
- boolean pathMightOverflow ) {
69
+ Expr source , RangeSsaDefinition def , LocalScopeVariable v , boolean pathMightOverflow
70
+ ) {
72
71
// Might the current definition overflow?
73
- exists ( boolean otherMightOverflow
74
- | flowsToDefImpl ( source , def , v , otherMightOverflow )
75
- | if defMightOverflow ( def , v )
76
- then pathMightOverflow = true
77
- else pathMightOverflow = otherMightOverflow )
72
+ exists ( boolean otherMightOverflow | flowsToDefImpl ( source , def , v , otherMightOverflow ) |
73
+ if defMightOverflow ( def , v )
74
+ then pathMightOverflow = true
75
+ else pathMightOverflow = otherMightOverflow
76
+ )
78
77
}
79
78
80
79
/**
@@ -89,26 +88,29 @@ predicate flowsToDef(
89
88
* the path. But it is a good way to reduce the number of false positives.
90
89
*/
91
90
predicate flowsToDefImpl (
92
- Expr source , RangeSsaDefinition def , LocalScopeVariable v ,
93
- boolean pathMightOverflow ) {
91
+ Expr source , RangeSsaDefinition def , LocalScopeVariable v , boolean pathMightOverflow
92
+ ) {
94
93
// Assignment or initialization: `e = v;`
95
- exists ( Expr e
96
- | e = def .getDefiningValue ( v ) and
97
- flowsToExpr ( source , e , pathMightOverflow ) )
94
+ exists ( Expr e |
95
+ e = def .getDefiningValue ( v ) and
96
+ flowsToExpr ( source , e , pathMightOverflow )
97
+ )
98
98
or
99
99
// `x++`
100
- exists ( CrementOperation crem
101
- | def = crem and
100
+ exists ( CrementOperation crem |
101
+ def = crem and
102
102
crem .getOperand ( ) = v .getAnAccess ( ) and
103
- flowsToExpr ( source , crem .getOperand ( ) , pathMightOverflow ) )
103
+ flowsToExpr ( source , crem .getOperand ( ) , pathMightOverflow )
104
+ )
104
105
or
105
106
// Phi definition.
106
107
flowsToDef ( source , def .getAPhiInput ( v ) , v , pathMightOverflow )
107
108
}
108
109
109
110
from FormattingFunctionCall call , Expr sink
110
- where flowsToExpr ( call , sink , true )
111
- and sink = call .getArgument ( call .getTarget ( ) .getSizeParameterIndex ( ) )
112
- select
113
- call , "The $@ of this snprintf call is derived from its return value, which may exceed the size of the buffer and overflow." ,
111
+ where
112
+ flowsToExpr ( call , sink , true ) and
113
+ sink = call .getArgument ( call .getTarget ( ) .getSizeParameterIndex ( ) )
114
+ select call ,
115
+ "The $@ of this snprintf call is derived from its return value, which may exceed the size of the buffer and overflow." ,
114
116
sink , "size argument"
0 commit comments