mbrtowc: Avoid compare with the result pointer add

Message ID 20250110030040.65458-1-yunqiang@isrc.iscas.ac.cn (mailing list archive)
State New
Headers
Series mbrtowc: Avoid compare with the result pointer add |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed

Commit Message

YunQiang Su Jan. 10, 2025, 3 a.m. UTC
  inbuf = (const unsigned char *) s;
  endbuf = inbuf + n;
  if (__glibc_unlikely (endbuf < inbuf))  // <--- here
    {
      endbuf = (const unsigned char *) ~(uintptr_t) 0;
      if (endbuf == inbuf)
        goto ilseq;
    }

Some compilers (such as clang 20), may treat that the endbuf
greater than inbuf always, as n is a `size_t`, aka `unsigned long`.

Let's use
   if (__glibc_unlikely ((ssize_t)n < 0))
instead.
---
 wcsmbs/mbrtowc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
  

Comments

YunQiang Su Jan. 10, 2025, 3:12 a.m. UTC | #1
> 2025年1月10日 11:00,YunQiang Su <yunqiang@isrc.iscas.ac.cn> 写道:
> 
>  inbuf = (const unsigned char *) s;
>  endbuf = inbuf + n;
>  if (__glibc_unlikely (endbuf < inbuf))  // <--- here
>    {
>      endbuf = (const unsigned char *) ~(uintptr_t) 0;
>      if (endbuf == inbuf)
>        goto ilseq;
>    }
> 
> Some compilers (such as clang 20), may treat that the endbuf
> greater than inbuf always, as n is a `size_t`, aka `unsigned long`.
> 
> Let's use
>   if (__glibc_unlikely ((ssize_t)n < 0))
> instead.
> ---
> wcsmbs/mbrtowc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/wcsmbs/mbrtowc.c b/wcsmbs/mbrtowc.c
> index 47068ed0e0..124f4b6f0a 100644
> --- a/wcsmbs/mbrtowc.c
> +++ b/wcsmbs/mbrtowc.c
> @@ -71,7 +71,7 @@ __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
>   /* Do a normal conversion.  */
>   inbuf = (const unsigned char *) s;
>   endbuf = inbuf + n;
> -  if (__glibc_unlikely (endbuf < inbuf))
> +  if (__glibc_unlikely ((ssize_t)n < 0))

This patch is incorrect, Sorry for the noisy.
For example on a 32bit system:
If `inbuf` is 8, and `n` is 0x80000008
    `endbuf < inbuf` is false
while
    (ssize_t)n < 0    is true.

>     {
>       endbuf = (const unsigned char *) ~(uintptr_t) 0;
>       if (endbuf == inbuf)
> -- 
> 2.39.5 (Apple Git-154)
  
Sam James Jan. 10, 2025, 3:15 a.m. UTC | #2
YunQiang Su <yunqiang@isrc.iscas.ac.cn> writes:

>   inbuf = (const unsigned char *) s;
>   endbuf = inbuf + n;
>   if (__glibc_unlikely (endbuf < inbuf))  // <--- here
>     {
>       endbuf = (const unsigned char *) ~(uintptr_t) 0;
>       if (endbuf == inbuf)
>         goto ilseq;
>     }
>
> Some compilers (such as clang 20), may treat that the endbuf
> greater than inbuf always, as n is a `size_t`, aka `unsigned long`.

Please always mention what problem you're seeing in the wild, too. A
warning? Error? Test failure?

(I see you've retracted the patch, but the comment stands for future changes).
  
Sam James Jan. 10, 2025, 6:15 a.m. UTC | #3
Sam James <sam@gentoo.org> writes:

> YunQiang Su <yunqiang@isrc.iscas.ac.cn> writes:
>
>>   inbuf = (const unsigned char *) s;
>>   endbuf = inbuf + n;
>>   if (__glibc_unlikely (endbuf < inbuf))  // <--- here
>>     {
>>       endbuf = (const unsigned char *) ~(uintptr_t) 0;
>>       if (endbuf == inbuf)
>>         goto ilseq;
>>     }
>>
>> Some compilers (such as clang 20), may treat that the endbuf
>> greater than inbuf always, as n is a `size_t`, aka `unsigned long`.
>
> Please always mention what problem you're seeing in the wild, too. A
> warning? Error? Test failure?
>
> (I see you've retracted the patch, but the comment stands for future changes).

I assume the context is https://github.com/llvm/llvm-project/issues/122400.
  

Patch

diff --git a/wcsmbs/mbrtowc.c b/wcsmbs/mbrtowc.c
index 47068ed0e0..124f4b6f0a 100644
--- a/wcsmbs/mbrtowc.c
+++ b/wcsmbs/mbrtowc.c
@@ -71,7 +71,7 @@  __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
   /* Do a normal conversion.  */
   inbuf = (const unsigned char *) s;
   endbuf = inbuf + n;
-  if (__glibc_unlikely (endbuf < inbuf))
+  if (__glibc_unlikely ((ssize_t)n < 0))
     {
       endbuf = (const unsigned char *) ~(uintptr_t) 0;
       if (endbuf == inbuf)