Index: include/llvm/IR/DerivedTypes.h =================================================================== --- include/llvm/IR/DerivedTypes.h +++ include/llvm/IR/DerivedTypes.h @@ -464,6 +464,9 @@ /// element type. static bool isValidElementType(Type *ElemTy); + /// Return true if we can load or store from a pointer to this type. + static bool isLoadableOrStorableType(Type *ElemTy); + /// @brief Return the address space of the Pointer type. inline unsigned getAddressSpace() const { return getSubclassData(); } Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -401,6 +401,12 @@ return Error(DiagnosticHandler, EC, EC.message()); } +static std::error_code Error(DiagnosticHandlerFunction DiagnosticHandler, + const Twine &Message) { + return Error(DiagnosticHandler, + make_error_code(BitcodeError::CorruptedBitcode), Message); +} + std::error_code BitcodeReader::Error(BitcodeError E, const Twine &Message) { return ::Error(DiagnosticHandler, make_error_code(E), Message); } @@ -3290,6 +3296,20 @@ } } +static std::error_code TypeCheckLoadStoreInst(DiagnosticHandlerFunction DH, + Type *ValType, Type *PtrType) { + if (!isa(PtrType)) + return Error(DH, "Load/Store operand is not a pointer type"); + Type *ElemType = cast(PtrType)->getElementType(); + + if (ValType && ValType != ElemType) + return Error(DH, "Explicit load/store type does not match pointee type of " + "pointer operand"); + if (!PointerType::isLoadableOrStorableType(ElemType)) + return Error(DH, "Cannot load/store from pointer"); + return std::error_code(); +} + /// ParseFunctionBody - Lazily parse the specified function body block. std::error_code BitcodeReader::ParseFunctionBody(Function *F) { if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID)) @@ -4067,13 +4087,11 @@ Type *Ty = nullptr; if (OpNum + 3 == Record.size()) Ty = getTypeByID(Record[OpNum++]); - if (!isa(Op->getType())) - return Error("Load operand is not a pointer type"); + if (std::error_code EC = + TypeCheckLoadStoreInst(DiagnosticHandler, Ty, Op->getType())) + return EC; if (!Ty) Ty = cast(Op->getType())->getElementType(); - else if (Ty != cast(Op->getType())->getElementType()) - return Error("Explicit load type does not match pointee type of " - "pointer operand"); unsigned Align; if (std::error_code EC = parseAlignmentValue(Record[OpNum], Align)) @@ -4094,6 +4112,11 @@ Type *Ty = nullptr; if (OpNum + 5 == Record.size()) Ty = getTypeByID(Record[OpNum++]); + if (std::error_code EC = + TypeCheckLoadStoreInst(DiagnosticHandler, Ty, Op->getType())) + return EC; + if (!Ty) + Ty = cast(Op->getType())->getElementType(); AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]); if (Ordering == NotAtomic || Ordering == Release || @@ -4108,10 +4131,6 @@ return EC; I = new LoadInst(Op, "", Record[OpNum+1], Align, Ordering, SynchScope); - (void)Ty; - assert((!Ty || Ty == I->getType()) && - "Explicit type doesn't match pointee type of the first operand"); - InstructionList.push_back(I); break; } @@ -4127,6 +4146,10 @@ Val)) || OpNum + 2 != Record.size()) return Error("Invalid record"); + + if (std::error_code EC = TypeCheckLoadStoreInst( + DiagnosticHandler, Val->getType(), Ptr->getType())) + return EC; unsigned Align; if (std::error_code EC = parseAlignmentValue(Record[OpNum], Align)) return EC; @@ -4148,6 +4171,9 @@ OpNum + 4 != Record.size()) return Error("Invalid record"); + if (std::error_code EC = TypeCheckLoadStoreInst( + DiagnosticHandler, Val->getType(), Ptr->getType())) + return EC; AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]); if (Ordering == NotAtomic || Ordering == Acquire || Ordering == AcquireRelease) @@ -4183,6 +4209,9 @@ return Error("Invalid record"); SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+2]); + if (std::error_code EC = TypeCheckLoadStoreInst( + DiagnosticHandler, Cmp->getType(), Ptr->getType())) + return EC; AtomicOrdering FailureOrdering; if (Record.size() < 7) FailureOrdering = Index: lib/IR/Type.cpp =================================================================== --- lib/IR/Type.cpp +++ lib/IR/Type.cpp @@ -765,3 +765,7 @@ return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && !ElemTy->isMetadataTy(); } + +bool PointerType::isLoadableOrStorableType(Type *ElemTy) { + return isValidElementType(ElemTy) && !ElemTy->isFunctionTy(); +} Index: test/Bitcode/invalid.test =================================================================== --- test/Bitcode/invalid.test +++ test/Bitcode/invalid.test @@ -35,7 +35,7 @@ BAD-BITWIDTH: Bitwidth for integer type out of range BAD-ALIGN: Invalid alignment value MISMATCHED-EXPLICIT-GEP: Explicit gep type does not match pointee type of pointer operand -MISMATCHED-EXPLICIT-LOAD: Explicit load type does not match pointee type of pointer operand +MISMATCHED-EXPLICIT-LOAD: Explicit load/store type does not match pointee type of pointer operand MISMATCHED-EXPLICIT-GEP-OPERATOR: Explicit gep operator type does not match pointee type of pointer operand MISMATCHED-EXPLICIT-CALL: Explicit call type does not match pointee type of callee operand NON-FUNCTION-EXPLICIT-CALL: Explicit call type is not a function type @@ -121,9 +121,14 @@ RUN: not llvm-dis -disable-output %p/Inputs/invalid-load-pointer-type.bc 2>&1 | \ RUN: FileCheck --check-prefix=LOAD-BAD-TYPE %s -LOAD-BAD-TYPE: Load operand is not a pointer type +LOAD-BAD-TYPE: Load/Store operand is not a pointer type RUN: not llvm-dis -disable-output %p/Inputs/invalid-GCTable-overflow.bc 2>&1 | \ RUN: FileCheck --check-prefix=GCTABLE-OFLOW %s GCTABLE-OFLOW: Invalid ID + +RUN: not llvm-dis -disable-output %p/Inputs/invalid-load-ptr-type.bc 2>&1 | \ +RUN: FileCheck --check-prefix=BAD-LOAD-PTR-TYPE %s + +BAD-LOAD-PTR-TYPE: Cannot load/store from pointer