@@ -420,6 +420,118 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) {
420
420
return false ;
421
421
}
422
422
423
+ class MaxValueEval : public RecursiveASTVisitor <MaxValueEval> {
424
+
425
+ std::vector<llvm::APInt> val;
426
+ ASTContext &Context;
427
+ llvm::APInt Max;
428
+ unsigned bit_width;
429
+
430
+ public:
431
+ typedef RecursiveASTVisitor<MaxValueEval> VisitorBase;
432
+
433
+ explicit MaxValueEval (ASTContext &Ctx, const Expr *exp) : Context(Ctx) {
434
+ bit_width = Ctx.getIntWidth (exp->getType ());
435
+ Max = llvm::APInt::getSignedMaxValue (bit_width);
436
+ val.clear ();
437
+ }
438
+
439
+ bool findMatch (Expr *exp) {
440
+ TraverseStmt (exp);
441
+ return true ;
442
+ }
443
+
444
+ bool VisitDeclRefExpr (DeclRefExpr *dre) {
445
+ val.push_back (Max);
446
+ return false ;
447
+ }
448
+
449
+ bool VisitArraySubscriptExpr (ArraySubscriptExpr *E) {
450
+ val.push_back (Max);
451
+ return false ;
452
+ }
453
+
454
+ bool EvaluateExpression (Expr *exp) {
455
+ Expr::EvalResult EVResult;
456
+ if (exp->EvaluateAsInt (EVResult, Context)) {
457
+ llvm::APSInt Result = EVResult.Val .getInt ();
458
+ val.push_back (Result);
459
+ return true ;
460
+ }
461
+ return false ;
462
+ }
463
+
464
+ bool VisitBinaryOperator (BinaryOperator *E) {
465
+
466
+ if (EvaluateExpression (E)) {
467
+ return false ;
468
+ } else {
469
+ TraverseStmt (E->getLHS ());
470
+ llvm::APInt LHS = val.back ();
471
+ val.pop_back ();
472
+
473
+ TraverseStmt (E->getRHS ());
474
+ llvm::APInt RHS = val.back ();
475
+ val.pop_back ();
476
+ llvm::APInt Result = Max;
477
+
478
+ switch (E->getOpcode ()) {
479
+ case BO_And:
480
+ case BO_AndAssign:
481
+ Result = LHS & RHS;
482
+ break ;
483
+
484
+ case BO_Or:
485
+ case BO_OrAssign:
486
+ Result = LHS | RHS;
487
+ break ;
488
+
489
+ case BO_Shl:
490
+ case BO_ShlAssign:
491
+ if (RHS != Max.getLimitedValue ())
492
+ Result = LHS << RHS.getLimitedValue ();
493
+ break ;
494
+
495
+ case BO_Shr:
496
+ case BO_ShrAssign:
497
+ if (RHS == Max.getLimitedValue ())
498
+ Result = LHS;
499
+ else
500
+ Result = LHS.getLimitedValue () >> RHS.getLimitedValue ();
501
+ break ;
502
+
503
+ case BO_Rem:
504
+ case BO_RemAssign:
505
+ if (LHS.getLimitedValue () < RHS.getLimitedValue ())
506
+ Result = LHS;
507
+ else
508
+ Result = --RHS;
509
+ break ;
510
+
511
+ default :
512
+ break ;
513
+ }
514
+ val.push_back (Result);
515
+ return false ;
516
+ }
517
+ return true ;
518
+ }
519
+
520
+ bool VisitExpr (Expr *E) {
521
+ if (EvaluateExpression (E)) {
522
+ return false ;
523
+ }
524
+ return VisitorBase::VisitExpr (E);
525
+ }
526
+
527
+ APInt getValue () {
528
+ if (val.size () == 1 )
529
+ return val[0 ];
530
+ else // A pattern we didn't consider was encountered
531
+ return Max;
532
+ }
533
+ };
534
+
423
535
AST_MATCHER (ArraySubscriptExpr, isSafeArraySubscript) {
424
536
// FIXME: Proper solution:
425
537
// - refactor Sema::CheckArrayAccess
@@ -439,14 +551,13 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
439
551
if (!CATy)
440
552
return false ;
441
553
442
- if (const auto *IdxLit = dyn_cast<IntegerLiteral>(Node.getIdx ())) {
443
- const APInt ArrIdx = IdxLit->getValue ();
444
- // FIXME: ArrIdx.isNegative() we could immediately emit an error as that's a
445
- // bug
446
- if (ArrIdx.isNonNegative () &&
447
- ArrIdx.getLimitedValue () < CATy->getLimitedSize ())
448
- return true ;
449
- }
554
+ MaxValueEval Vis (Finder->getASTContext (), Node.getIdx ());
555
+ Vis.findMatch (const_cast <Expr *>(Node.getIdx ()));
556
+ APInt result = Vis.getValue ();
557
+
558
+ if (result.isNonNegative () &&
559
+ result.getLimitedValue () < CATy->getLimitedSize ())
560
+ return true ;
450
561
451
562
return false ;
452
563
}
0 commit comments