11import go
22
3- /**
4- * Gets the maximum value of an integer (signed if `isSigned`
5- * is true, unsigned otherwise) with `bitSize` bits.
6- */
7- float getMaxIntValue ( int bitSize , boolean isSigned ) {
8- bitSize in [ 8 , 16 , 32 , 64 ] and
9- (
10- isSigned = true and result = 2 .pow ( bitSize - 1 ) - 1
11- or
12- isSigned = false and result = 2 .pow ( bitSize ) - 1
13- )
3+ /** The constant `math.MaxInt` or the constant `math.MaxUint`. */
4+ abstract private class MaxIntOrMaxUint extends DeclaredConstant {
5+ /**
6+ * Gets the integer `x` such that `2.pow(x) - 1` is the value of this
7+ * constant when the architecture has bit size `architectureBitSize`.
8+ */
9+ abstract int getX ( int architectureBitSize ) ;
10+
11+ /**
12+ * Holds if the value of this constant given `architectureBitSize` minus
13+ * `strictnessOffset` is less than or equal to `2.pow(b) - 1`.
14+ */
15+ predicate isBoundFor ( int b , int architectureBitSize , float strictnessOffset ) {
16+ // 2.pow(x) - 1 - strictnessOffset <= 2.pow(b) - 1
17+ exists ( int x |
18+ x = this .getX ( architectureBitSize ) and
19+ b = validBitSize ( ) and
20+ (
21+ strictnessOffset = 0 and x <= b
22+ or
23+ strictnessOffset = 1 and x <= b - 1
24+ )
25+ )
26+ }
27+ }
28+
29+ /** The constant `math.MaxInt`. */
30+ private class MaxInt extends MaxIntOrMaxUint {
31+ MaxInt ( ) { this .hasQualifiedName ( "math" , "MaxInt" ) }
32+
33+ override int getX ( int architectureBitSize ) {
34+ architectureBitSize = [ 32 , 64 ] and result = architectureBitSize - 1
35+ }
36+ }
37+
38+ /** The constant `math.MaxUint`. */
39+ private class MaxUint extends MaxIntOrMaxUint {
40+ MaxUint ( ) { this .hasQualifiedName ( "math" , "MaxUint" ) }
41+
42+ override int getX ( int architectureBitSize ) {
43+ architectureBitSize = [ 32 , 64 ] and result = architectureBitSize
44+ }
1445}
1546
1647/**
@@ -276,7 +307,7 @@ class UpperBoundCheckGuard extends DataFlow::RelationalComparisonNode {
276307 predicate isBoundFor ( int bitSize , int architectureBitSize ) {
277308 bitSize = validBitSize ( ) and
278309 architectureBitSize = [ 32 , 64 ] and
279- exists ( float bound , int b , float strictnessOffset |
310+ exists ( int b , float strictnessOffset |
280311 b = max ( int a | a = validBitSize ( ) and a < bitSize ) and
281312 // For `x < c` the bound is `c-1`. For `x >= c` we will be an upper bound
282313 // on the `branch` argument of `checks` is false, which is equivalent to
@@ -285,17 +316,11 @@ class UpperBoundCheckGuard extends DataFlow::RelationalComparisonNode {
285316 then strictnessOffset = 1
286317 else strictnessOffset = 0
287318 |
288- exists ( DeclaredConstant maxint , DeclaredConstant maxuint |
289- maxint .hasQualifiedName ( "math" , "MaxInt" ) and maxuint .hasQualifiedName ( "math" , "MaxUint" )
290- |
291- if expr .getAnOperand ( ) = maxint .getAReference ( )
292- then bound = getMaxIntValue ( architectureBitSize , true )
293- else
294- if expr .getAnOperand ( ) = maxuint .getAReference ( )
295- then bound = getMaxIntValue ( architectureBitSize , false )
296- else bound = expr .getAnOperand ( ) .getExactValue ( ) .toFloat ( )
297- ) and
298- bound - strictnessOffset <= 2 .pow ( b ) - 1
319+ if expr .getAnOperand ( ) = any ( MaxIntOrMaxUint m ) .getAReference ( )
320+ then
321+ any ( MaxIntOrMaxUint m | expr .getAnOperand ( ) = m .getAReference ( ) )
322+ .isBoundFor ( b , architectureBitSize , strictnessOffset )
323+ else expr .getAnOperand ( ) .getExactValue ( ) .toFloat ( ) - strictnessOffset <= 2 .pow ( b ) - 1
299324 )
300325 }
301326
0 commit comments