Hi there,

I have a patch to fix to regressions we observed in armhf native environment.

To effectively check out of range for format string, a target type should be
used. And according to the standard, int type is used for "width" and 
"precision"
field of format string.

Here target_strtol10 is rename to target_strtoi10, and fixed to use
target_int_max () which is target dependent.

The value returned by target_strtol10 is (target_int_max () + 1) when it 
exceeds the range.
This is used to indicate its value exceeds target INT_MAX for the later warning.

Is it Okay to commit?

Regards,
Renlin

gcc/ChangeLog:

2018-01-31  Renlin Li  <renlin...@arm.com>

        * gimple-ssa-sprintf.c (target_strtol10): Use target integer to check
        the range. Rename it into ....
        (target_strtoi10): This.
        (parse_directive): Compare with target int max instead of LONG_MAX.


On 20/06/17 12:00, Renlin Li wrote:
Hi Martin,

I did a little investigation into this. Please correct me if I missed anything.

I build a native arm-linux-gnueabihf toolchain in armhf hardware.
It's ILP32. So in this situation:

HOST_WIDE_INT is long, which is 32-bit.
integer type 32-bit as well, so target_int_max () == LONG_MAX


gimple-ssa-sprintf.c line 2887
  /* Has the likely and maximum directive output exceeded INT_MAX?  */
  bool likelyximax = *dir.beg && res->range.likely > target_int_max ();

likelyximax will be false as the latter expression is always false.
res->range.likely is truncated to LONG_MAX (in target_strtol10 function)

I have checked in cross build environment (host x86_64), this variable is true.

Regards,
Renlin


On 13/06/17 09:16, Renlin Li wrote:
Hi Martin,

On 04/06/17 23:24, Martin Sebor wrote:
On 06/02/2017 09:38 AM, Renlin Li wrote:
Hi Martin,

After r247444, I saw the following two regressions in
arm-linux-gnueabihf environment:

FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-18.c  (test for warnings,
line 119)
PASS: gcc.dg/tree-ssa/builtin-sprintf-warn-18.c  (test for warnings,
line 121)
FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-18.c  (test for warnings,
line 121)

The warning message related to those two lines are:
testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c:119:3: warning:
'%9223372036854775808i' directive width out of range [-Wformat-overflow=]

testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c:121:3: warning:
'%.9223372036854775808i' directive precision out of range
[-Wformat-overflow=]

testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c:121:3: warning:
'%.9223372036854775808i' directive precision out of range
[-Wformat-overflow=]

Did you notice similar things from your test environment, Christophe?

Looks like you're missing a couple of warnings.  I see the following
output with both my arm-linux-gnueabihf cross compiler and my native
x86_64 GCC, both in 32-bit and 64-bit modes, as expected by the test,
so I don't see the same issue in my environment.

Yes, it happens on arm-linux-gnueabihf native environment. the warnings with 
"INT_MAX"
line are missing. I don't know if the host environment will cause the 
difference.

Regards,
Renlin
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 14b12191d9b16699b28541cb24914fa9f8d8fea9..3a903ffad8e524c6d2fd405812ebc0869bfed7a7 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -399,12 +399,12 @@ target_to_host (char *hostr, size_t hostsz, const char *targstr)
 }
 
 /* Convert the sequence of decimal digits in the execution character
-   starting at S to a long, just like strtol does.  Return the result
-   and set *END to one past the last converted character.  On range
-   error set ERANGE to the digit that caused it.  */
+   starting at S to a int.  Return the result and set *END to one past the last
+   converted character.
+   On range error set ERANGE to the digit that caused it.  */
 
-static inline long
-target_strtol10 (const char **ps, const char **erange)
+static inline HOST_WIDE_INT
+target_strtoi10 (const char **ps, const char **erange)
 {
   unsigned HOST_WIDE_INT val = 0;
   for ( ; ; ++*ps)
@@ -415,9 +415,9 @@ target_strtol10 (const char **ps, const char **erange)
 	  c -= '0';
 
 	  /* Check for overflow.  */
-	  if (val > (LONG_MAX - c) / 10LU)
+	  if (val > (target_int_max () - c) / 10LU)
 	    {
-	      val = LONG_MAX;
+	      val = target_int_max () + 1;
 	      *erange = *ps;
 
 	      /* Skip the remaining digits.  */
@@ -3082,7 +3082,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
 	 width and sort it out later after the next character has
 	 been seen.  */
       pwidth = pf;
-      width = target_strtol10 (&pf, &werange);
+      width = target_strtoi10 (&pf, &werange);
     }
   else if (target_to_host (*pf) == '*')
     {
@@ -3164,7 +3164,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
 	{
 	  werange = 0;
 	  pwidth = pf;
-	  width = target_strtol10 (&pf, &werange);
+	  width = target_strtoi10 (&pf, &werange);
 	}
       else if (target_to_host (*pf) == '*')
 	{
@@ -3197,7 +3197,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
       if (ISDIGIT (target_to_host (*pf)))
 	{
 	  pprec = pf;
-	  precision = target_strtol10 (&pf, &perange);
+	  precision = target_strtoi10 (&pf, &perange);
 	}
       else if (target_to_host (*pf) == '*')
 	{
@@ -3348,7 +3348,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
     }
   else
     {
-      if (width == LONG_MAX && werange)
+      if ((unsigned HOST_WIDE_INT) width > target_int_max () && werange)
 	{
 	  size_t begin = dir.beg - info.fmtstr + (pwidth - pcnt);
 	  size_t caret = begin + (werange - pcnt);
@@ -3381,7 +3381,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
     }
   else
     {
-      if (precision == LONG_MAX && perange)
+      if ((unsigned HOST_WIDE_INT) precision > target_int_max () && perange)
 	{
 	  size_t begin = dir.beg - info.fmtstr + (pprec - pcnt) - 1;
 	  size_t caret = dir.beg - info.fmtstr + (perange - pcnt) - 1;

Reply via email to