summaryrefslogtreecommitdiff
path: root/system/gcc/backport-r267157-posix-conformant-snprintf.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/gcc/backport-r267157-posix-conformant-snprintf.patch')
-rw-r--r--system/gcc/backport-r267157-posix-conformant-snprintf.patch80
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