aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-06-05 07:58:54 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-06-05 07:58:54 +0000
commitfdf4986c4c75514df428ed71d5942252f18e129b (patch)
tree634ddc308a89fe6490528781d2f88c296c75a6a0
parent5a77973d9bc2c9cdbdb7860dcf3ac795abe258ec (diff)
ABI handling: Fix nasty thinko where IRgen could generate an out-of-bounds read
when generating a coercion for ABI handling purposes. - This may only manifest itself when building at -O0, but the practical effect is that other arguments may get clobbered. - <rdar://problem/6930451> [irgen] ABI coercion clobbers other arguments git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72932 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGCall.cpp15
-rw-r--r--test/CodeGen/x86_64-arguments.c6
2 files changed, 14 insertions, 7 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 954ac53068..248619fc2d 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1638,13 +1638,7 @@ static void CreateCoercedStore(llvm::Value *Src,
uint64_t DstSize = CGF.CGM.getTargetData().getTypeAllocSize(DstTy);
// If store is legal, just bitcast the src pointer.
- if (SrcSize >= DstSize) {
- // Generally SrcSize is never greater than DstSize, since this means we are
- // losing bits. However, this can happen in cases where the structure has
- // additional padding, for example due to a user specified alignment.
- //
- // FIXME: Assert that we aren't truncating non-padding bits when have access
- // to that information.
+ if (SrcSize <= DstSize) {
llvm::Value *Casted =
CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
// FIXME: Use better alignment / avoid requiring aligned store.
@@ -1652,6 +1646,13 @@ static void CreateCoercedStore(llvm::Value *Src,
} else {
// Otherwise do coercion through memory. This is stupid, but
// simple.
+
+ // Generally SrcSize is never greater than DstSize, since this means we are
+ // losing bits. However, this can happen in cases where the structure has
+ // additional padding, for example due to a user specified alignment.
+ //
+ // FIXME: Assert that we aren't truncating non-padding bits when have access
+ // to that information.
llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy);
CGF.Builder.CreateStore(Src, Tmp);
llvm::Value *Casted =
diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c
index 6f7ec82872..0b68afdb4e 100644
--- a/test/CodeGen/x86_64-arguments.c
+++ b/test/CodeGen/x86_64-arguments.c
@@ -82,4 +82,10 @@ void f16(float a, float b, float c, float d, float e, float f, float g, float h,
void f17(float a, float b, float c, float d, float e, float f, float g, float h,
long double X) {}
+// Check for valid coercion.
+// RUN: grep '.1 = bitcast i64. .tmp to .struct.f18_s0.' %t &&
+// RUN: grep '.2 = load .struct.f18_s0. .1, align 1' %t &&
+// RUN: grep 'store .struct.f18_s0 .2, .struct.f18_s0. .f18_arg1' %t &&
+void f18(int a, struct f18_s0 { int f0; } f18_arg1) {}
+
// RUN: true