This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix out-of-bounds write in RTL function reader (PR bootstrap/79952)


PR bootstrap/79952 identifies a crash that can occur when running
-fself-test.

The root cause is an out-of-bounds memory write in the RTL dump
reader when handling SYMBOL_REFs with SYMBOL_FLAG_HAS_BLOCK_INFO set.

Such SYMBOL_REFs are normally created by varasm.c:create_block_symbol,
which has:

  /* Create the extended SYMBOL_REF.  */
  size = RTX_HDR_SIZE + sizeof (struct block_symbol);

A normal SYMBOL_REF has the RTX_HDR_SIZE plus two rtunion
  on an x86_64 host this is: 8 + (2 * 8) = 24 bytes,

whereas a SYMBOL_REF with SYMBOL_REF_HAS_BLOCK_INFO_P () has
RTX_HDR_SIZE + sizeof (struct block_symbol);
  on an x86_64 host this is: 8 + 32 = 40 bytes

So the reader allocates a 24-byte symbol_ref, whereas this line
in function_reader::extra_parsing_for_operand_code_0:

1142		    SYMBOL_REF_BLOCK (x) = NULL;

implicitly assumes we have a 40-byte allocation, and writes
zeros to whatever is in memory after the 24-byte allocation,
and chaos ensues.

The fix is to reallocate the SYMBOL_REF after parsing the flags
if the pertinent flag is set.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.

OK for trunk in stage 4?

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.
---
 gcc/read-rtl-function.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index 8552cd2..c5027971 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -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.
-- 
1.8.5.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]