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