]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/59138 (possible packed struct miscompile)
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 27 Nov 2013 09:17:23 +0000 (09:17 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 27 Nov 2013 09:17:23 +0000 (09:17 +0000)
PR middle-end/59138
* expr.c (emit_group_store): Don't write past the end of the structure.
(store_bit_field): Fix formatting.

From-SVN: r205436

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20131127-1.c [new file with mode: 0644]

index 43383ffa098f3b8c4e9b841925ebfd22405381ec..05a31a8e42a86b4a87ab0528b69694d0b167ecc7 100644 (file)
@@ -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-27  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/59288
index dc379dc1094bd59269a4a32dfb8360c3d061ed38..8f8b5272846c18cb30ce2b05b0e1b034e95c0f4d 100644 (file)
@@ -2061,12 +2061,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)
        {
@@ -2107,6 +2109,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.
@@ -2124,16 +2127,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]);
@@ -4776,8 +4785,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;
     }
 
index 2edd80b94d75162f35922c0490cb1e1dafebfd90..74273b21e48b096e914061ea8a58fcbf6540a530 100644 (file)
@@ -1,3 +1,7 @@
+2013-11-27  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.c-torture/execute/20131127-1.c: New test.
+
 2013-11-27  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/59288
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 (file)
index 0000000..8ec4965
--- /dev/null
@@ -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;
+}