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.
This commit is contained in:
Eli Friedman 2020-05-16 14:01:54 -07:00
parent accd9af838
commit 0ec5f50196
4 changed files with 33 additions and 3 deletions

View File

@ -7057,7 +7057,8 @@ int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS) {
if (Ty != cast<PointerType>(Val->getType())->getElementType()) if (Ty != cast<PointerType>(Val->getType())->getElementType())
return Error(ExplicitTypeLoc, return Error(ExplicitTypeLoc,
"explicit pointee type doesn't match operand's pointee type"); "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"); return Error(ExplicitTypeLoc, "loading unsized types is not allowed");
if (!Alignment) if (!Alignment)
Alignment = M->getDataLayout().getABITypeAlign(Ty); Alignment = M->getDataLayout().getABITypeAlign(Ty);
@ -7107,7 +7108,8 @@ int LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS) {
if (Ordering == AtomicOrdering::Acquire || if (Ordering == AtomicOrdering::Acquire ||
Ordering == AtomicOrdering::AcquireRelease) Ordering == AtomicOrdering::AcquireRelease)
return Error(Loc, "atomic store cannot use Acquire ordering"); 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"); return Error(Loc, "storing unsized types is not allowed");
if (!Alignment) if (!Alignment)
Alignment = M->getDataLayout().getABITypeAlign(Val->getType()); Alignment = M->getDataLayout().getABITypeAlign(Val->getType());

View File

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

View File

@ -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
}

View File

@ -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
}