@@ -431,6 +431,122 @@ 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 (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
455
+ return TraverseImplicitCastExpr (ICE);
456
+ } else if (dyn_cast<DeclRefExpr>(E)) {
457
+ return Max;
458
+ } else if (dyn_cast<ArraySubscriptExpr>(E)) {
459
+ return Max;
460
+ } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
461
+ return TraverseBinaryOperator (BO);
462
+ } else if (IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E)) {
463
+ return IL->getValue ();
464
+ }
465
+ }
466
+ return Max;
467
+ }
468
+
469
+ llvm::APInt TraverseImplicitCastExpr (ImplicitCastExpr *E) {
470
+ Expr::EvalResult EVResult;
471
+ if (EvaluateExpression (E, EVResult)) {
472
+ return EVResult.Val .getInt ();
473
+ } else {
474
+ Expr *eExpr = E->getSubExpr ();
475
+ llvm::APInt subEValue = TraverseStmt (eExpr);
476
+ switch (E->getCastKind ()) {
477
+ case CK_LValueToRValue:
478
+ return subEValue;
479
+ case CK_IntegralCast: {
480
+ Expr *eExpr = E->getSubExpr ();
481
+ clang::IntegerLiteral *intLiteral = clang::IntegerLiteral::Create (
482
+ Context, subEValue, eExpr->getType (), {});
483
+ E->setSubExpr (intLiteral);
484
+ bool evaluated = EvaluateExpression (E, EVResult);
485
+ E->setSubExpr (eExpr);
486
+ if (evaluated) {
487
+ return EVResult.Val .getInt ();
488
+ }
489
+ break ;
490
+ }
491
+ default :
492
+ break ;
493
+ }
494
+ return Max;
495
+ }
496
+ }
497
+
498
+ bool EvaluateExpression (Expr *exp, Expr::EvalResult &EVResult) {
499
+ if (exp->EvaluateAsInt (EVResult, Context)) {
500
+ return true ;
501
+ }
502
+ return false ;
503
+ }
504
+
505
+ llvm::APInt TraverseBinaryOperator (BinaryOperator *E) {
506
+ unsigned bwidth = Context.getIntWidth (E->getType ());
507
+
508
+ auto evaluateSubExpr = [&, bwidth](Expr *E) -> llvm::APInt {
509
+ llvm::APInt Result = TraverseStmt (E);
510
+ unsigned width = Result.getBitWidth ();
511
+
512
+ // Fix the bit length.
513
+ if (bwidth < width)
514
+ Result = Result.trunc (bwidth);
515
+ else if (bwidth > width)
516
+ Result =
517
+ APInt (bwidth, Result.getLimitedValue (), Result.isSignedIntN (width));
518
+ return Result;
519
+ };
520
+
521
+ Expr::EvalResult EVResult;
522
+ if (EvaluateExpression (E, EVResult)) {
523
+ return EVResult.Val .getInt ();
524
+ } else {
525
+ Expr *LHSExpr = E->getLHS ()->IgnoreParenCasts ();
526
+ Expr *RHSExpr = E->getRHS ()->IgnoreParenCasts ();
527
+
528
+ unsigned bwidth = Context.getIntWidth (E->getType ());
529
+
530
+ llvm::APInt LHS = evaluateSubExpr (LHSExpr);
531
+ llvm::APInt RHS = evaluateSubExpr (RHSExpr);
532
+
533
+ llvm::APInt Result = Max;
534
+
535
+ switch (E->getOpcode ()) {
536
+ case BO_And:
537
+ case BO_AndAssign:
538
+ Result = LHS & RHS;
539
+ break ;
540
+
541
+ default :
542
+ break ;
543
+ }
544
+ return Result;
545
+ }
546
+ return Max;
547
+ }
548
+ };
549
+
434
550
AST_MATCHER (ArraySubscriptExpr, isSafeArraySubscript) {
435
551
// FIXME: Proper solution:
436
552
// - refactor Sema::CheckArrayAccess
@@ -463,6 +579,13 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
463
579
if (ArrIdx.isNonNegative () && ArrIdx.getLimitedValue () < limit)
464
580
return true ;
465
581
}
582
+
583
+ MaxValueEval Vis (Finder->getASTContext (), Node.getIdx ());
584
+ APInt result = Vis.findMatch (const_cast <Expr *>(Node.getIdx ()));
585
+
586
+ if (result.isNonNegative () && result.getLimitedValue () < limit)
587
+ return true ;
588
+
466
589
return false ;
467
590
}
468
591
0 commit comments