aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-strlen.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2021-11-16 09:18:25 -0700
committerMartin Sebor <msebor@redhat.com>2021-11-16 09:18:25 -0700
commitba6e17e78db543b336c196b55fa6430e513f1941 (patch)
tree834fa5781c510ed696423f889b3bcc46572f9729 /gcc/tree-ssa-strlen.c
parent0002a8a1997c7beb3c4facc17ed0d1294e3dce14 (diff)
downloadgcc-ba6e17e78db543b336c196b55fa6430e513f1941.zip
gcc-ba6e17e78db543b336c196b55fa6430e513f1941.tar.gz
gcc-ba6e17e78db543b336c196b55fa6430e513f1941.tar.bz2
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.
Diffstat (limited to 'gcc/tree-ssa-strlen.c')
-rw-r--r--gcc/tree-ssa-strlen.c152
1 files changed, 79 insertions, 73 deletions
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 <gphi *> (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<gphi *>(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 ();