diff mbox series

avoid more ICE due to bad built-in calls declared without a prototype (PR 89911, 89957)

Message ID 7f9f933f-58f4-f6bd-335f-829ef4ad6507@gmail.com
State New
Headers show
Series avoid more ICE due to bad built-in calls declared without a prototype (PR 89911, 89957) | expand

Commit Message

Martin Sebor April 4, 2019, 9:42 p.m. UTC
Attached is yet another patch to avoid ICE due to middle-end
assumptions about the sanity of calls to built-ins, this time
for strnlen.  It fixes two unsafe assumptions:

1) The -Wstringop-overflow checker for unterminated constant char
    arrays assumes that strnlen is called with exactly two arguments.
    When the function is declared without a prototype and called with
    no arguments the code aborts.  This is PR 89911 (P1).

2) The wide_int min/max values of get_range_info() called on
    the strnlen bound have the same precision as PTRDIFF_MAX.
    That's not so when strnlen is declared without a prototype
    and called with an int128_t argument in some range.  Rather
    than handling this case, wi::ltu_p() helpfully aborts instead.
    This is PR 89957 that I exposed while testing the fix above.

The trivial patch avoids both of these assumptions.  It's been
tested on x86_64-linux.  Similar to the patch for PR 89934, I
will commit it later this week unless there are objections.

Martin

Patch for PR 89934 for reference:
   https://gcc.gnu.org/ml/gcc-patches/2019-04/msg00149.html

Comments

Jeff Law April 4, 2019, 9:55 p.m. UTC | #1
On 4/4/19 3:42 PM, Martin Sebor wrote:
> Attached is yet another patch to avoid ICE due to middle-end
> assumptions about the sanity of calls to built-ins, this time
> for strnlen.  It fixes two unsafe assumptions:
> 
> 1) The -Wstringop-overflow checker for unterminated constant char
>    arrays assumes that strnlen is called with exactly two arguments.
>    When the function is declared without a prototype and called with
>    no arguments the code aborts.  This is PR 89911 (P1).
> 
> 2) The wide_int min/max values of get_range_info() called on
>    the strnlen bound have the same precision as PTRDIFF_MAX.
>    That's not so when strnlen is declared without a prototype
>    and called with an int128_t argument in some range.  Rather
>    than handling this case, wi::ltu_p() helpfully aborts instead.
>    This is PR 89957 that I exposed while testing the fix above.
> 
> The trivial patch avoids both of these assumptions.  It's been
> tested on x86_64-linux.  Similar to the patch for PR 89934, I
> will commit it later this week unless there are objections.
> 
> Martin
> 
> Patch for PR 89934 for reference:
>   https://gcc.gnu.org/ml/gcc-patches/2019-04/msg00149.html
> 
> gcc-89911.diff
> 
> PR middle-end/89957 - ICE calling strnlen with an int128_t bound in a known range
> PR middle-end/89911 - [9 Regression] ICE in get_attr_nonstring_decl
> 
> gcc/ChangeLog:
> 
> 	PR middle-end/89957
> 	PR middle-end/89911
> 	* builtins.c (expand_builtin_strnlen): Make sure wi::ltu_p operands
> 	have the same precision since the function crashes otherwise.
> 	* calls.c (maybe_warn_nonstring_arg): Avoid assuming strnlen() call
> 	has non-zero arguments.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR middle-end/89957
> 	PR middle-end/89911
> 	* gcc.dg/Wstringop-overflow-13.c: New test.
OK
jeff
diff mbox series

Patch

PR middle-end/89957 - ICE calling strnlen with an int128_t bound in a known range
PR middle-end/89911 - [9 Regression] ICE in get_attr_nonstring_decl

gcc/ChangeLog:

	PR middle-end/89957
	PR middle-end/89911
	* builtins.c (expand_builtin_strnlen): Make sure wi::ltu_p operands
	have the same precision since the function crashes otherwise.
	* calls.c (maybe_warn_nonstring_arg): Avoid assuming strnlen() call
	has non-zero arguments.

gcc/testsuite/ChangeLog:

	PR middle-end/89957
	PR middle-end/89911
	* gcc.dg/Wstringop-overflow-13.c: New test.

Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 270149)
+++ gcc/builtins.c	(working copy)
@@ -3151,7 +3151,7 @@  expand_builtin_strnlen (tree exp, rtx target, mach
     return NULL_RTX;
 
   if (!TREE_NO_WARNING (exp)
-      && wi::ltu_p (wi::to_wide (maxobjsize), min)
+      && wi::ltu_p (wi::to_wide (maxobjsize, min.get_precision ()), min)
       && warning_at (loc, OPT_Wstringop_overflow_,
 		     "%K%qD specified bound [%wu, %wu] "
 		     "exceeds maximum object size %E",
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	(revision 270149)
+++ gcc/calls.c	(working copy)
@@ -1555,7 +1555,10 @@  maybe_warn_nonstring_arg (tree fndecl, tree exp)
   if (TREE_NO_WARNING (exp) || !warn_stringop_overflow)
     return;
 
+  /* Avoid clearly invalid calls (more checking done below).  */
   unsigned nargs = call_expr_nargs (exp);
+  if (!nargs)
+    return;
 
   /* The bound argument to a bounded string function like strncpy.  */
   tree bound = NULL_TREE;
Index: gcc/testsuite/gcc.dg/Wstringop-overflow-13.c
===================================================================
--- gcc/testsuite/gcc.dg/Wstringop-overflow-13.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/Wstringop-overflow-13.c	(working copy)
@@ -0,0 +1,40 @@ 
+/* PR middle-end/89957 - ICE calling strnlen with an int128_t bound
+   in a known range
+   PR middle-end/89911 - ICE on a call with no arguments to strnlen
+   declared with no prototype
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern size_t strnlen ();
+
+size_t f0 (void)
+{
+  return strnlen ();          /* { dg-warning "too few arguments to built-in function 'strnlen'" } */
+}
+
+size_t f1 (const char *s)
+{
+  return strnlen (s);         /* { dg-warning "too few arguments to built-in function 'strnlen'" } */
+}
+
+size_t f2 (const char *s)
+{
+  return strnlen (s, s);      /* { dg-warning "\\\[-Wint-conversion]" } */
+}
+
+#if __SIZEOF_INT128__ == 16
+
+size_t fi128 (const char *s, __int128_t n)
+{
+ if (n < 0)
+   n = 0;
+
+ /* PR middle-end/89957 */
+ return strnlen (s, n);       /* { dg-warning "\\\[-Wbuiltin-declaration-mismatch]" "int128" { target int128 } } */
+}
+
+#endif
+
+/* { dg-prune-output "\\\[-Wint-conversion]" } */