[llvm] r262268 - [Verifier] Handle more funclet edge cases

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 29 14:56:37 PST 2016


Author: majnemer
Date: Mon Feb 29 16:56:36 2016
New Revision: 262268

URL: http://llvm.org/viewvc/llvm-project?rev=262268&view=rev
Log:
[Verifier] Handle more funclet edge cases

This change makes the verifier a little more paranoid.  It was possible
to trick the verifier into crashing or infinite looping.

Modified:
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/test/Verifier/invalid-eh.ll

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=262268&r1=262267&r2=262268&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Mon Feb 29 16:56:36 2016
@@ -3119,8 +3119,6 @@ void Verifier::visitLandingPadInst(Landi
 }
 
 void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
-  visitEHPadPredecessors(CPI);
-
   BasicBlock *BB = CPI.getParent();
 
   Function *F = BB->getParent();
@@ -3136,6 +3134,7 @@ void Verifier::visitCatchPadInst(CatchPa
   Assert(BB->getFirstNonPHI() == &CPI,
          "CatchPadInst not the first non-PHI instruction in the block.", &CPI);
 
+  visitEHPadPredecessors(CPI);
   visitFuncletPadInst(CPI);
 }
 
@@ -3148,8 +3147,6 @@ void Verifier::visitCatchReturnInst(Catc
 }
 
 void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
-  visitEHPadPredecessors(CPI);
-
   BasicBlock *BB = CPI.getParent();
 
   Function *F = BB->getParent();
@@ -3166,6 +3163,7 @@ void Verifier::visitCleanupPadInst(Clean
   Assert(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),
          "CleanupPadInst has an invalid parent.", &CPI);
 
+  visitEHPadPredecessors(CPI);
   visitFuncletPadInst(CPI);
 }
 
@@ -3173,8 +3171,12 @@ void Verifier::visitFuncletPadInst(Funcl
   User *FirstUser = nullptr;
   Value *FirstUnwindPad = nullptr;
   SmallVector<FuncletPadInst *, 8> Worklist({&FPI});
+  std::set<FuncletPadInst *> Seen;
+
   while (!Worklist.empty()) {
     FuncletPadInst *CurrentPad = Worklist.pop_back_val();
+    Assert(Seen.insert(CurrentPad).second,
+           "FuncletPadInst must not be nested within itself", CurrentPad);
     Value *UnresolvedAncestorPad = nullptr;
     for (User *U : CurrentPad->users()) {
       BasicBlock *UnwindDest;
@@ -3210,6 +3212,8 @@ void Verifier::visitFuncletPadInst(Funcl
       bool ExitsFPI;
       if (UnwindDest) {
         UnwindPad = UnwindDest->getFirstNonPHI();
+        if (!cast<Instruction>(UnwindPad)->isEHPad())
+          continue;
         Value *UnwindParent = getParentPad(UnwindPad);
         // Ignore unwind edges that don't exit CurrentPad.
         if (UnwindParent == CurrentPad)
@@ -3323,8 +3327,6 @@ void Verifier::visitFuncletPadInst(Funcl
 }
 
 void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) {
-  visitEHPadPredecessors(CatchSwitch);
-
   BasicBlock *BB = CatchSwitch.getParent();
 
   Function *F = BB->getParent();
@@ -3362,6 +3364,7 @@ void Verifier::visitCatchSwitchInst(Catc
            "CatchSwitchInst handlers must be catchpads", &CatchSwitch, Handler);
   }
 
+  visitEHPadPredecessors(CatchSwitch);
   visitTerminatorInst(CatchSwitch);
 }
 

Modified: llvm/trunk/test/Verifier/invalid-eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/invalid-eh.ll?rev=262268&r1=262267&r2=262268&view=diff
==============================================================================
--- llvm/trunk/test/Verifier/invalid-eh.ll (original)
+++ llvm/trunk/test/Verifier/invalid-eh.ll Mon Feb 29 16:56:36 2016
@@ -19,6 +19,9 @@
 ; RUN: sed -e s/.T19:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK19 %s
 ; RUN: sed -e s/.T20:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK20 %s
 ; RUN: sed -e s/.T21:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK21 %s
+; RUN: sed -e s/.T22:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK22 %s
+; RUN: sed -e s/.T23:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK23 %s
+; RUN: sed -e s/.T24:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK24 %s
 
 declare void @g()
 
@@ -370,3 +373,50 @@ declare void @g()
 ;T21:     %cp2 = catchpad within %cs [i32 2]
 ;T21:     unreachable
 ;T21: }
+
+;T22: define void @f() personality void ()* @g {
+;T22:   invoke void @g()
+;T22:           to label %merge unwind label %cleanup
+;T22:
+;T22: cleanup:
+;T22:   %outer = cleanuppad within none []
+;T22:   invoke void @g() [ "funclet"(token %outer) ]
+;T22:           to label %merge unwind label %merge
+;T22:   ; CHECK22: The unwind destination does not have an exception handling instruction!
+;T22:   ; CHECK22:   invoke void @g() [ "funclet"(token %outer) ]
+;T22:   ; CHECK22:           to label %merge unwind label %merge
+;T22:
+;T22: merge:
+;T22:   unreachable
+;T22: }
+
+;T23: define void @f() personality void ()* @g {
+;T23:   invoke void @g()
+;T23:           to label %exit unwind label %pad
+;T23:
+;T23: pad:
+;T23:   %outer = catchpad within %outer []
+;T23:   ; CHECK23: CatchPadInst needs to be directly nested in a CatchSwitchInst.
+;T23:   ; CHECK23:   %outer = catchpad within %outer []
+;T23:   unreachable
+;T23:
+;T23: exit:
+;T23:   unreachable
+;T23: }
+
+;T24: define void @f() personality void ()* @g {
+;T24:   invoke void @g()
+;T24:           to label %exit unwind label %pad
+;T24:   ; CHECK24: A single unwind edge may only enter one EH pad
+;T24:   ; CHECK24:   invoke void @g()
+;T24:   ; CHECK24:           to label %exit unwind label %pad
+;T24:
+;T24: pad:
+;T24:   %outer = cleanuppad within %outer []
+;T24:   ; CHECK24: FuncletPadInst must not be nested within itself
+;T24:   ; CHECK24:   %outer = cleanuppad within %outer []
+;T24:   unreachable
+;T24:
+;T24: exit:
+;T24:   unreachable
+;T24: }




More information about the llvm-commits mailing list