@@ -71,8 +71,6 @@ import javascript
7171 *
7272 * - We assume !(x <= y) means x > y, ignoring NaN.
7373 *
74- * - We assume x < y means x <= y + 1, ignoring floats.
75- *
7674 * - We assume integer arithmetic is exact, ignoring values above 2^53.
7775 *
7876 */
@@ -281,19 +279,24 @@ module RangeAnalysis {
281279 *
282280 * The dual constraint `-B <= -A + c` is not included in this predicate.
283281 */
284- predicate comparisonEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int bias ) {
282+ predicate comparisonEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int bias , boolean sharp ) {
285283 // A <= B + c
286- linearComparisonGuard ( cfg , a , asign , "<=" , b , bsign , bias )
284+ linearComparisonGuard ( cfg , a , asign , "<=" , b , bsign , bias ) and
285+ sharp = false
287286 or
288- // A <= B + c iff A < B + c + 1 (assuming A,B are integers)
289- linearComparisonGuard ( cfg , a , asign , "<" , b , bsign , bias + 1 )
287+ // A < B + c
288+ linearComparisonGuard ( cfg , a , asign , "<" , b , bsign , bias ) and
289+ sharp = true
290290 or
291291 // A <= B + c iff B >= A - c
292- linearComparisonGuard ( cfg , b , bsign , ">=" , a , asign , - bias )
292+ linearComparisonGuard ( cfg , b , bsign , ">=" , a , asign , - bias ) and
293+ sharp = false
293294 or
294- // A <= B + c iff B > A - c - 1 (assuming A,B are integers)
295- linearComparisonGuard ( cfg , b , bsign , ">" , a , asign , - bias - 1 )
295+ // A < B + c iff B > A - c
296+ linearComparisonGuard ( cfg , b , bsign , ">" , a , asign , - bias ) and
297+ sharp = true
296298 or
299+ sharp = false and
297300 exists ( string operator | operator = "==" or operator = "===" |
298301 // A == B + c iff A <= B + c and B <= A - c
299302 linearComparisonGuard ( cfg , a , asign , operator , b , bsign , bias )
@@ -387,31 +390,31 @@ module RangeAnalysis {
387390 /**
388391 * The set of initial edges including those from dual constraints.
389392 */
390- private predicate seedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c ) {
393+ private predicate seedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c , boolean sharp ) {
391394 // A <= B + c
392- comparisonEdge ( cfg , a , asign , b , bsign , c )
395+ comparisonEdge ( cfg , a , asign , b , bsign , c , sharp )
393396 or
394- phiEdge ( cfg , a , asign , b , bsign , c )
397+ phiEdge ( cfg , a , asign , b , bsign , c ) and sharp = false
395398 or
396- constantEdge ( cfg , a , asign , b , bsign , c )
399+ constantEdge ( cfg , a , asign , b , bsign , c ) and sharp = false
397400 }
398401
399- private predicate seedEdgeWithDual ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c ) {
402+ private predicate seedEdgeWithDual ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c , boolean sharp ) {
400403 // A <= B + c
401- seedEdge ( cfg , a , asign , b , bsign , c )
404+ seedEdge ( cfg , a , asign , b , bsign , c , sharp )
402405 or
403406 // -B <= -A + c (dual constraint)
404- seedEdge ( cfg , b , - bsign , a , - asign , c )
407+ seedEdge ( cfg , b , - bsign , a , - asign , c , sharp )
405408 }
406409
407410 /**
408411 * Adds a negative and positive integer, but only if they are within in the same
409412 * order of magnitude.
410413 */
411- bindingset [ x, y ]
412- private int wideningAddition ( int x , int y ) {
413- x < 0 and
414- y >= 0 and
414+ bindingset [ x, sharpx , y , sharpy ]
415+ private int wideningAddition ( int x , boolean sharpx , int y , boolean sharpy ) {
416+ ( x < 0 or x = 0 and sharpx = true ) and
417+ ( y > 0 or y = 0 and sharpy = false ) and
415418 (
416419 x = 0
417420 or
@@ -449,13 +452,14 @@ module RangeAnalysis {
449452 *
450453 * This means negative-weight cycles (contradictions) can be detected using simple cycle detection.
451454 */
452- private predicate extendedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c ) {
453- seedEdgeWithDual ( cfg , a , asign , b , bsign , c )
455+ private predicate extendedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c , boolean sharp ) {
456+ seedEdgeWithDual ( cfg , a , asign , b , bsign , c , sharp )
454457 or
455- exists ( DataFlow:: Node mid , int midx , ControlFlowNode cfg1 , int c1 , ControlFlowNode cfg2 , int c2 |
456- extendedEdge ( cfg1 , a , asign , mid , midx , c1 ) and
457- extendedEdge ( cfg2 , mid , midx , b , bsign , c2 ) and
458- c = wideningAddition ( c1 , c2 ) and
458+ exists ( DataFlow:: Node mid , int midx , ControlFlowNode cfg1 , int c1 , ControlFlowNode cfg2 , int c2 , boolean sharp1 , boolean sharp2 |
459+ extendedEdge ( cfg1 , a , asign , mid , midx , c1 , sharp1 ) and
460+ extendedEdge ( cfg2 , mid , midx , b , bsign , c2 , sharp2 ) and
461+ sharp = sharp1 .booleanOr ( sharp2 ) and
462+ c = wideningAddition ( c1 , sharp1 , c2 , sharp2 ) and
459463 // One of the two CFG nodes must dominate the other, and `cfg` must be bound to the dominated one.
460464 (
461465 // They are in the same basic block
@@ -481,7 +485,9 @@ module RangeAnalysis {
481485 * Holds if there is a negative-weight edge from src to dst.
482486 */
483487 private predicate negativeEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign ) {
484- exists ( int weight | extendedEdge ( cfg , a , asign , b , bsign , weight ) |
488+ exists ( int weight , boolean sharp | extendedEdge ( cfg , a , asign , b , bsign , weight , sharp ) |
489+ weight = 0 and sharp = true // a strict "< 0" edge counts as negative
490+ or
485491 weight < 0 )
486492 }
487493
0 commit comments