This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix various undefined behaviors in gcc found by bootstrap-ubsan
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 2 Jul 2014 10:14:48 +0200
- Subject: [PATCH] Fix various undefined behaviors in gcc found by bootstrap-ubsan
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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