From: Hans Wennborg Date: Tue, 17 Feb 2015 23:40:20 +0000 (+0000) Subject: Merging r229352: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aa43f964b290b7d83b2be822962673ce15591821;p=llvm Merging r229352: ------------------------------------------------------------------------ r229352 | majnemer | 2015-02-15 20:02:09 -0800 (Sun, 15 Feb 2015) | 8 lines IR: Properly return nullptr when getAggregateElement is out-of-bounds We didn't properly handle the out-of-bounds case for ConstantAggregateZero and UndefValue. This would manifest as a crash when the constant folder was asked to fold a load of a constant global whose struct type has no operands. This fixes PR22595. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_36@229588 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 1b0e1b7e7b7..5b098b4f51d 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -325,6 +325,9 @@ public: /// index. Constant *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + /// Methods for support type inquiry through isa, cast, and dyn_cast: /// static bool classof(const Value *V) { @@ -1196,6 +1199,9 @@ public: /// index. UndefValue *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + void destroyConstant() override; /// Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index 1d2602aef13..44052b22457 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -257,11 +257,11 @@ Constant *Constant::getAggregateElement(unsigned Elt) const { if (const ConstantVector *CV = dyn_cast(this)) return Elt < CV->getNumOperands() ? CV->getOperand(Elt) : nullptr; - if (const ConstantAggregateZero *CAZ =dyn_cast(this)) - return CAZ->getElementValue(Elt); + if (const ConstantAggregateZero *CAZ = dyn_cast(this)) + return Elt < CAZ->getNumElements() ? CAZ->getElementValue(Elt) : nullptr; if (const UndefValue *UV = dyn_cast(this)) - return UV->getElementValue(Elt); + return Elt < UV->getNumElements() ? UV->getElementValue(Elt) : nullptr; if (const ConstantDataSequential *CDS =dyn_cast(this)) return Elt < CDS->getNumElements() ? CDS->getElementAsConstant(Elt) @@ -764,6 +764,14 @@ Constant *ConstantAggregateZero::getElementValue(unsigned Idx) const { return getStructElement(Idx); } +unsigned ConstantAggregateZero::getNumElements() const { + const Type *Ty = getType(); + if (const auto *AT = dyn_cast(Ty)) + return AT->getNumElements(); + if (const auto *VT = dyn_cast(Ty)) + return VT->getNumElements(); + return Ty->getStructNumElements(); +} //===----------------------------------------------------------------------===// // UndefValue Implementation @@ -797,7 +805,14 @@ UndefValue *UndefValue::getElementValue(unsigned Idx) const { return getStructElement(Idx); } - +unsigned UndefValue::getNumElements() const { + const Type *Ty = getType(); + if (const auto *AT = dyn_cast(Ty)) + return AT->getNumElements(); + if (const auto *VT = dyn_cast(Ty)) + return VT->getNumElements(); + return Ty->getStructNumElements(); +} //===----------------------------------------------------------------------===// // ConstantXXX Classes diff --git a/test/Transforms/InstSimplify/load.ll b/test/Transforms/InstSimplify/load.ll new file mode 100644 index 00000000000..92953cd0ebf --- /dev/null +++ b/test/Transforms/InstSimplify/load.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +@zeroinit = constant {} zeroinitializer +@undef = constant {} undef + +define i32 @crash_on_zeroinit() { +; CHECK-LABEL: @crash_on_zeroinit +; CHECK: ret i32 0 + %load = load i32* bitcast ({}* @zeroinit to i32*) + ret i32 %load +} + +define i32 @crash_on_undef() { +; CHECK-LABEL: @crash_on_undef +; CHECK: ret i32 undef + %load = load i32* bitcast ({}* @undef to i32*) + ret i32 %load +} +