https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87096
GCC's "optimised" snprintf is not POSIX conformant
--- trunk/gcc/gimple-ssa-sprintf.c 2018/12/07 17:02:11 266897
+++ trunk/gcc/gimple-ssa-sprintf.c 2018/12/14 22:38:08 267157
@@ -3899,6 +3899,7 @@
/* 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 == HOST_WIDE_INT_M1U)
{
@@ -3931,11 +3932,20 @@
"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)
{
@@ -3944,9 +3954,29 @@
if (vr->type == VR_RANGE
&& TREE_CODE (vr->min) == INTEGER_CST
&& TREE_CODE (vr->max) == INTEGER_CST)
- 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->type == VR_VARYING)
+ {
+ /* 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
@@ -4033,7 +4073,7 @@
the call. Avoid this optimization when -frounding-math is in effect
and the format string contains a floating point directive. */
bool call_removed = false;
- if (success && optimize > 0)
+ if (!posunder4k && success && optimize > 0)
{
/* Save a copy of the iterator pointing at the call. The iterator
may change to point past the call in try_substitute_return_value