diff options
Diffstat (limited to 'system/gcc/backport-r267157-posix-conformant-snprintf.patch')
-rw-r--r-- | system/gcc/backport-r267157-posix-conformant-snprintf.patch | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/system/gcc/backport-r267157-posix-conformant-snprintf.patch b/system/gcc/backport-r267157-posix-conformant-snprintf.patch new file mode 100644 index 000000000..adedf0ce9 --- /dev/null +++ b/system/gcc/backport-r267157-posix-conformant-snprintf.patch @@ -0,0 +1,80 @@ +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 |