summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/DerivedTypes.h3
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp47
-rw-r--r--llvm/lib/IR/Type.cpp4
-rw-r--r--llvm/test/Bitcode/Inputs/invalid-load-ptr-type.bcbin0 -> 424 bytes
-rw-r--r--llvm/test/Bitcode/invalid.test9
5 files changed, 52 insertions, 11 deletions
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index 76f806434f4..38f1af0d70d 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -464,6 +464,9 @@ public:
/// 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(); }
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index e0800916c8c..86c61bdf66b 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -401,6 +401,12 @@ static std::error_code Error(DiagnosticHandlerFunction DiagnosticHandler,
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 @@ std::error_code BitcodeReader::ParseMetadataAttachment(Function &F) {
}
}
+static std::error_code TypeCheckLoadStoreInst(DiagnosticHandlerFunction DH,
+ Type *ValType, Type *PtrType) {
+ if (!isa<PointerType>(PtrType))
+ return Error(DH, "Load/Store operand is not a pointer type");
+ Type *ElemType = cast<PointerType>(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))
@@ -4071,13 +4091,11 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
Type *Ty = nullptr;
if (OpNum + 3 == Record.size())
Ty = getTypeByID(Record[OpNum++]);
- if (!isa<PointerType>(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<PointerType>(Op->getType())->getElementType();
- else if (Ty != cast<PointerType>(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))
@@ -4098,6 +4116,11 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
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<PointerType>(Op->getType())->getElementType();
AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
if (Ordering == NotAtomic || Ordering == Release ||
@@ -4112,10 +4135,6 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
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;
}
@@ -4131,6 +4150,10 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
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;
@@ -4152,6 +4175,9 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
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)
@@ -4187,6 +4213,9 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
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 =
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index d8baf7c9d33..1c405168ae2 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -765,3 +765,7 @@ bool PointerType::isValidElementType(Type *ElemTy) {
return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
!ElemTy->isMetadataTy();
}
+
+bool PointerType::isLoadableOrStorableType(Type *ElemTy) {
+ return isValidElementType(ElemTy) && !ElemTy->isFunctionTy();
+}
diff --git a/llvm/test/Bitcode/Inputs/invalid-load-ptr-type.bc b/llvm/test/Bitcode/Inputs/invalid-load-ptr-type.bc
new file mode 100644
index 00000000000..5207ed9156e
--- /dev/null
+++ b/llvm/test/Bitcode/Inputs/invalid-load-ptr-type.bc
Binary files differ
diff --git a/llvm/test/Bitcode/invalid.test b/llvm/test/Bitcode/invalid.test
index fbd1cb9f4d9..7dd97a4f49a 100644
--- a/llvm/test/Bitcode/invalid.test
+++ b/llvm/test/Bitcode/invalid.test
@@ -35,7 +35,7 @@ BAD-TYPE-TABLE-FORWARD-REF: Invalid TYPE table: Only named structs can be forwar
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,7 +121,7 @@ HUGE-FWDREF: Invalid record
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
@@ -137,3 +137,8 @@ RUN: not llvm-dis -disable-output %p/Inputs/invalid-extract-0-indices.bc 2>&1 |
RUN: FileCheck --check-prefix=EXTRACT-0-IDXS %s
EXTRACT-0-IDXS: EXTRACTVAL: Invalid instruction with 0 indices
+
+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
OpenPOWER on IntegriCloud