From: Martin Sebor Date: Tue, 16 Nov 2021 16:18:25 +0000 (-0700) Subject: Avoid assuming maximum string length is constant [PR102960]. X-Git-Tag: upstream/12.2.0~3387 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ba6e17e78db543b336c196b55fa6430e513f1941;p=platform%2Fupstream%2Fgcc.git Avoid assuming maximum string length is constant [PR102960]. Resolves: PR tree-optimization/102960 - ICE: in sign_mask, at wide-int.h:855 in GCC 10.3.0 gcc/ChangeLog: PR tree-optimization/102960 * gimple-fold.c (get_range_strlen): Take bitmap as an argument rather than a pointer to it. (get_range_strlen_tree): Same. Remove bitmap allocation. Use an auto_bitmap. (get_maxval_strlen): Use an auto_bitmap. * tree-ssa-strlen.c (get_range_strlen_dynamic): Factor out PHI handling... (get_range_strlen_phi): ...into this function. Avoid assuming maximum string length is constant (printf_strlen_execute): Dump pointer query cache contents when details are requisted. gcc/testsuite/ChangeLog: PR tree-optimization/102960 * gcc.dg/Wstringop-overflow-84.c: New test. --- diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 765726c..ad9703e 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -86,7 +86,7 @@ enum strlen_range_kind { }; static bool -get_range_strlen (tree, bitmap *, strlen_range_kind, c_strlen_data *, unsigned); +get_range_strlen (tree, bitmap, strlen_range_kind, c_strlen_data *, unsigned); /* Return true when DECL can be referenced from current unit. FROM_DECL (if non-null) specify constructor of variable DECL was taken from. @@ -1525,7 +1525,7 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len) /* Helper of get_range_strlen for ARG that is not an SSA_NAME. */ static bool -get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind, +get_range_strlen_tree (tree arg, bitmap visited, strlen_range_kind rkind, c_strlen_data *pdata, unsigned eltsize) { gcc_assert (TREE_CODE (arg) != SSA_NAME); @@ -1849,7 +1849,7 @@ get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind, Return true if *PDATA was successfully populated and false otherwise. */ static bool -get_range_strlen (tree arg, bitmap *visited, +get_range_strlen (tree arg, bitmap visited, strlen_range_kind rkind, c_strlen_data *pdata, unsigned eltsize) { @@ -1863,9 +1863,7 @@ get_range_strlen (tree arg, bitmap *visited, return false; /* If we were already here, break the infinite cycle. */ - if (!*visited) - *visited = BITMAP_ALLOC (NULL); - if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (arg))) + if (!bitmap_set_bit (visited, SSA_NAME_VERSION (arg))) return true; tree var = arg; @@ -1962,10 +1960,10 @@ get_range_strlen (tree arg, bitmap *visited, bool get_range_strlen (tree arg, c_strlen_data *pdata, unsigned eltsize) { - bitmap visited = NULL; + auto_bitmap visited; tree maxbound = pdata->maxbound; - if (!get_range_strlen (arg, &visited, SRK_LENRANGE, pdata, eltsize)) + if (!get_range_strlen (arg, visited, SRK_LENRANGE, pdata, eltsize)) { /* On failure extend the length range to an impossible maximum (a valid MAXLEN must be less than PTRDIFF_MAX - 1). Other @@ -1981,9 +1979,6 @@ get_range_strlen (tree arg, c_strlen_data *pdata, unsigned eltsize) if (maxbound && pdata->maxbound == maxbound) pdata->maxbound = build_all_ones_cst (size_type_node); - if (visited) - BITMAP_FREE (visited); - return !integer_all_onesp (pdata->maxlen); } @@ -2005,19 +2000,16 @@ get_maxval_strlen (tree arg, strlen_range_kind rkind, tree *nonstr = NULL) /* ARG must have an integral type when RKIND says so. */ gcc_assert (rkind != SRK_INT_VALUE || INTEGRAL_TYPE_P (TREE_TYPE (arg))); - bitmap visited = NULL; + auto_bitmap visited; /* Reset DATA.MAXLEN if the call fails or when DATA.MAXLEN is unbounded. */ c_strlen_data lendata = { }; - if (!get_range_strlen (arg, &visited, rkind, &lendata, /* eltsize = */1)) + if (!get_range_strlen (arg, visited, rkind, &lendata, /* eltsize = */1)) lendata.maxlen = NULL_TREE; else if (lendata.maxlen && integer_all_onesp (lendata.maxlen)) lendata.maxlen = NULL_TREE; - if (visited) - BITMAP_FREE (visited); - if (nonstr) { /* For callers prepared to handle unterminated arrays set diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-84.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-84.c new file mode 100644 index 0000000..2c0f507 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-84.c @@ -0,0 +1,15 @@ +/* PR middle-end/102960 - ICE: in sign_mask, at wide-int.h:855 in GCC 10.3.0 + { dg-do compile } + { dg-options "-Og -Wall" } */ + +void f (int i) +{ + const char *s; + if (i) + s = &"abcd"[i]; + + __builtin_printf ("%s", s); +} + +/* The use of s in the call to sprintf should result in: + { dg-prune-output "-Wmaybe-uninitialized" } */ diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index c0ec7d2..536f796 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -193,6 +193,8 @@ struct laststmt_struct } laststmt; static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree); +static bool get_range_strlen_dynamic (tree, gimple *s, c_strlen_data *, + bitmap, range_query *, unsigned *); /* Sets MINMAX to either the constant value or the range VAL is in and returns either the constant value or VAL on success or null @@ -1087,6 +1089,76 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals) } } +/* Helper of get_range_strlen_dynamic(). See below. */ + +static bool +get_range_strlen_phi (tree src, gphi *phi, + c_strlen_data *pdata, bitmap visited, + range_query *rvals, unsigned *pssa_def_max) +{ + if (!bitmap_set_bit (visited, SSA_NAME_VERSION (src))) + return true; + + if (*pssa_def_max == 0) + return false; + + --*pssa_def_max; + + /* Iterate over the PHI arguments and determine the minimum and maximum + length/size of each and incorporate them into the overall result. */ + for (unsigned i = 0; i != gimple_phi_num_args (phi); ++i) + { + tree arg = gimple_phi_arg_def (phi, i); + if (arg == gimple_phi_result (phi)) + continue; + + c_strlen_data argdata = { }; + if (!get_range_strlen_dynamic (arg, phi, &argdata, visited, rvals, + pssa_def_max)) + { + pdata->maxlen = build_all_ones_cst (size_type_node); + continue; + } + + /* Set the DECL of an unterminated array this argument refers to + if one hasn't been found yet. */ + if (!pdata->decl && argdata.decl) + pdata->decl = argdata.decl; + + if (!argdata.minlen + || (integer_zerop (argdata.minlen) + && (!argdata.maxbound + || integer_all_onesp (argdata.maxbound)) + && integer_all_onesp (argdata.maxlen))) + { + /* Set the upper bound of the length to unbounded. */ + pdata->maxlen = build_all_ones_cst (size_type_node); + continue; + } + + /* Adjust the minimum and maximum length determined so far and + the upper bound on the array size. */ + if (!pdata->minlen + || tree_int_cst_lt (argdata.minlen, pdata->minlen)) + pdata->minlen = argdata.minlen; + + if (!pdata->maxlen + || (argdata.maxlen + && TREE_CODE (argdata.maxlen) == INTEGER_CST + && tree_int_cst_lt (pdata->maxlen, argdata.maxlen))) + pdata->maxlen = argdata.maxlen; + + if (!pdata->maxbound + || TREE_CODE (pdata->maxbound) != INTEGER_CST + || (argdata.maxbound + && tree_int_cst_lt (pdata->maxbound, argdata.maxbound) + && !integer_all_onesp (argdata.maxbound))) + pdata->maxbound = argdata.maxbound; + } + + return true; +} + /* Attempt to determine the length of the string SRC. On success, store the length in *PDATA and return true. Otherwise, return false. VISITED is a bitmap of visited PHI nodes. RVALS points to the valuation @@ -1095,7 +1167,7 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals) static bool get_range_strlen_dynamic (tree src, gimple *stmt, - c_strlen_data *pdata, bitmap *visited, + c_strlen_data *pdata, bitmap visited, range_query *rvals, unsigned *pssa_def_max) { int idx = get_stridx (src, stmt); @@ -1104,72 +1176,9 @@ get_range_strlen_dynamic (tree src, gimple *stmt, if (TREE_CODE (src) == SSA_NAME) { gimple *def_stmt = SSA_NAME_DEF_STMT (src); - if (gimple_code (def_stmt) == GIMPLE_PHI) - { - if (!*visited) - *visited = BITMAP_ALLOC (NULL); - - if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (src))) - return true; - - if (*pssa_def_max == 0) - return false; - - --*pssa_def_max; - - /* Iterate over the PHI arguments and determine the minimum - and maximum length/size of each and incorporate them into - the overall result. */ - gphi *phi = as_a (def_stmt); - for (unsigned i = 0; i != gimple_phi_num_args (phi); ++i) - { - tree arg = gimple_phi_arg_def (phi, i); - if (arg == gimple_phi_result (def_stmt)) - continue; - - c_strlen_data argdata = { }; - if (get_range_strlen_dynamic (arg, phi, &argdata, visited, - rvals, pssa_def_max)) - { - /* Set the DECL of an unterminated array this argument - refers to if one hasn't been found yet. */ - if (!pdata->decl && argdata.decl) - pdata->decl = argdata.decl; - - if (!argdata.minlen - || (integer_zerop (argdata.minlen) - && (!argdata.maxbound - || integer_all_onesp (argdata.maxbound)) - && integer_all_onesp (argdata.maxlen))) - { - /* Set the upper bound of the length to unbounded. */ - pdata->maxlen = build_all_ones_cst (size_type_node); - continue; - } - - /* Adjust the minimum and maximum length determined - so far and the upper bound on the array size. */ - if (!pdata->minlen - || tree_int_cst_lt (argdata.minlen, pdata->minlen)) - pdata->minlen = argdata.minlen; - if (!pdata->maxlen - || (argdata.maxlen - && tree_int_cst_lt (pdata->maxlen, argdata.maxlen))) - pdata->maxlen = argdata.maxlen; - if (!pdata->maxbound - || TREE_CODE (pdata->maxbound) != INTEGER_CST - || (argdata.maxbound - && tree_int_cst_lt (pdata->maxbound, - argdata.maxbound) - && !integer_all_onesp (argdata.maxbound))) - pdata->maxbound = argdata.maxbound; - } - else - pdata->maxlen = build_all_ones_cst (size_type_node); - } - - return true; - } + if (gphi *phi = dyn_cast(def_stmt)) + return get_range_strlen_phi (src, phi, pdata, visited, rvals, + pssa_def_max); } /* Return success regardless of the result and handle *PDATA @@ -1286,11 +1295,11 @@ void get_range_strlen_dynamic (tree src, gimple *stmt, c_strlen_data *pdata, range_query *rvals) { - bitmap visited = NULL; + auto_bitmap visited; tree maxbound = pdata->maxbound; unsigned limit = param_ssa_name_def_chain_limit; - if (!get_range_strlen_dynamic (src, stmt, pdata, &visited, rvals, &limit)) + if (!get_range_strlen_dynamic (src, stmt, pdata, visited, rvals, &limit)) { /* On failure extend the length range to an impossible maximum (a valid MAXLEN must be less than PTRDIFF_MAX - 1). Other @@ -1305,9 +1314,6 @@ get_range_strlen_dynamic (tree src, gimple *stmt, c_strlen_data *pdata, MAXBOUND to SIZE_MAX. Otherwise leave it null (if it is null). */ if (maxbound && pdata->maxbound == maxbound) pdata->maxbound = build_all_ones_cst (size_type_node); - - if (visited) - BITMAP_FREE (visited); } /* Invalidate string length information for strings whose length might @@ -5831,7 +5837,7 @@ printf_strlen_execute (function *fun, bool warn_only) walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun)); if (dump_file && (dump_flags & TDF_DETAILS)) - walker.ptr_qry.dump (dump_file); + walker.ptr_qry.dump (dump_file, true); ssa_ver_to_stridx.release (); strinfo_pool.release ();