From 2004617a8c2e67005230ebfcbdd1e4216b411bf1 Mon Sep 17 00:00:00 2001 From: Qing Zhao Date: Thu, 14 Dec 2017 17:37:20 +0000 Subject: [PATCH] Patch for middle-end/PR79538 missing -Wformat-overflow with %s and non-member array arguments MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit -Wformat-overflow uses the routine "get_range_strlen" to decide the maximum string length, however, currently "get_range_strlen" misses the handling of non-member arrays. Adding the handling of non-member array resolves the issue. Adding test case pr79538.c into gcc.dg. During gcc bootstrap, 2 source files (c-family/c-cppbuiltin.c, fortran/class.c) were detected new warnings by -Wformat-overflow due to the new handling of non-member array in "get_range_strlen". in order to avoid these new warnings and continue with bootstrap, updating these 2 files to avoid the warnings. in c-family/c-cppbuiltin.c, the warning is following: ../../latest_gcc_2/gcc/c-family/c-cppbuiltin.c:1627:15: note: ‘sprintf’ output 2 or more bytes (assuming 257) into a destination of size 256 sprintf (buf1, "%s=%s", macro, buf2); ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~ in the above, buf1 and buf2 are declared as: char buf1[256], buf2[256]; i.e, buf1 and buf2 have same size. adjusting the size of buf1 and buf2 resolves the warning. fortran/class.c has the similar issue as above. Instead of adjusting size of the buffers, replacing sprintf with xasprintf is a better solution for these cases. From-SVN: r255654 --- gcc/ChangeLog | 6 +++++ gcc/c-family/ChangeLog | 7 +++++ gcc/c-family/c-cppbuiltin.c | 10 +++---- gcc/fortran/ChangeLog | 9 +++++++ gcc/fortran/class.c | 49 +++++++++++++++++++--------------- gcc/gimple-fold.c | 13 +++++++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/pr79538.c | 22 +++++++++++++++ 8 files changed, 95 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr79538.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7473263a62c..0192d672823 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-12-14 Qing Zhao + + PR middle_end/79538 + * gimple-fold.c (get_range_strlen): Add the handling of non-member + array. + 2017-12-14 David Malcolm PR tree-optimization/83312 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 6c31dbef45e..abe53019aa6 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2017-12-14 Qing Zhao + + PR middle_end/79538 + * c-cppbuiltin.c (builtin_define_with_hex_fp_value): + Adjust the size of buf1 and buf2, add a new buf to avoid + format-overflow warning. + 2017-12-12 Alexandre Oliva * c-semantics.c (pop_stmt_list): Move begin stmt marker into diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index 2ac9616b72f..9e33aed9b8b 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -1613,7 +1613,7 @@ builtin_define_with_hex_fp_value (const char *macro, const char *fp_cast) { REAL_VALUE_TYPE real; - char dec_str[64], buf1[256], buf2[256]; + char dec_str[64], buf[256], buf1[128], buf2[64]; /* This is very expensive, so if possible expand them lazily. */ if (lazy_hex_fp_value_count < 12 @@ -1656,11 +1656,11 @@ builtin_define_with_hex_fp_value (const char *macro, /* Assemble the macro in the following fashion macro = fp_cast [dec_str fp_suffix] */ - sprintf (buf1, "%s%s", dec_str, fp_suffix); - sprintf (buf2, fp_cast, buf1); - sprintf (buf1, "%s=%s", macro, buf2); + sprintf (buf2, "%s%s", dec_str, fp_suffix); + sprintf (buf1, fp_cast, buf2); + sprintf (buf, "%s=%s", macro, buf1); - cpp_define (parse_in, buf1); + cpp_define (parse_in, buf); } /* Return a string constant for the suffix for a value of type TYPE diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index f3f9d9c9300..cc8b11879f3 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2017-12-14 Qing Zhao + + PR middle_end/79538 + * class.c (gfc_build_class_symbol): Replace call to + sprintf with xasprintf to avoid format-overflow warning. + (generate_finalization_wrapper): Likewise. + (gfc_find_derived_vtab): Likewise. + (find_intrinsic_vtab): Likewise. + 2017-12-12 Thomas Koenig * intrinsic.texi (MAXLOC): Remove double description diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c index ebbd41b0d96..a08fb8d81c5 100644 --- a/gcc/fortran/class.c +++ b/gcc/fortran/class.c @@ -602,7 +602,8 @@ bool gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr, gfc_array_spec **as) { - char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1]; + char tname[GFC_MAX_SYMBOL_LEN+1]; + char *name; gfc_symbol *fclass; gfc_symbol *vtab; gfc_component *c; @@ -633,17 +634,17 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr, rank = !(*as) || (*as)->rank == -1 ? GFC_MAX_DIMENSIONS : (*as)->rank; get_unique_hashed_string (tname, ts->u.derived); if ((*as) && attr->allocatable) - sprintf (name, "__class_%s_%d_%da", tname, rank, (*as)->corank); + name = xasprintf ("__class_%s_%d_%da", tname, rank, (*as)->corank); else if ((*as) && attr->pointer) - sprintf (name, "__class_%s_%d_%dp", tname, rank, (*as)->corank); + name = xasprintf ("__class_%s_%d_%dp", tname, rank, (*as)->corank); else if ((*as)) - sprintf (name, "__class_%s_%d_%dt", tname, rank, (*as)->corank); + name = xasprintf ("__class_%s_%d_%dt", tname, rank, (*as)->corank); else if (attr->pointer) - sprintf (name, "__class_%s_p", tname); + name = xasprintf ("__class_%s_p", tname); else if (attr->allocatable) - sprintf (name, "__class_%s_a", tname); + name = xasprintf ("__class_%s_a", tname); else - sprintf (name, "__class_%s_t", tname); + name = xasprintf ("__class_%s_t", tname); if (ts->u.derived->attr.unlimited_polymorphic) { @@ -738,6 +739,7 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr, ts->u.derived = fclass; attr->allocatable = attr->pointer = attr->dimension = attr->codimension = 0; (*as) = NULL; + free (name); return true; } @@ -1527,7 +1529,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns, gfc_component *comp; gfc_namespace *sub_ns; gfc_code *last_code, *block; - char name[GFC_MAX_SYMBOL_LEN+1]; + char *name; bool finalizable_comp = false; bool expr_null_wrapper = false; gfc_expr *ancestor_wrapper = NULL, *rank; @@ -1606,7 +1608,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns, sub_ns->resolved = 1; /* Set up the procedure symbol. */ - sprintf (name, "__final_%s", tname); + name = xasprintf ("__final_%s", tname); gfc_get_symbol (name, sub_ns, &final); sub_ns->proc_name = final; final->attr.flavor = FL_PROCEDURE; @@ -2172,6 +2174,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns, gfc_free_expr (rank); vtab_final->initializer = gfc_lval_expr_from_sym (final); vtab_final->ts.interface = final; + free (name); } @@ -2239,10 +2242,11 @@ gfc_find_derived_vtab (gfc_symbol *derived) if (ns) { - char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1]; + char tname[GFC_MAX_SYMBOL_LEN+1]; + char *name; get_unique_hashed_string (tname, derived); - sprintf (name, "__vtab_%s", tname); + name = xasprintf ("__vtab_%s", tname); /* Look for the vtab symbol in various namespaces. */ if (gsym && gsym->ns) @@ -2270,7 +2274,7 @@ gfc_find_derived_vtab (gfc_symbol *derived) vtab->attr.vtab = 1; vtab->attr.access = ACCESS_PUBLIC; gfc_set_sym_referenced (vtab); - sprintf (name, "__vtype_%s", tname); + name = xasprintf ("__vtype_%s", tname); gfc_find_symbol (name, ns, 0, &vtype); if (vtype == NULL) @@ -2373,7 +2377,7 @@ gfc_find_derived_vtab (gfc_symbol *derived) else { /* Construct default initialization variable. */ - sprintf (name, "__def_init_%s", tname); + name = xasprintf ("__def_init_%s", tname); gfc_get_symbol (name, ns, &def_init); def_init->attr.target = 1; def_init->attr.artificial = 1; @@ -2406,7 +2410,7 @@ gfc_find_derived_vtab (gfc_symbol *derived) ns->contained = sub_ns; sub_ns->resolved = 1; /* Set up procedure symbol. */ - sprintf (name, "__copy_%s", tname); + name = xasprintf ("__copy_%s", tname); gfc_get_symbol (name, sub_ns, ©); sub_ns->proc_name = copy; copy->attr.flavor = FL_PROCEDURE; @@ -2483,7 +2487,7 @@ gfc_find_derived_vtab (gfc_symbol *derived) ns->contained = sub_ns; sub_ns->resolved = 1; /* Set up procedure symbol. */ - sprintf (name, "__deallocate_%s", tname); + name = xasprintf ("__deallocate_%s", tname); gfc_get_symbol (name, sub_ns, &dealloc); sub_ns->proc_name = dealloc; dealloc->attr.flavor = FL_PROCEDURE; @@ -2532,6 +2536,7 @@ have_vtype: vtab->ts.u.derived = vtype; vtab->value = gfc_default_initializer (&vtab->ts); } + free (name); } found_sym = vtab; @@ -2623,13 +2628,14 @@ find_intrinsic_vtab (gfc_typespec *ts) if (ns) { - char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1]; - + char tname[GFC_MAX_SYMBOL_LEN+1]; + char *name; + /* Encode all types as TYPENAME_KIND_ including especially character arrays, whose length is now consistently stored in the _len component of the class-variable. */ sprintf (tname, "%s_%d_", gfc_basic_typename (ts->type), ts->kind); - sprintf (name, "__vtab_%s", tname); + name = xasprintf ("__vtab_%s", tname); /* Look for the vtab symbol in the top-level namespace only. */ gfc_find_symbol (name, ns, 0, &vtab); @@ -2646,7 +2652,7 @@ find_intrinsic_vtab (gfc_typespec *ts) vtab->attr.vtab = 1; vtab->attr.access = ACCESS_PUBLIC; gfc_set_sym_referenced (vtab); - sprintf (name, "__vtype_%s", tname); + name = xasprintf ("__vtype_%s", tname); gfc_find_symbol (name, ns, 0, &vtype); if (vtype == NULL) @@ -2722,12 +2728,12 @@ find_intrinsic_vtab (gfc_typespec *ts) c->tb->ppc = 1; if (ts->type != BT_CHARACTER) - sprintf (name, "__copy_%s", tname); + name = xasprintf ("__copy_%s", tname); else { /* __copy is always the same for characters. Check to see if copy function already exists. */ - sprintf (name, "__copy_character_%d", ts->kind); + name = xasprintf ("__copy_character_%d", ts->kind); contained = ns->contained; for (; contained; contained = contained->sibling) if (contained->proc_name @@ -2796,6 +2802,7 @@ find_intrinsic_vtab (gfc_typespec *ts) vtab->ts.u.derived = vtype; vtab->value = gfc_default_initializer (&vtab->ts); } + free (name); } found_sym = vtab; diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 24f7e76228b..403fbb8c940 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1340,6 +1340,19 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type, the array could have zero length. */ *minlen = ssize_int (0); } + + if (VAR_P (arg) + && TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE) + { + val = TYPE_SIZE_UNIT (TREE_TYPE (arg)); + if (!val || TREE_CODE (val) != INTEGER_CST || integer_zerop (val)) + return false; + val = wide_int_to_tree (TREE_TYPE (val), + wi::sub(wi::to_wide (val), 1)); + /* Set the minimum size to zero since the string in + the array could have zero length. */ + *minlen = ssize_int (0); + } } if (!val) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 81d28f1adb6..6cedc130701 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-12-14 Qing Zhao + + PR middle_end/79538 + * gcc.dg/pr79538.c: New test. + 2017-12-14 David Malcolm PR tree-optimization/83312 diff --git a/gcc/testsuite/gcc.dg/pr79538.c b/gcc/testsuite/gcc.dg/pr79538.c new file mode 100644 index 00000000000..6cdab45128a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr79538.c @@ -0,0 +1,22 @@ +/* PR middle-end/79538 - missing -Wformat-overflow with %s and non-member array arguments + { dg-do compile } + { dg-options "-O2 -Wformat-overflow" } */ + +char a3[3]; +char a4[4]; +char d[3]; + +void g (int i) +{ + const char *s = i < 0 ? a3 : a4; + __builtin_sprintf (d, "%s", s); /* { dg-warning ".__builtin_sprintf. may write a terminating nul past the end of the destination" } */ + return; +} + +void f () +{ + char des[3]; + char src[] = "abcd"; + __builtin_sprintf (des, "%s", src); /* { dg-warning "directive writing up to 4 bytes into a region of size 3" } */ + return; +} -- 2.30.2