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 %", - dstsize); + { + warning_at (gimple_location (info.callstmt), info.warnopt (), + "specified bound %wu exceeds %", + 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 " + "%", + 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