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 various undefined behaviors in gcc found by bootstrap-ubsan


Hi!

Most of this probably doesn't need explanation, just the
expand_sdiv_pow2 change - shift_cost only tracks shift counts to
MAX_BITS_PER_WORD (but, for consistency between e.g. i?86 and x86_64 -m32
we'd better use BITS_PER_WORD instead as in most other expmed.c places),
when called with larger values it is out of bounds access.  I believe
for multiword accesses, even when we don't have costs for it, and masking
will be typically cheaper (e.g. for double word you need two word ANDs,
while for double word shift unless there is a specialized instruction
for double word shifts one needs either a library routine or 3 shifts and
IOR).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2014-07-02  Jakub Jelinek  <jakub@redhat.com>

	* gcov-io.c (gcov_read_words): Don't call memmove if excess is 0.
	* data-streamer-in.c (streamer_read_hwi): Shift UHWI 1 instead of
	HWI 1 and negate the unsigned value.
	* expmed.c (expand_sdiv_pow2): For modes wider than word always
	use AND instead of shift.
	* wide-int-print.cc (print_decs): Negate UHWI instead of HWI.
c-family/
	* c-ada-spec.c (dump_ada_nodes): Don't call qsort if 
	comments->count <= 1, as comments->entries might be NULL.

--- gcc/gcov-io.c.jj	2014-05-30 10:51:15.000000000 +0200
+++ gcc/gcov-io.c	2014-06-30 12:09:54.276063826 +0200
@@ -489,14 +489,15 @@ gcov_read_words (unsigned words)
   if (excess < words)
     {
       gcov_var.start += gcov_var.offset;
-#if IN_LIBGCOV
       if (excess)
 	{
+#if IN_LIBGCOV
 	  memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4);
-	}
 #else
-      memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, excess * 4);
+	  memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset,
+		   excess * 4);
 #endif
+	}
       gcov_var.offset = 0;
       gcov_var.length = excess;
 #if IN_LIBGCOV
--- gcc/data-streamer-in.c.jj	2014-01-03 11:40:29.000000000 +0100
+++ gcc/data-streamer-in.c	2014-06-30 11:59:52.000221301 +0200
@@ -174,7 +174,7 @@ streamer_read_hwi (struct lto_input_bloc
       if ((byte & 0x80) == 0)
 	{
 	  if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40))
-	    result |= - ((HOST_WIDE_INT)1 << shift);
+	    result |= - (HOST_WIDE_INT_1U << shift);
 
 	  return result;
 	}
--- gcc/expmed.c.jj	2014-06-27 09:03:01.000000000 +0200
+++ gcc/expmed.c	2014-06-30 11:46:00.947593030 +0200
@@ -3795,8 +3795,9 @@ expand_sdiv_pow2 (enum machine_mode mode
 
       temp = gen_reg_rtx (mode);
       temp = emit_store_flag (temp, LT, op0, const0_rtx, mode, 0, -1);
-      if (shift_cost (optimize_insn_for_speed_p (), mode, ushift)
-	  > COSTS_N_INSNS (1))
+      if (GET_MODE_BITSIZE (mode) >= BITS_PER_WORD
+	  || shift_cost (optimize_insn_for_speed_p (), mode, ushift)
+	     > COSTS_N_INSNS (1))
 	temp = expand_binop (mode, and_optab, temp, gen_int_mode (d - 1, mode),
 			     NULL_RTX, 0, OPTAB_LIB_WIDEN);
       else
--- gcc/c-family/c-ada-spec.c.jj	2014-05-11 22:20:59.000000000 +0200
+++ gcc/c-family/c-ada-spec.c	2014-06-30 12:05:06.931560475 +0200
@@ -636,8 +636,9 @@ dump_ada_nodes (pretty_printer *pp, cons
   comments = cpp_get_comments (parse_in);
 
   /* Sort the comments table by sloc.  */
-  qsort (comments->entries, comments->count, sizeof (cpp_comment),
-	 compare_comment);
+  if (comments->count > 1)
+    qsort (comments->entries, comments->count, sizeof (cpp_comment),
+	   compare_comment);
 
   /* Interleave comments and declarations in line number order.  */
   i = j = 0;
--- gcc/wide-int-print.cc.jj	2014-05-11 22:21:04.000000000 +0200
+++ gcc/wide-int-print.cc	2014-06-30 12:02:11.349485371 +0200
@@ -62,7 +62,8 @@ print_decs (const wide_int_ref &wi, char
       || (wi.get_len () == 1))
     {
       if (wi::neg_p (wi))
-      	sprintf (buf, "-" HOST_WIDE_INT_PRINT_UNSIGNED, -wi.to_shwi ());
+      	sprintf (buf, "-" HOST_WIDE_INT_PRINT_UNSIGNED,
+		 -(unsigned HOST_WIDE_INT) wi.to_shwi ());
       else
 	sprintf (buf, HOST_WIDE_INT_PRINT_DEC, wi.to_shwi ());
     }

	Jakub


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