aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-ssa-sprintf.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-12-14 22:38:08 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-12-14 15:38:08 -0700
commit3e6837c2a56f47c6b3156bbc12a9e89611412f83 (patch)
tree1ebbcdd3b8bf5c101b8a55c558e45f3af4b6455a /gcc/gimple-ssa-sprintf.c
parent92863013e5f487dc43d78228ad20757ee8f20d77 (diff)
downloadgcc-3e6837c2a56f47c6b3156bbc12a9e89611412f83.zip
gcc-3e6837c2a56f47c6b3156bbc12a9e89611412f83.tar.gz
gcc-3e6837c2a56f47c6b3156bbc12a9e89611412f83.tar.bz2
PR tree-optimization/87096 - Optimised snprintf is not POSIX conformant
gcc/ChangeLog: PR rtl-optimization/87096 * gimple-ssa-sprintf.c (sprintf_dom_walker::handle_gimple_call): Avoid folding calls whose bound may exceed INT_MAX. Diagnose bound ranges that exceed the limit. gcc/testsuite/ChangeLog: PR tree-optimization/87096 * gcc.dg/tree-ssa/builtin-snprintf-4.c: New test. From-SVN: r267157
Diffstat (limited to 'gcc/gimple-ssa-sprintf.c')
-rw-r--r--gcc/gimple-ssa-sprintf.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 00485d9..52286a6 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -3990,6 +3990,7 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
/* True when the destination size is constant as opposed to the lower
or upper bound of a range. */
bool dstsize_cst_p = true;
+ bool posunder4k = true;
if (idx_dstsize == UINT_MAX)
{
@@ -4022,11 +4023,20 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
"specified bound %wu exceeds maximum object size "
"%wu",
dstsize, target_size_max () / 2);
+ /* POSIX requires snprintf to fail if DSTSIZE is greater
+ than INT_MAX. Even though not all POSIX implementations
+ conform to the requirement, avoid folding in this case. */
+ posunder4k = false;
}
else if (dstsize > target_int_max ())
- warning_at (gimple_location (info.callstmt), info.warnopt (),
- "specified bound %wu exceeds %<INT_MAX%>",
- dstsize);
+ {
+ warning_at (gimple_location (info.callstmt), info.warnopt (),
+ "specified bound %wu exceeds %<INT_MAX%>",
+ dstsize);
+ /* POSIX requires snprintf to fail if DSTSIZE is greater
+ than INT_MAX. Avoid folding in that case. */
+ posunder4k = false;
+ }
}
else if (TREE_CODE (size) == SSA_NAME)
{
@@ -4035,9 +4045,29 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
of them at level 2. */
value_range *vr = evrp_range_analyzer.get_value_range (size);
if (range_int_cst_p (vr))
- dstsize = (warn_level < 2
- ? TREE_INT_CST_LOW (vr->max ())
- : TREE_INT_CST_LOW (vr->min ()));
+ {
+ unsigned HOST_WIDE_INT minsize = TREE_INT_CST_LOW (vr->min ());
+ unsigned HOST_WIDE_INT maxsize = TREE_INT_CST_LOW (vr->max ());
+ dstsize = warn_level < 2 ? maxsize : minsize;
+
+ if (minsize > target_int_max ())
+ warning_at (gimple_location (info.callstmt), info.warnopt (),
+ "specified bound range [%wu, %wu] exceeds "
+ "%<INT_MAX%>",
+ minsize, maxsize);
+
+ /* POSIX requires snprintf to fail if DSTSIZE is greater
+ than INT_MAX. Avoid folding if that's possible. */
+ if (maxsize > target_int_max ())
+ posunder4k = false;
+ }
+ else if (vr->varying_p ())
+ {
+ /* POSIX requires snprintf to fail if DSTSIZE is greater
+ than INT_MAX. Since SIZE's range is unknown, avoid
+ folding. */
+ posunder4k = false;
+ }
/* The destination size is not constant. If the function is
bounded (e.g., snprintf) a lower bound of zero doesn't
@@ -4122,7 +4152,7 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
directive. Clear POSUNDER4K for the former set of functions and set
it to true for the latter (it can only be cleared later, but it is
never set to true again). */
- res.posunder4k = dstptr;
+ res.posunder4k = posunder4k && dstptr;
bool success = compute_format_length (info, &res);
if (res.warned)