From 9816f509db4966fcb90ed3baab72cc6cd901f06c Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 4 Jun 2021 10:49:06 -0600 Subject: [PATCH] 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. --- gcc/gimple-fold.c | 30 ++++++++-------- .../gcc.dg/tree-ssa/builtin-snprintf-11.c | 32 +++++++++++++++++ .../gcc.dg/tree-ssa/builtin-snprintf-12.c | 36 +++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-28.c | 30 ++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-29.c | 40 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/uninit-pr100732.c | 21 ++++++++++++ gcc/tree-ssa-uninit.c | 3 ++ 7 files changed, 176 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-11.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-12.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-28.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-29.c create mode 100644 gcc/testsuite/gcc.dg/uninit-pr100732.c diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index eaf0fb7..1c0e930 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -3514,10 +3514,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 @@ -3525,25 +3521,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; @@ -3584,16 +3583,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)) { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-11.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-11.c new file mode 100644 index 0000000..73117c4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-11.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-12.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-12.c new file mode 100644 index 0000000..9e26356 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-12.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-28.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-28.c new file mode 100644 index 0000000..c1d0083 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-28.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-29.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-29.c new file mode 100644 index 0000000..d0f7db2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-29.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/uninit-pr100732.c b/gcc/testsuite/gcc.dg/uninit-pr100732.c new file mode 100644 index 0000000..9c847ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-pr100732.c @@ -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" } +} diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index dcfdec9..7c002f8 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -541,6 +541,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); -- 2.7.4