Fix out-of-bounds write in RTL function reader (PR bootstrap/79952)
authorDavid Malcolm <dmalcolm@redhat.com>
Fri, 10 Mar 2017 18:39:52 +0000 (18:39 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Fri, 10 Mar 2017 18:39:52 +0000 (18:39 +0000)
gcc/ChangeLog:
PR bootstrap/79952
* read-rtl-function.c (function_reader::read_rtx_operand): Update
x with result of extra_parsing_for_operand_code_0.
(function_reader::extra_parsing_for_operand_code_0): Convert
return type from void to rtx, returning x.  When reading
SYMBOL_REF with SYMBOL_FLAG_HAS_BLOCK_INFO, reallocate x to the
larger size containing struct block_symbol.

From-SVN: r246044

gcc/ChangeLog
gcc/read-rtl-function.c

index 518178a..25737a3 100644 (file)
@@ -1,3 +1,13 @@
+2017-03-10  David Malcolm  <dmalcolm@redhat.com>
+
+       PR bootstrap/79952
+       * read-rtl-function.c (function_reader::read_rtx_operand): Update
+       x with result of extra_parsing_for_operand_code_0.
+       (function_reader::extra_parsing_for_operand_code_0): Convert
+       return type from void to rtx, returning x.  When reading
+       SYMBOL_REF with SYMBOL_FLAG_HAS_BLOCK_INFO, reallocate x to the
+       larger size containing struct block_symbol.
+
 2017-03-10  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * config/rs6000/rs6000.c (rs6000_option_override_internal): Disallow
index 8552cd2..c502797 100644 (file)
@@ -103,7 +103,7 @@ class function_reader : public rtx_reader
   void read_rtx_operand_u (rtx x, int idx);
   void read_rtx_operand_i_or_n (rtx x, int idx, char format_char);
   rtx read_rtx_operand_r (rtx x);
-  void extra_parsing_for_operand_code_0 (rtx x, int idx);
+  rtx extra_parsing_for_operand_code_0 (rtx x, int idx);
 
   void add_fixup_insn_uid (file_location loc, rtx insn, int operand_idx,
                           int insn_uid);
@@ -923,7 +923,7 @@ function_reader::read_rtx_operand (rtx x, int idx)
   switch (format_char)
     {
     case '0':
-      extra_parsing_for_operand_code_0 (x, idx);
+      x = extra_parsing_for_operand_code_0 (x, idx);
       break;
 
     case 'w':
@@ -1116,9 +1116,10 @@ function_reader::read_rtx_operand_r (rtx x)
 }
 
 /* Additional parsing for format code '0' in dumps, handling a variety
-   of special-cases in print_rtx, when parsing operand IDX of X.  */
+   of special-cases in print_rtx, when parsing operand IDX of X.
+   Return X, or possibly a reallocated copy of X.  */
 
-void
+rtx
 function_reader::extra_parsing_for_operand_code_0 (rtx x, int idx)
 {
   RTX_CODE code = GET_CODE (x);
@@ -1137,9 +1138,26 @@ function_reader::extra_parsing_for_operand_code_0 (rtx x, int idx)
          read_name (&name);
          SYMBOL_REF_FLAGS (x) = strtol (name.string, NULL, 16);
 
-         /* We can't reconstruct SYMBOL_REF_BLOCK; set it to NULL.  */
+         /* The standard RTX_CODE_SIZE (SYMBOL_REF) used when allocating
+            x doesn't have space for the block_symbol information, so
+            we must reallocate it if this flag is set.  */
          if (SYMBOL_REF_HAS_BLOCK_INFO_P (x))
-           SYMBOL_REF_BLOCK (x) = NULL;
+           {
+             /* Emulate the allocation normally done by
+                varasm.c:create_block_symbol.  */
+             unsigned int size = RTX_HDR_SIZE + sizeof (struct block_symbol);
+             rtx new_x = (rtx) ggc_internal_alloc (size);
+
+             /* Copy data over from the smaller SYMBOL_REF.  */
+             memcpy (new_x, x, RTX_CODE_SIZE (SYMBOL_REF));
+             x = new_x;
+
+             /* We can't reconstruct SYMBOL_REF_BLOCK; set it to NULL.  */
+             SYMBOL_REF_BLOCK (x) = NULL;
+
+             /* Zero the offset.  */
+             SYMBOL_REF_BLOCK_OFFSET (x) = 0;
+           }
 
          require_char (']');
        }
@@ -1185,6 +1203,8 @@ function_reader::extra_parsing_for_operand_code_0 (rtx x, int idx)
       else
        unread_char (c);
     }
+
+  return x;
 }
 
 /* Implementation of rtx_reader::handle_any_trailing_information.