@@ -317,6 +317,7 @@ class ReturnOfOriginFact : public Fact {
317
317
class UseFact : public Fact {
318
318
OriginID UsedOrigin;
319
319
const Expr *UseExpr;
320
+ bool IsWritten = false ;
320
321
321
322
public:
322
323
static bool classof (const Fact *F) { return F->getKind () == Kind::Use; }
@@ -326,6 +327,8 @@ class UseFact : public Fact {
326
327
327
328
OriginID getUsedOrigin () const { return UsedOrigin; }
328
329
const Expr *getUseExpr () const { return UseExpr; }
330
+ void markAsWritten () { IsWritten = true ; }
331
+ bool isWritten () const { return IsWritten; }
329
332
330
333
void dump (llvm::raw_ostream &OS, const OriginManager &OM) const override {
331
334
OS << " Use (" ;
@@ -428,6 +431,8 @@ class FactGeneratorVisitor : public ConstStmtVisitor<FactGeneratorVisitor> {
428
431
addAssignOriginFact (*VD, *InitExpr);
429
432
}
430
433
434
+ void VisitDeclRefExpr (const DeclRefExpr *DRE) { handleUse (DRE); }
435
+
431
436
void VisitCXXNullPtrLiteralExpr (const CXXNullPtrLiteralExpr *N) {
432
437
// / TODO: Handle nullptr expr as a special 'null' loan. Uninitialized
433
438
// / pointers can use the same type of loan.
@@ -461,10 +466,6 @@ class FactGeneratorVisitor : public ConstStmtVisitor<FactGeneratorVisitor> {
461
466
}
462
467
}
463
468
}
464
- } else if (UO->getOpcode () == UO_Deref) {
465
- // This is a pointer use, like '*p'.
466
- OriginID OID = FactMgr.getOriginMgr ().get (*UO->getSubExpr ());
467
- CurrentBlockFacts.push_back (FactMgr.createFact <UseFact>(OID, UO));
468
469
}
469
470
}
470
471
@@ -479,20 +480,13 @@ class FactGeneratorVisitor : public ConstStmtVisitor<FactGeneratorVisitor> {
479
480
}
480
481
481
482
void VisitBinaryOperator (const BinaryOperator *BO) {
482
- if (BO->isAssignmentOp ()) {
483
- const Expr *LHSExpr = BO->getLHS ();
484
- const Expr *RHSExpr = BO->getRHS ();
485
-
486
- // We are interested in assignments like `ptr1 = ptr2` or `ptr = &var`
487
- // LHS must be a pointer/reference type that can be an origin.
488
- // RHS must also represent an origin (either another pointer/ref or an
489
- // address-of).
490
- if (const auto *DRE_LHS = dyn_cast<DeclRefExpr>(LHSExpr))
491
- if (const auto *VD_LHS =
492
- dyn_cast<ValueDecl>(DRE_LHS->getDecl ()->getCanonicalDecl ());
493
- VD_LHS && hasOrigin (VD_LHS->getType ()))
494
- addAssignOriginFact (*VD_LHS, *RHSExpr);
495
- }
483
+ if (BO->isAssignmentOp ())
484
+ handleAssignment (BO->getLHS (), BO->getRHS ());
485
+ }
486
+
487
+ void VisitCXXOperatorCallExpr (const CXXOperatorCallExpr *OCE) {
488
+ if (OCE->isAssignmentOp () && OCE->getNumArgs () == 2 )
489
+ handleAssignment (OCE->getArg (0 ), OCE->getArg (1 ));
496
490
}
497
491
498
492
void VisitCXXFunctionalCastExpr (const CXXFunctionalCastExpr *FCE) {
@@ -559,9 +553,45 @@ class FactGeneratorVisitor : public ConstStmtVisitor<FactGeneratorVisitor> {
559
553
return false ;
560
554
}
561
555
556
+ void handleAssignment (const Expr *LHSExpr, const Expr *RHSExpr) {
557
+ // Find the underlying variable declaration for the left-hand side.
558
+ if (const auto *DRE_LHS =
559
+ dyn_cast<DeclRefExpr>(LHSExpr->IgnoreParenImpCasts ())) {
560
+ markUseAsWrite (DRE_LHS);
561
+ if (const auto *VD_LHS = dyn_cast<ValueDecl>(DRE_LHS->getDecl ()))
562
+ if (hasOrigin (VD_LHS->getType ()))
563
+ // We are interested in assignments like `ptr1 = ptr2` or `ptr = &var`
564
+ // LHS must be a pointer/reference type that can be an origin.
565
+ // RHS must also represent an origin (either another pointer/ref or an
566
+ // address-of).
567
+ addAssignOriginFact (*VD_LHS, *RHSExpr);
568
+ }
569
+ }
570
+
571
+ // A DeclRefExpr is a use of the referenced decl. It is checked for
572
+ // use-after-free unless it is being written to (e.g. on the left-hand side
573
+ // of an assignment).
574
+ void handleUse (const DeclRefExpr *DRE) {
575
+ const auto *VD = dyn_cast<ValueDecl>(DRE->getDecl ());
576
+ if (VD && hasOrigin (VD->getType ())) {
577
+ OriginID OID = FactMgr.getOriginMgr ().get (*VD);
578
+ UseFact *UF = FactMgr.createFact <UseFact>(OID, DRE);
579
+ CurrentBlockFacts.push_back (UF);
580
+ assert (!UseFacts.contains (DRE));
581
+ UseFacts[DRE] = UF;
582
+ }
583
+ }
584
+
585
+ void markUseAsWrite (const DeclRefExpr *DRE) {
586
+ assert (UseFacts.contains (DRE));
587
+ UseFacts[DRE]->markAsWritten ();
588
+ }
589
+
562
590
FactManager &FactMgr;
563
591
const CFGBlock *CurrentBlock = nullptr ;
564
592
llvm::SmallVector<Fact *> CurrentBlockFacts;
593
+ // Doc: Why do we need this ?
594
+ llvm::DenseMap<const DeclRefExpr *, UseFact *> UseFacts;
565
595
};
566
596
567
597
class FactGenerator : public RecursiveASTVisitor <FactGenerator> {
@@ -1076,7 +1106,8 @@ class LifetimeChecker {
1076
1106
// / graph. It determines if the loans held by the used origin have expired
1077
1107
// / at the point of use.
1078
1108
void checkUse (const UseFact *UF) {
1079
-
1109
+ if (UF->isWritten ())
1110
+ return ;
1080
1111
OriginID O = UF->getUsedOrigin ();
1081
1112
1082
1113
// Get the set of loans that the origin might hold at this program point.
0 commit comments