diff options
author | Martin Sebor <msebor@redhat.com> | 2018-12-14 22:38:08 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2018-12-14 15:38:08 -0700 |
commit | 3e6837c2a56f47c6b3156bbc12a9e89611412f83 (patch) | |
tree | 1ebbcdd3b8bf5c101b8a55c558e45f3af4b6455a /gcc/gimple-ssa-sprintf.c | |
parent | 92863013e5f487dc43d78228ad20757ee8f20d77 (diff) | |
download | gcc-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.c | 44 |
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) |