@@ -39,59 +39,35 @@ predicate bounded(Instruction i, Instruction b, int delta) {
39
39
)
40
40
}
41
41
42
- /**
43
- * Holds if the combination of `n` and `state` represents an appropriate
44
- * source for the expression `e` suitable for use-use flow.
45
- */
46
- private predicate hasSizeImpl ( Expr e , DataFlow:: Node n , string state ) {
47
- // The simple case: If the size is a variable access with no qualifier we can just use the
48
- // dataflow node for that expression and no state.
49
- exists ( VariableAccess va |
50
- va = e and
51
- not va instanceof FieldAccess and
52
- n .asConvertedExpr ( ) = va .getFullyConverted ( ) and
53
- state = "0"
54
- )
55
- or
56
- // If the size is a choice between two expressions we allow both to be nodes representing the size.
57
- exists ( ConditionalExpr cond | cond = e | hasSizeImpl ( [ cond .getThen ( ) , cond .getElse ( ) ] , n , state ) )
58
- or
59
- // If the size is an expression plus a constant, we pick the dataflow node of the expression and
60
- // remember the constant in the state.
61
- exists ( Expr const , Expr nonconst |
62
- e .( AddExpr ) .hasOperands ( const , nonconst ) and
63
- state = const .getValue ( ) and
64
- hasSizeImpl ( nonconst , n , _)
65
- )
66
- or
67
- exists ( Expr const , Expr nonconst |
68
- e .( SubExpr ) .hasOperands ( const , nonconst ) and
69
- state = "-" + const .getValue ( ) and
70
- hasSizeImpl ( nonconst , n , _)
71
- )
72
- }
42
+ VariableAccess getAVariableAccess ( Expr e ) { e .getAChild * ( ) = result }
73
43
74
44
/**
75
45
* Holds if `(n, state)` pair represents the source of flow for the size
76
46
* expression associated with `alloc`.
77
47
*/
78
48
predicate hasSize ( AllocationExpr alloc , DataFlow:: Node n , string state ) {
79
- hasSizeImpl ( alloc .getSizeExpr ( ) , n , state )
49
+ exists ( VariableAccess va , Expr size , int delta |
50
+ size = alloc .getSizeExpr ( ) and
51
+ // Get the unique variable in a size expression like `x` in `malloc(x + 1)`.
52
+ va = unique( | | getAVariableAccess ( size ) ) and
53
+ // Compute `delta` as the constant difference between `x` and `x + 1`.
54
+ bounded ( any ( Instruction instr | instr .getUnconvertedResultExpression ( ) = size ) ,
55
+ any ( LoadInstruction load | load .getUnconvertedResultExpression ( ) = va ) , delta ) and
56
+ n .asConvertedExpr ( ) = va .getFullyConverted ( ) and
57
+ state = delta .toString ( )
58
+ )
80
59
}
81
60
82
61
predicate isSinkPairImpl (
83
- CallInstruction c , DataFlow:: Node bufSink , DataFlow:: Node sizeSink , int delta , Expr eBuf ,
84
- Expr eSize
62
+ CallInstruction c , DataFlow:: Node bufSink , DataFlow:: Node sizeSink , int delta , Expr eBuf
85
63
) {
86
64
exists ( int bufIndex , int sizeIndex , Instruction sizeInstr , Instruction bufInstr |
87
65
bufInstr = bufSink .asInstruction ( ) and
88
66
c .getArgument ( bufIndex ) = bufInstr and
89
67
sizeInstr = sizeSink .asInstruction ( ) and
90
68
c .getStaticCallTarget ( ) .( ArrayFunction ) .hasArrayWithVariableSize ( bufIndex , sizeIndex ) and
91
69
bounded ( c .getArgument ( sizeIndex ) , sizeInstr , delta ) and
92
- eSize = sizeInstr .getUnconvertedResultExpression ( ) and
93
- eBuf = bufInstr .getUnconvertedResultExpression ( ) and
94
- delta >= 1
70
+ eBuf = bufInstr .getUnconvertedResultExpression ( )
95
71
)
96
72
}
97
73
@@ -117,9 +93,9 @@ class StringSizeConfiguration extends ProductFlow::Configuration {
117
93
DataFlow:: FlowState state2
118
94
) {
119
95
state1 instanceof DataFlow:: FlowStateEmpty and
120
- state2 = [ 0 .. 32 ] .toString ( ) and // An arbitrary bound because we need to bound `state2`
96
+ state2 = [ - 32 .. 32 ] .toString ( ) and // An arbitrary bound because we need to bound `state2`
121
97
exists ( int delta |
122
- isSinkPairImpl ( _, bufSink , sizeSink , delta , _, _ ) and
98
+ isSinkPairImpl ( _, bufSink , sizeSink , delta , _) and
123
99
delta > state2 .toInt ( )
124
100
)
125
101
}
@@ -129,7 +105,7 @@ class StringSizeConfiguration extends ProductFlow::Configuration {
129
105
DataFlow:: FlowState state2
130
106
) {
131
107
exists ( AddInstruction add , Operand op , int delta , int s1 , int s2 |
132
- s1 = [ 0 .. 32 ] and // An arbitrary bound because we need to bound `state`
108
+ s1 = [ - 32 .. 32 ] and // An arbitrary bound because we need to bound `state`
133
109
state1 = s1 .toString ( ) and
134
110
state2 = s2 .toString ( ) and
135
111
add .hasOperands ( node1 .asOperand ( ) , op ) and
@@ -142,13 +118,14 @@ class StringSizeConfiguration extends ProductFlow::Configuration {
142
118
143
119
from
144
120
StringSizeConfiguration conf , DataFlow:: PathNode source1 , DataFlow2:: PathNode source2 ,
145
- DataFlow:: PathNode sink1 , DataFlow2:: PathNode sink2 , int k , CallInstruction c ,
146
- DataFlow:: Node sourceNode , Expr bound , Expr buffer , string element
121
+ DataFlow:: PathNode sink1 , DataFlow2:: PathNode sink2 , int overflow , int sinkState ,
122
+ CallInstruction c , DataFlow:: Node sourceNode , Expr buffer , string element
147
123
where
148
124
conf .hasFlowPath ( source1 , source2 , sink1 , sink2 ) and
149
- k > sink2 .getState ( ) .toInt ( ) and
150
- isSinkPairImpl ( c , sink1 .getNode ( ) , sink2 .getNode ( ) , k , buffer , bound ) and
125
+ sinkState = sink2 .getState ( ) .toInt ( ) and
126
+ isSinkPairImpl ( c , sink1 .getNode ( ) , sink2 .getNode ( ) , overflow + sinkState , buffer ) and
127
+ overflow > 0 and
151
128
sourceNode = source1 .getNode ( ) and
152
- if k = 1 then element = " element." else element = " elements."
129
+ if overflow = 1 then element = " element." else element = " elements."
153
130
select c .getUnconvertedResultExpression ( ) , source1 , sink1 ,
154
- "This write may overflow $@ by " + k + element , buffer , buffer .toString ( )
131
+ "This write may overflow $@ by " + overflow + element , buffer , buffer .toString ( )
0 commit comments