PR middle-end/100732 - ICE on sprintf %s with integer argument
gcc/ChangeLog:
PR middle-end/100732
* gimple-fold.c (gimple_fold_builtin_sprintf): Avoid folding calls
with either source or destination argument of invalid type.
* tree-ssa-uninit.c (maybe_warn_pass_by_reference): Avoid checking
calls with arguments of invalid type.
gcc/testsuite/ChangeLog:
PR middle-end/100732
* gcc.dg/tree-ssa/builtin-snprintf-11.c: New test.
* gcc.dg/tree-ssa/builtin-snprintf-12.c: New test.
* gcc.dg/tree-ssa/builtin-sprintf-28.c: New test.
* gcc.dg/tree-ssa/builtin-sprintf-29.c: New test.
* gcc.dg/uninit-pr100732.c: New test.
@@ -3509,10 +3509,6 @@ bool
gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
{
gimple *stmt = gsi_stmt (*gsi);
- tree dest = gimple_call_arg (stmt, 0);
- tree fmt = gimple_call_arg (stmt, 1);
- tree orig = NULL_TREE;
- const char *fmt_str = NULL;
/* Verify the required arguments in the original call. We deal with two
types of sprintf() calls: 'sprintf (str, fmt)' and
@@ -3520,25 +3516,28 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
if (gimple_call_num_args (stmt) > 3)
return false;
+ tree orig = NULL_TREE;
if (gimple_call_num_args (stmt) == 3)
orig = gimple_call_arg (stmt, 2);
/* Check whether the format is a literal string constant. */
- fmt_str = c_getstr (fmt);
+ tree fmt = gimple_call_arg (stmt, 1);
+ const char *fmt_str = c_getstr (fmt);
if (fmt_str == NULL)
return false;
+ tree dest = gimple_call_arg (stmt, 0);
+
if (!init_target_chars ())
return false;
+ tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
+ if (!fn)
+ return false;
+
/* If the format doesn't contain % args or %%, use strcpy. */
if (strchr (fmt_str, target_percent) == NULL)
{
- tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
-
- if (!fn)
- return false;
-
/* Don't optimize sprintf (buf, "abc", ptr++). */
if (orig)
return false;
@@ -3579,16 +3578,15 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
/* If the format is "%s", use strcpy if the result isn't used. */
else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
{
- tree fn;
- fn = builtin_decl_implicit (BUILT_IN_STRCPY);
-
- if (!fn)
- return false;
-
/* Don't crash on sprintf (str1, "%s"). */
if (!orig)
return false;
+ /* Don't fold calls with source arguments of invalid (nonpointer)
+ types. */
+ if (!POINTER_TYPE_P (TREE_TYPE (orig)))
+ return false;
+
tree orig_len = NULL_TREE;
if (gimple_call_lhs (stmt))
{
new file mode 100644
@@ -0,0 +1,32 @@
+/* PR middle-end/100732 - ICE on sprintf %s with integer argument
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+char d[32];
+
+void gb (_Bool b)
+{
+ __builtin_snprintf (d, 32, "%s", b); // { dg-warning "\\\[-Wformat" }
+}
+
+void gi (int i)
+{
+ __builtin_snprintf (d, 32, "%s", i); // { dg-warning "\\\[-Wformat" }
+}
+
+void gd (char *d, double x)
+{
+ __builtin_snprintf (d, 32, "%s", x); // { dg-warning "\\\[-Wformat" }
+}
+
+
+struct X { int i; };
+
+void gx (char *d, struct X x)
+{
+ __builtin_snprintf (d, 32, "%s", x); // { dg-warning "\\\[-Wformat" }
+}
+
+/* Also verify that the invalid sprintf call isn't folded to strcpy.
+ { dg-final { scan-tree-dump-times "snprintf" 4 "optimized" } }
+ { dg-final { scan-tree-dump-not "strcpy" "optimized" } } */
new file mode 100644
@@ -0,0 +1,36 @@
+/* PR middle-end/100732 - ICE on sprintf %s with integer argument
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+#define snprintf(d, n, f, ...) \
+ __builtin___snprintf_chk (d, n, 0, 32, f, __VA_ARGS__)
+
+int n;
+
+void gb (char *d, _Bool b)
+{
+ snprintf (d, n, "%s", b); // { dg-warning "\\\[-Wformat" }
+}
+
+void gi (char *d, int i)
+{
+ snprintf (d, n, "%s", i); // { dg-warning "\\\[-Wformat" }
+}
+
+void gd (char *d, double x)
+{
+ snprintf (d, n, "%s", x); // { dg-warning "\\\[-Wformat" }
+}
+
+
+struct X { int i; };
+
+void gx (char *d, struct X x)
+{
+ snprintf (d, n, "%s", x); // { dg-warning "\\\[-Wformat" }
+}
+
+
+/* Also verify that the invalid sprintf call isn't folded to strcpy.
+ { dg-final { scan-tree-dump-times "snprintf_chk" 4 "optimized" } }
+ { dg-final { scan-tree-dump-not "strcpy" "optimized" } } */
new file mode 100644
@@ -0,0 +1,30 @@
+/* PR middle-end/100732 - ICE on sprintf %s with integer argument
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+void gb (char *d, _Bool b)
+{
+ __builtin_sprintf (d, "%s", b); // { dg-warning "\\\[-Wformat" }
+}
+
+void gi (char *d, int i)
+{
+ __builtin_sprintf (d, "%s", i); // { dg-warning "\\\[-Wformat" }
+}
+
+void gd (char *d, double x)
+{
+ __builtin_sprintf (d, "%s", x); // { dg-warning "\\\[-Wformat" }
+}
+
+
+struct X { int i; };
+
+void gx (char *d, struct X x)
+{
+ __builtin_sprintf (d, "%s", x); // { dg-warning "\\\[-Wformat" }
+}
+
+/* Also verify that the invalid sprintf call isn't folded to strcpy.
+ { dg-final { scan-tree-dump-times "sprintf" 4 "optimized" } }
+ { dg-final { scan-tree-dump-not "strcpy" "optimized" } } */
new file mode 100644
@@ -0,0 +1,40 @@
+/* PR middle-end/100732 - ICE on sprintf %s with integer argument
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+#define sprintf(d, f, ...) \
+ __builtin___sprintf_chk (d, 0, 32, f, __VA_ARGS__)
+
+
+void fi (int i, const char *s)
+{
+ sprintf (i, "%s", s); // { dg-warning "\\\[-Wint-conversion" }
+}
+
+void gb (char *d, _Bool b)
+{
+ sprintf (d, "%s", b); // { dg-warning "\\\[-Wformat" }
+}
+
+void gi (char *d, int i)
+{
+ sprintf (d, "%s", i); // { dg-warning "\\\[-Wformat" }
+}
+
+void gd (char *d, double x)
+{
+ sprintf (d, "%s", x); // { dg-warning "\\\[-Wformat" }
+}
+
+
+struct X { int i; };
+
+void gx (char *d, struct X x)
+{
+ sprintf (d, "%s", x); // { dg-warning "\\\[-Wformat" }
+}
+
+
+/* Also verify that the invalid sprintf call isn't folded to strcpy.
+ { dg-final { scan-tree-dump-times "sprintf_chk" 5 "optimized" } }
+ { dg-final { scan-tree-dump-not "strcpy" "optimized" } } */
new file mode 100644
@@ -0,0 +1,21 @@
+/* PR middle-end/100732 - ICE on sprintf %s with integer argument
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+void nowarn_s_i (char *d, int i)
+{
+ __builtin_sprintf (d, "%s", i); // { dg-warning "\\\[-Wformat" }
+}
+
+void warn_s_i (char *d)
+{
+ int i;
+ __builtin_sprintf (d, "%s", i); // { dg-warning "\\\[-Wformat" }
+ // { dg-warning "\\\[-Wuninitialized" "" { target *-*-* } .-1 }
+}
+
+void warn_i_i (char *d)
+{
+ int i;
+ __builtin_sprintf (d, "%i", i); // { dg-warning "\\\[-Wuninitialized" }
+}
@@ -540,6 +540,9 @@ maybe_warn_pass_by_reference (gcall *stmt, wlimits &wlims)
continue;
tree arg = gimple_call_arg (stmt, argno - 1);
+ if (!POINTER_TYPE_P (TREE_TYPE (arg)))
+ /* Avoid actual arguments with invalid types. */
+ continue;
ao_ref ref;
ao_ref_init_from_ptr_and_size (&ref, arg, access_size);