@@ -427,6 +427,45 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
427
427
// - e. g. "Try harder to find a NamedDecl to point at in the note."
428
428
// already duplicated
429
429
// - call both from Sema and from here
430
+ std::function<bool (const Expr *exp, const ConstantArrayType *CATy,
431
+ unsigned int limit)>
432
+ SafeMaskedAccess;
433
+ unsigned int RecLimit = 5 ;
434
+ llvm::APInt Max;
435
+ bool Initialized = false ;
436
+
437
+ SafeMaskedAccess = [&](const Expr *exp, const ConstantArrayType *CATy,
438
+ unsigned int RecLimit) -> bool {
439
+ if (RecLimit == 0 )
440
+ return false ;
441
+
442
+ RecLimit--;
443
+
444
+ if (const auto *IntLit = dyn_cast<IntegerLiteral>(exp)) {
445
+ const APInt ArrIdx = IntLit->getValue ();
446
+ if (ArrIdx.isNonNegative () &&
447
+ ArrIdx.getLimitedValue () < CATy->getLimitedSize ())
448
+ return true ;
449
+ if (!Initialized) {
450
+ Max = ArrIdx;
451
+ Initialized = true ;
452
+ } else {
453
+ Max = Max & ArrIdx.getLimitedValue ();
454
+ }
455
+ if (Max.getLimitedValue () < CATy->getLimitedSize ())
456
+ return true ;
457
+ }
458
+
459
+ if (const auto *BinEx = dyn_cast<BinaryOperator>(exp)) {
460
+ if (SafeMaskedAccess (BinEx->getLHS ()->IgnoreParenCasts (), CATy, RecLimit))
461
+ return true ;
462
+ else if (SafeMaskedAccess (BinEx->getRHS ()->IgnoreParenCasts (), CATy,
463
+ RecLimit))
464
+ return true ;
465
+ }
466
+
467
+ return false ;
468
+ };
430
469
431
470
const auto *BaseDRE =
432
471
dyn_cast<DeclRefExpr>(Node.getBase ()->IgnoreParenImpCasts ());
@@ -446,6 +485,12 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
446
485
if (ArrIdx.isNonNegative () &&
447
486
ArrIdx.getLimitedValue () < CATy->getLimitedSize ())
448
487
return true ;
488
+ } else if (const auto *BinEx = dyn_cast<BinaryOperator>(Node.getIdx ())) {
489
+ if (BinEx->getOpcode () != BO_And)
490
+ return false ;
491
+
492
+ Max.setAllBits ();
493
+ return SafeMaskedAccess (Node.getIdx (), CATy, RecLimit);
449
494
}
450
495
451
496
return false ;
0 commit comments