@@ -40,7 +40,7 @@ type integer struct {
40
40
type rangeResult struct {
41
41
minValue int
42
42
maxValue uint
43
- explixitPositiveVals []uint
43
+ explicitPositiveVals []uint
44
44
explicitNegativeVals []int
45
45
isRangeCheck bool
46
46
convertFound bool
@@ -271,7 +271,7 @@ func hasExplicitRangeCheck(instr *ssa.Convert, dstType string) bool {
271
271
if result .isRangeCheck {
272
272
minValue = max (minValue , & result .minValue )
273
273
maxValue = min (maxValue , & result .maxValue )
274
- explicitPositiveVals = append (explicitPositiveVals , result .explixitPositiveVals ... )
274
+ explicitPositiveVals = append (explicitPositiveVals , result .explicitPositiveVals ... )
275
275
explicitNegativeVals = append (explicitNegativeVals , result .explicitNegativeVals ... )
276
276
}
277
277
case * ssa.Call :
@@ -325,16 +325,17 @@ func getResultRange(ifInstr *ssa.If, instr *ssa.Convert, visitedIfs map[*ssa.If]
325
325
result .convertFound = true
326
326
result .minValue = max (result .minValue , thenBounds .minValue )
327
327
result .maxValue = min (result .maxValue , thenBounds .maxValue )
328
- result .explixitPositiveVals = append (result .explixitPositiveVals , thenBounds .explixitPositiveVals ... )
329
- result .explicitNegativeVals = append (result .explicitNegativeVals , thenBounds .explicitNegativeVals ... )
330
328
} else if elseBounds .convertFound {
331
329
result .convertFound = true
332
330
result .minValue = max (result .minValue , elseBounds .minValue )
333
331
result .maxValue = min (result .maxValue , elseBounds .maxValue )
334
- result .explixitPositiveVals = append (result .explixitPositiveVals , elseBounds .explixitPositiveVals ... )
335
- result .explicitNegativeVals = append (result .explicitNegativeVals , elseBounds .explicitNegativeVals ... )
336
332
}
337
333
334
+ result .explicitPositiveVals = append (result .explicitPositiveVals , thenBounds .explixitPositiveVals ... )
335
+ result .explicitNegativeVals = append (result .explicitNegativeVals , thenBounds .explicitNegativeVals ... )
336
+ result .explicitPositiveVals = append (result .explicitPositiveVals , elseBounds .explixitPositiveVals ... )
337
+ result .explicitNegativeVals = append (result .explicitNegativeVals , elseBounds .explicitNegativeVals ... )
338
+
338
339
return result
339
340
}
340
341
@@ -344,8 +345,15 @@ func updateResultFromBinOp(result *rangeResult, binOp *ssa.BinOp, instr *ssa.Con
344
345
operandsFlipped := false
345
346
346
347
compareVal , op := getRealValueFromOperation (instr .X )
347
- if x != compareVal {
348
- y , operandsFlipped = x , true
348
+
349
+ // Handle FieldAddr
350
+ if fieldAddr , ok := compareVal .(* ssa.FieldAddr ); ok {
351
+ compareVal = fieldAddr
352
+ }
353
+
354
+ if ! isSameOrRelated (x , compareVal ) {
355
+ y = x
356
+ operandsFlipped = true
349
357
}
350
358
351
359
constVal , ok := y .(* ssa.Const )
@@ -362,25 +370,12 @@ func updateResultFromBinOp(result *rangeResult, binOp *ssa.BinOp, instr *ssa.Con
362
370
if ! successPathConvert {
363
371
break
364
372
}
365
-
366
- // Determine if the constant value is positive or negative.
367
- if strings .Contains (constVal .String (), "-" ) {
368
- result .explicitNegativeVals = append (result .explicitNegativeVals , int (constVal .Int64 ()))
369
- } else {
370
- result .explixitPositiveVals = append (result .explixitPositiveVals , uint (constVal .Uint64 ()))
371
- }
372
-
373
+ updateExplicitValues (result , constVal )
373
374
case token .NEQ :
374
375
if successPathConvert {
375
376
break
376
377
}
377
-
378
- // Determine if the constant value is positive or negative.
379
- if strings .Contains (constVal .String (), "-" ) {
380
- result .explicitNegativeVals = append (result .explicitNegativeVals , int (constVal .Int64 ()))
381
- } else {
382
- result .explixitPositiveVals = append (result .explixitPositiveVals , uint (constVal .Uint64 ()))
383
- }
378
+ updateExplicitValues (result , constVal )
384
379
}
385
380
386
381
if op == "neg" {
@@ -391,11 +386,19 @@ func updateResultFromBinOp(result *rangeResult, binOp *ssa.BinOp, instr *ssa.Con
391
386
result .maxValue = uint (min )
392
387
}
393
388
if max <= math .MaxInt {
394
- result .minValue = int (max ) //nolint:gosec
389
+ result .minValue = int (max )
395
390
}
396
391
}
397
392
}
398
393
394
+ func updateExplicitValues (result * rangeResult , constVal * ssa.Const ) {
395
+ if strings .Contains (constVal .String (), "-" ) {
396
+ result .explicitNegativeVals = append (result .explicitNegativeVals , int (constVal .Int64 ()))
397
+ } else {
398
+ result .explicitPositiveVals = append (result .explicitPositiveVals , uint (constVal .Uint64 ()))
399
+ }
400
+ }
401
+
399
402
func updateMinMaxForLessOrEqual (result * rangeResult , constVal * ssa.Const , op token.Token , operandsFlipped bool , successPathConvert bool ) {
400
403
// If the success path has a conversion and the operands are not flipped, then the constant value is the maximum value.
401
404
if successPathConvert && ! operandsFlipped {
@@ -439,6 +442,8 @@ func walkBranchForConvert(block *ssa.BasicBlock, instr *ssa.Convert, visitedIfs
439
442
if result .isRangeCheck {
440
443
bounds .minValue = toPtr (max (result .minValue , bounds .minValue ))
441
444
bounds .maxValue = toPtr (min (result .maxValue , bounds .maxValue ))
445
+ bounds .explixitPositiveVals = append (bounds .explixitPositiveVals , result .explicitPositiveVals ... )
446
+ bounds .explicitNegativeVals = append (bounds .explicitNegativeVals , result .explicitNegativeVals ... )
442
447
}
443
448
case * ssa.Call :
444
449
if v == instr .X {
@@ -463,9 +468,10 @@ func isRangeCheck(v ssa.Value, x ssa.Value) bool {
463
468
switch op := v .(type ) {
464
469
case * ssa.BinOp :
465
470
switch op .Op {
466
- case token .LSS , token .LEQ , token .GTR , token .GEQ ,
467
- token .EQL , token .NEQ :
468
- return op .X == compareVal || op .Y == compareVal
471
+ case token .LSS , token .LEQ , token .GTR , token .GEQ , token .EQL , token .NEQ :
472
+ leftMatch := isSameOrRelated (op .X , compareVal )
473
+ rightMatch := isSameOrRelated (op .Y , compareVal )
474
+ return leftMatch || rightMatch
469
475
}
470
476
}
471
477
return false
@@ -475,12 +481,36 @@ func getRealValueFromOperation(v ssa.Value) (ssa.Value, string) {
475
481
switch v := v .(type ) {
476
482
case * ssa.UnOp :
477
483
if v .Op == token .SUB {
478
- return v .X , "neg"
484
+ val , _ := getRealValueFromOperation (v .X )
485
+ return val , "neg"
479
486
}
487
+ return getRealValueFromOperation (v .X )
488
+ case * ssa.FieldAddr :
489
+ return v , "field"
490
+ case * ssa.Alloc :
491
+ return v , "alloc"
480
492
}
481
493
return v , ""
482
494
}
483
495
496
+ func isSameOrRelated (a , b ssa.Value ) bool {
497
+ aVal , _ := getRealValueFromOperation (a )
498
+ bVal , _ := getRealValueFromOperation (b )
499
+
500
+ if aVal == bVal {
501
+ return true
502
+ }
503
+
504
+ // Check if both are FieldAddr operations referring to the same field of the same struct
505
+ if aField , aOk := aVal .(* ssa.FieldAddr ); aOk {
506
+ if bField , bOk := bVal .(* ssa.FieldAddr ); bOk {
507
+ return aField .X == bField .X && aField .Field == bField .Field
508
+ }
509
+ }
510
+
511
+ return false
512
+ }
513
+
484
514
func explicitValsInRange (explicitPosVals []uint , explicitNegVals []int , dstInt integer ) bool {
485
515
if len (explicitPosVals ) == 0 && len (explicitNegVals ) == 0 {
486
516
return false
0 commit comments