diff mbox series

gimple-ssa-sprintf: Fix typo in range check

Message ID 20240725234838.3804003-1-siddhesh@gotplt.org
State New
Headers show
Series gimple-ssa-sprintf: Fix typo in range check | expand

Commit Message

Siddhesh Poyarekar July 25, 2024, 11:48 p.m. UTC
The code to scale ranges for wide chars in format_string incorrectly
checks range.likely to scale range.unlikely, which is a copy-paste typo
from the immediate previous condition.

gcc/ChangeLog:

	gimple-ssa-sprintf.cc (format_string): Fix type in range check
	for UNLIKELY for wide chars.

Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
---
Tested on x86_64, no new testsuite regressions due to this fix.

 gcc/gimple-ssa-sprintf.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Jakub Jelinek July 26, 2024, 5:11 p.m. UTC | #1
On Thu, Jul 25, 2024 at 07:48:38PM -0400, Siddhesh Poyarekar wrote:
> The code to scale ranges for wide chars in format_string incorrectly
> checks range.likely to scale range.unlikely, which is a copy-paste typo
> from the immediate previous condition.
> 
> gcc/ChangeLog:
> 
> 	gimple-ssa-sprintf.cc (format_string): Fix type in range check
> 	for UNLIKELY for wide chars.
> 
> Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>

LGTM.
What exactly the code really wants to do is unclear to me, what does
the INT_MAX on the target have to do with the minimum/maximum/expected
sizes of %S or %ls printed strings is unclear, target PTRDIFF_MAX
maybe.  And why it uses this
	  if (slen.range.something < target_int_max ())
	    slen.range.something *= something_else;
rather than say
	  slen.range.something
	    = MIN (slang.range.something * something_else, target_int_max ());
perhaps with some overflow checking is also something that is hard to guess.
In any case, I think your patch is a step in the right direction.

> --- a/gcc/gimple-ssa-sprintf.cc
> +++ b/gcc/gimple-ssa-sprintf.cc
> @@ -2623,7 +2623,7 @@ format_string (const directive &dir, tree arg, pointer_query &ptr_qry)
>  	  if (slen.range.likely < target_int_max ())
>  	    slen.range.likely *= 2;
>  
> -	  if (slen.range.likely < target_int_max ())
> +	  if (slen.range.unlikely < target_int_max ())
>  	    slen.range.unlikely *= target_mb_len_max ();
>  
>  	  /* A non-empty wide character conversion may fail.  */
> -- 
> 2.45.1

	Jakub
Siddhesh Poyarekar July 26, 2024, 5:39 p.m. UTC | #2
On 2024-07-26 13:11, Jakub Jelinek wrote:
> On Thu, Jul 25, 2024 at 07:48:38PM -0400, Siddhesh Poyarekar wrote:
>> The code to scale ranges for wide chars in format_string incorrectly
>> checks range.likely to scale range.unlikely, which is a copy-paste typo
>> from the immediate previous condition.
>>
>> gcc/ChangeLog:
>>
>> 	gimple-ssa-sprintf.cc (format_string): Fix type in range check
>> 	for UNLIKELY for wide chars.
>>
>> Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
> 
> LGTM.

Thanks, pushed.

> What exactly the code really wants to do is unclear to me, what does
> the INT_MAX on the target have to do with the minimum/maximum/expected
> sizes of %S or %ls printed strings is unclear, target PTRDIFF_MAX

I think that is because the printf family returns the number of 
bytes/chars written in an int, which imposes the INT_MAX limitation on 
the format string expansion.

> maybe.  And why it uses this
> 	  if (slen.range.something < target_int_max ())
> 	    slen.range.something *= something_else;
> rather than say
> 	  slen.range.something
> 	    = MIN (slang.range.something * something_else, target_int_max ());
> perhaps with some overflow checking is also something that is hard to guess.

That's what I tried first but I settled for the minimal change because I 
didn't want to dig in deeper than I had time for to at the moment. 
Further down it checks if MAX and UNLIKELY cross INT_MAX and then resets 
to INT_MAX, but that looks suspicious on, e.g. 32-bit targets.  The code 
could use some refactoring/cleanup.

Thanks,
Sid
Jakub Jelinek July 26, 2024, 6:19 p.m. UTC | #3
On Fri, Jul 26, 2024 at 01:39:04PM -0400, Siddhesh Poyarekar wrote:
> > What exactly the code really wants to do is unclear to me, what does
> > the INT_MAX on the target have to do with the minimum/maximum/expected
> > sizes of %S or %ls printed strings is unclear, target PTRDIFF_MAX
> 
> I think that is because the printf family returns the number of bytes/chars
> written in an int, which imposes the INT_MAX limitation on the format string
> expansion.

Ah, yes, that makes sense.

> > maybe.  And why it uses this
> > 	  if (slen.range.something < target_int_max ())
> > 	    slen.range.something *= something_else;
> > rather than say
> > 	  slen.range.something
> > 	    = MIN (slang.range.something * something_else, target_int_max ());
> > perhaps with some overflow checking is also something that is hard to guess.
> 
> That's what I tried first but I settled for the minimal change because I
> didn't want to dig in deeper than I had time for to at the moment. Further
> down it checks if MAX and UNLIKELY cross INT_MAX and then resets to INT_MAX,
> but that looks suspicious on, e.g. 32-bit targets.  The code could use some
> refactoring/cleanup.

I think the counters are HOST_WIDE_INT or unsigned HOST_WIDE_INT, so always
64-bit.

	Jakub
diff mbox series

Patch

diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
index 025b0fbff6f..0900710647c 100644
--- a/gcc/gimple-ssa-sprintf.cc
+++ b/gcc/gimple-ssa-sprintf.cc
@@ -2623,7 +2623,7 @@  format_string (const directive &dir, tree arg, pointer_query &ptr_qry)
 	  if (slen.range.likely < target_int_max ())
 	    slen.range.likely *= 2;
 
-	  if (slen.range.likely < target_int_max ())
+	  if (slen.range.unlikely < target_int_max ())
 	    slen.range.unlikely *= target_mb_len_max ();
 
 	  /* A non-empty wide character conversion may fail.  */