[llvm] 0ec5f50 - Harden IR and bitcode parsers against infinite size types.

Eli Friedman via llvm-commits llvm-commits at lists.llvm.org
Sat May 16 14:25:22 PDT 2020


Author: Eli Friedman
Date: 2020-05-16T14:24:51-07:00
New Revision: 0ec5f501964010d4a186a51438338656eebe7912

URL: https://github.com/llvm/llvm-project/commit/0ec5f501964010d4a186a51438338656eebe7912
DIFF: https://github.com/llvm/llvm-project/commit/0ec5f501964010d4a186a51438338656eebe7912.diff

LOG: Harden IR and bitcode parsers against infinite size types.

If isSized is passed a SmallPtrSet, it uses that set to catch infinitely
recursive types (for example, a struct that has itself as a member).
Otherwise, it just crashes on such types.

Added: 
    llvm/test/Verifier/recursive-type-load.ll
    llvm/test/Verifier/recursive-type-store.ll

Modified: 
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 13c7eafff381..c0db5884bc37 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -7057,7 +7057,8 @@ int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS) {
   if (Ty != cast<PointerType>(Val->getType())->getElementType())
     return Error(ExplicitTypeLoc,
                  "explicit pointee type doesn't match operand's pointee type");
-  if (!Alignment && !Ty->isSized())
+  SmallPtrSet<Type *, 4> Visited;
+  if (!Alignment && !Ty->isSized(&Visited))
     return Error(ExplicitTypeLoc, "loading unsized types is not allowed");
   if (!Alignment)
     Alignment = M->getDataLayout().getABITypeAlign(Ty);
@@ -7107,7 +7108,8 @@ int LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS) {
   if (Ordering == AtomicOrdering::Acquire ||
       Ordering == AtomicOrdering::AcquireRelease)
     return Error(Loc, "atomic store cannot use Acquire ordering");
-  if (!Alignment && !Val->getType()->isSized())
+  SmallPtrSet<Type *, 4> Visited;
+  if (!Alignment && !Val->getType()->isSized(&Visited))
     return Error(Loc, "storing unsized types is not allowed");
   if (!Alignment)
     Alignment = M->getDataLayout().getABITypeAlign(Val->getType());

diff  --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 64427b75d5da..7b62bab3041d 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -4857,7 +4857,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
       MaybeAlign Align;
       if (Error Err = parseAlignmentValue(Record[OpNum], Align))
         return Err;
-      if (!Align && !Ty->isSized())
+      SmallPtrSet<Type *, 4> Visited;
+      if (!Align && !Ty->isSized(&Visited))
         return error("load of unsized type");
       if (!Align)
         Align = TheModule->getDataLayout().getABITypeAlign(Ty);
@@ -4922,6 +4923,9 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
       MaybeAlign Align;
       if (Error Err = parseAlignmentValue(Record[OpNum], Align))
         return Err;
+      SmallPtrSet<Type *, 4> Visited;
+      if (!Align && !Val->getType()->isSized(&Visited))
+        return error("store of unsized type");
       if (!Align)
         Align = TheModule->getDataLayout().getABITypeAlign(Val->getType());
       I = new StoreInst(Val, Ptr, Record[OpNum + 1], *Align);

diff  --git a/llvm/test/Verifier/recursive-type-load.ll b/llvm/test/Verifier/recursive-type-load.ll
new file mode 100644
index 000000000000..6a4215d815f4
--- /dev/null
+++ b/llvm/test/Verifier/recursive-type-load.ll
@@ -0,0 +1,12 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+%rt2 = type { i32, { i8, %rt2, i8 }, i32 }
+
+define i32 @f(%rt2* %p) nounwind {
+entry:
+  ; Check that recursive types trigger an error instead of segfaulting, when
+  ; the recursion isn't through a pointer to the type.
+  ; CHECK: loading unsized types is not allowed
+  %0 = load %rt2, %rt2* %p
+  ret i32 %0
+}

diff  --git a/llvm/test/Verifier/recursive-type-store.ll b/llvm/test/Verifier/recursive-type-store.ll
new file mode 100644
index 000000000000..1756b0678d6a
--- /dev/null
+++ b/llvm/test/Verifier/recursive-type-store.ll
@@ -0,0 +1,12 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+%rt2 = type { i32, { i8, %rt2, i8 }, i32 }
+
+define void @f(%rt2 %r, %rt2 *%p) nounwind {
+entry:
+  ; Check that recursive types trigger an error instead of segfaulting, when
+  ; the recursion isn't through a pointer to the type.
+  ; CHECK: storing unsized types is not allowed
+  store %rt2 %r, %rt2 *%p
+  ret void
+}


        


More information about the llvm-commits mailing list