@@ -431,6 +431,151 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) {
431
431
return false ;
432
432
}
433
433
434
+ class MaxValueEval : public ConstStmtVisitor <MaxValueEval, llvm::APInt> {
435
+
436
+ ASTContext &Context;
437
+ llvm::APInt Max;
438
+ unsigned bit_width;
439
+
440
+ public:
441
+ typedef ConstStmtVisitor<MaxValueEval, llvm::APInt> VisitorBase;
442
+
443
+ explicit MaxValueEval (ASTContext &Ctx, const Expr *exp) : Context(Ctx) {
444
+ bit_width = Ctx.getIntWidth (exp->getType ());
445
+ Max = llvm::APInt::getSignedMaxValue (bit_width);
446
+ // val.clear();
447
+ }
448
+
449
+ llvm::APInt findMatch (Expr *exp) { return TraverseStmt (exp); }
450
+
451
+ llvm::APInt TraverseStmt (Stmt *S) {
452
+ if (Expr *E = dyn_cast<Expr>(S)) {
453
+ Expr::EvalResult EVResult;
454
+ if (EvaluateExpression (E, EVResult)) {
455
+ return EVResult.Val .getInt ();
456
+ } else if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
457
+ return TraverseImplicitCastExpr (ICE);
458
+ } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
459
+ return Max;
460
+ } else if (ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
461
+ return Max;
462
+ } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
463
+ return TraverseBinaryOperator (BO);
464
+ } else if (IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E)) {
465
+ return IL->getValue ();
466
+ }
467
+ }
468
+ return Max;
469
+ }
470
+
471
+ llvm::APInt TraverseImplicitCastExpr (ImplicitCastExpr *E) {
472
+ Expr::EvalResult EVResult;
473
+ if (EvaluateExpression (E, EVResult)) {
474
+ return EVResult.Val .getInt ();
475
+ } else {
476
+ Expr *eExpr = E->getSubExpr ();
477
+ llvm::APInt subEValue = TraverseStmt (eExpr);
478
+ switch (E->getCastKind ()) {
479
+ case CK_LValueToRValue:
480
+ return subEValue;
481
+ case CK_IntegralCast: {
482
+ Expr *eExpr = E->getSubExpr ();
483
+ clang::IntegerLiteral *intLiteral = clang::IntegerLiteral::Create (
484
+ Context, subEValue, eExpr->getType (), {});
485
+ E->setSubExpr (intLiteral);
486
+ bool evaluated = EvaluateExpression (E, EVResult);
487
+ E->setSubExpr (eExpr);
488
+ if (evaluated) {
489
+ return EVResult.Val .getInt ();
490
+ }
491
+ break ;
492
+ }
493
+ default :
494
+ break ;
495
+ }
496
+ return Max;
497
+ }
498
+ }
499
+
500
+ bool EvaluateExpression (Expr *exp, Expr::EvalResult &EVResult) {
501
+ if (exp->EvaluateAsInt (EVResult, Context)) {
502
+ return true ;
503
+ }
504
+ return false ;
505
+ }
506
+
507
+ llvm::APInt TraverseBinaryOperator (BinaryOperator *E) {
508
+ unsigned bwidth = Context.getIntWidth (E->getType ());
509
+
510
+ auto evaluateSubExpr = [&, bwidth](Expr *E) -> llvm::APInt {
511
+ llvm::APInt Result = TraverseStmt (E);
512
+ unsigned width = Result.getBitWidth ();
513
+
514
+ // Fix the bit length.
515
+ if (bwidth < width)
516
+ Result = Result.trunc (bwidth);
517
+ else if (bwidth > width)
518
+ Result =
519
+ APInt (bwidth, Result.getLimitedValue (), Result.isSignedIntN (width));
520
+ return Result;
521
+ };
522
+
523
+ Expr::EvalResult EVResult;
524
+ if (EvaluateExpression (E, EVResult)) {
525
+ return EVResult.Val .getInt ();
526
+ } else {
527
+ Expr *LHSExpr = E->getLHS ()->IgnoreParenCasts ();
528
+ Expr *RHSExpr = E->getRHS ()->IgnoreParenCasts ();
529
+
530
+ unsigned bwidth = Context.getIntWidth (E->getType ());
531
+
532
+ llvm::APInt LHS = evaluateSubExpr (LHSExpr);
533
+ llvm::APInt RHS = evaluateSubExpr (RHSExpr);
534
+
535
+ llvm::APInt Result = Max;
536
+
537
+ switch (E->getOpcode ()) {
538
+ case BO_And:
539
+ case BO_AndAssign:
540
+ Result = LHS & RHS;
541
+ break ;
542
+
543
+ case BO_Or:
544
+ case BO_OrAssign:
545
+ Result = LHS | RHS;
546
+ break ;
547
+
548
+ case BO_Shl:
549
+ case BO_ShlAssign:
550
+ if (RHS != Max.getLimitedValue ())
551
+ Result = LHS << RHS.getLimitedValue ();
552
+ break ;
553
+
554
+ case BO_Shr:
555
+ case BO_ShrAssign:
556
+ if (RHS == Max.getLimitedValue ())
557
+ Result = LHS;
558
+ else
559
+ Result = LHS.getLimitedValue () >> RHS.getLimitedValue ();
560
+ break ;
561
+
562
+ case BO_Rem:
563
+ case BO_RemAssign:
564
+ if (LHS.getLimitedValue () < RHS.getLimitedValue ())
565
+ Result = LHS;
566
+ else
567
+ Result = --RHS;
568
+ break ;
569
+
570
+ default :
571
+ break ;
572
+ }
573
+ return Result;
574
+ }
575
+ return Max;
576
+ }
577
+ };
578
+
434
579
AST_MATCHER (ArraySubscriptExpr, isSafeArraySubscript) {
435
580
// FIXME: Proper solution:
436
581
// - refactor Sema::CheckArrayAccess
@@ -453,11 +598,12 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
453
598
return false ;
454
599
}
455
600
456
- if (const auto *IdxLit = dyn_cast<IntegerLiteral>(Node.getIdx ())) {
457
- const APInt ArrIdx = IdxLit->getValue ();
458
- if (ArrIdx.isNonNegative () && ArrIdx.getLimitedValue () < limit)
459
- return true ;
460
- }
601
+ MaxValueEval Vis (Finder->getASTContext (), Node.getIdx ());
602
+ APInt result = Vis.findMatch (const_cast <Expr *>(Node.getIdx ()));
603
+
604
+ if (result.isNonNegative () && result.getLimitedValue () < limit)
605
+ return true ;
606
+
461
607
return false ;
462
608
}
463
609
0 commit comments