@@ -39,59 +39,35 @@ predicate bounded(Instruction i, Instruction b, int delta) {
3939 )
4040}
4141
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 }
7343
7444/**
7545 * Holds if `(n, state)` pair represents the source of flow for the size
7646 * expression associated with `alloc`.
7747 */
7848predicate 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+ )
8059}
8160
8261predicate 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
8563) {
8664 exists ( int bufIndex , int sizeIndex , Instruction sizeInstr , Instruction bufInstr |
8765 bufInstr = bufSink .asInstruction ( ) and
8866 c .getArgument ( bufIndex ) = bufInstr and
8967 sizeInstr = sizeSink .asInstruction ( ) and
9068 c .getStaticCallTarget ( ) .( ArrayFunction ) .hasArrayWithVariableSize ( bufIndex , sizeIndex ) and
9169 bounded ( c .getArgument ( sizeIndex ) , sizeInstr , delta ) and
92- eSize = sizeInstr .getUnconvertedResultExpression ( ) and
93- eBuf = bufInstr .getUnconvertedResultExpression ( ) and
94- delta >= 1
70+ eBuf = bufInstr .getUnconvertedResultExpression ( )
9571 )
9672}
9773
@@ -117,9 +93,9 @@ class StringSizeConfiguration extends ProductFlow::Configuration {
11793 DataFlow:: FlowState state2
11894 ) {
11995 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`
12197 exists ( int delta |
122- isSinkPairImpl ( _, bufSink , sizeSink , delta , _, _ ) and
98+ isSinkPairImpl ( _, bufSink , sizeSink , delta , _) and
12399 delta > state2 .toInt ( )
124100 )
125101 }
@@ -129,7 +105,7 @@ class StringSizeConfiguration extends ProductFlow::Configuration {
129105 DataFlow:: FlowState state2
130106 ) {
131107 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`
133109 state1 = s1 .toString ( ) and
134110 state2 = s2 .toString ( ) and
135111 add .hasOperands ( node1 .asOperand ( ) , op ) and
@@ -142,13 +118,14 @@ class StringSizeConfiguration extends ProductFlow::Configuration {
142118
143119from
144120 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
147123where
148124 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
151128 sourceNode = source1 .getNode ( ) and
152- if k = 1 then element = " element." else element = " elements."
129+ if overflow = 1 then element = " element." else element = " elements."
153130select 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