From 0ec5f501964010d4a186a51438338656eebe7912 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sat, 16 May 2020 14:01:54 -0700 Subject: [PATCH] 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. --- llvm/lib/AsmParser/LLParser.cpp | 6 ++++-- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 6 +++++- llvm/test/Verifier/recursive-type-load.ll | 12 ++++++++++++ llvm/test/Verifier/recursive-type-store.ll | 12 ++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 llvm/test/Verifier/recursive-type-load.ll create mode 100644 llvm/test/Verifier/recursive-type-store.ll 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(Val->getType())->getElementType()) return Error(ExplicitTypeLoc, "explicit pointee type doesn't match operand's pointee type"); - if (!Alignment && !Ty->isSized()) + SmallPtrSet 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 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 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 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 +}