summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-27 09:19:47 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-27 09:19:47 +0000
commit50b6efd6cf220963dddfafc1c3fd6d4f531c2461 (patch)
tree464de63e1f69235378526adc3e4ce569d38fb10f
parentbfb02355a080f309ad04fe9d5fa4310c3cfe8ef9 (diff)
downloadgcc-50b6efd6cf220963dddfafc1c3fd6d4f531c2461.tar.gz
PR middle-end/59138
* expr.c (emit_group_store): Don't write past the end of the structure. (store_bit_field): Fix formatting. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_8-branch@205437 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/expr.c26
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20131127-1.c34
4 files changed, 61 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d381a5e3a97..e443649dcfd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2013-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/59138
+ * expr.c (emit_group_store): Don't write past the end of the structure.
+ (store_bit_field): Fix formatting.
+
2013-11-24 Sebastian Huber <sebastian.huber@embedded-brains.de>
Backport from mainline
diff --git a/gcc/expr.c b/gcc/expr.c
index 785747be8d0..628a6d9abd9 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -1994,12 +1994,14 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
enum machine_mode mode = GET_MODE (tmps[i]);
unsigned int bytelen = GET_MODE_SIZE (mode);
- unsigned int adj_bytelen = bytelen;
+ unsigned int adj_bytelen;
rtx dest = dst;
/* Handle trailing fragments that run over the size of the struct. */
if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
adj_bytelen = ssize - bytepos;
+ else
+ adj_bytelen = bytelen;
if (GET_CODE (dst) == CONCAT)
{
@@ -2040,6 +2042,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
}
}
+ /* Handle trailing fragments that run over the size of the struct. */
if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
{
/* store_bit_field always takes its value from the lsb.
@@ -2057,16 +2060,22 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
tmps[i] = expand_shift (RSHIFT_EXPR, mode, tmps[i],
shift, tmps[i], 0);
}
- bytelen = adj_bytelen;
+
+ /* Make sure not to write past the end of the struct. */
+ store_bit_field (dest,
+ adj_bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
+ bytepos * BITS_PER_UNIT, ssize * BITS_PER_UNIT,
+ VOIDmode, tmps[i]);
}
/* Optimize the access just a bit. */
- if (MEM_P (dest)
- && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest))
- || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode))
- && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
- && bytelen == GET_MODE_SIZE (mode))
+ else if (MEM_P (dest)
+ && (!SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest))
+ || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode))
+ && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
+ && bytelen == GET_MODE_SIZE (mode))
emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]);
+
else
store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
0, 0, mode, tmps[i]);
@@ -4668,8 +4677,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
expand_insn (icode, 2, ops);
}
else
- store_bit_field (mem, GET_MODE_BITSIZE (mode),
- 0, 0, 0, mode, reg);
+ store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg);
return;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6c32a80a312..023a1c50481 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2013-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/execute/20131127-1.c: New test.
+
2013-11-25 Vidya Praveen <vidyapraveen@arm.com>
Backport from mainline
diff --git a/gcc/testsuite/gcc.c-torture/execute/20131127-1.c b/gcc/testsuite/gcc.c-torture/execute/20131127-1.c
new file mode 100644
index 00000000000..8ec49657741
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20131127-1.c
@@ -0,0 +1,34 @@
+/* PR middle-end/59138 */
+/* Testcase by John Regehr <regehr@cs.utah.edu> */
+
+extern void abort (void);
+
+#pragma pack(1)
+
+struct S0 {
+ int f0;
+ int f1;
+ int f2;
+ short f3;
+};
+
+short a = 1;
+
+struct S0 b = { 1 }, c, d, e;
+
+struct S0 fn1() { return c; }
+
+void fn2 (void)
+{
+ b = fn1 ();
+ a = 0;
+ d = e;
+}
+
+int main (void)
+{
+ fn2 ();
+ if (a != 0)
+ abort ();
+ return 0;
+}