bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Integer overflows in memchr


From: Po Lu
Subject: Re: Integer overflows in memchr
Date: Wed, 26 Jun 2024 18:05:14 +0800
User-agent: Gnus/5.13 (Gnus v5.13)

Bruno Haible <bruno@clisp.org> writes:

> This memchr invocation is wrong. memchr is defined in ISO C23 § 7.26.5.2
>   "The memchr generic function locates the first occurrence of c (...)
>    in the initial n characters (...) of the object pointed to by s."
> The term "object" being defined in § 3.15:
>   "region of data storage in the execution environment, the contents
>    of which can represent values"
>
> If you call memchr (s, c, n) where n > - (uintptr_t) s, you are pretending
> that the NULL pointer is part of a region of data storage, which is wrong.
>
> Similarly, if you call memchr (s, c, n) where n == - (uintptr_t) s, you are
> pretending that the address (uintptr_t)(-1) is part of a region of data
> storage, which is impossible on all OSes we know of.
>
> Thus, it is the application's duty to provide a sane value for n. The
> following code will usually avoid the overflow (although it still violates
> the specification):
>
>    const char *s = "";
>    size_t n = SIZE_MAX;
>    if (n > ~(uintptr_t)s)
>      n = ~(uintptr_t)s;
>    memchr (s, 0, n);

Does this not imply that Android's strnlen implementation is incorrect?

> Similarly here. strnlen is specified by POSIX
> https://pubs.opengroup.org/onlinepubs/9699919799/functions/strlen.html
>   "The strnlen() function shall compute the smaller of the number of bytes
>    in the array to which s points, not including any terminating NUL 
> character,
>    or the value of the maxlen argument. The strnlen() function shall never
>    examine more than maxlen bytes of the array pointed to by s."
> In other words, if precision is 0, you are allowing the implementation to
> look at SIZE_MAX bytes, which includes the NULL pointer. Thus the
> implementation is allowed to crash.

I believe that the semantics of the POSIX specification of this GNU
function omit the implied guarantee that strnlen will never examine
bytes beyond the first null byte, made in (libc)String Length:

     If the array S of size MAXLEN contains a null byte, the ‘strnlen’
     function returns the length of the string S in bytes.  Otherwise it
     returns MAXLEN.  Therefore this function is equivalent to ‘(strlen
                                                                 ------
     (S) < MAXLEN ? strlen (S) : MAXLEN)’ but it is more efficient and
     -----------------------------------
     works even if S is not null-terminated so long as MAXLEN does not
     exceed the size of S's array.

          char string[32] = "hello, world";
          strnlen (string, 32)
              ⇒ 12
          strnlen (string, 5)
              ⇒ 5

     This function is a GNU extension and is declared in ‘string.h’.

assuming that the proviso that follows the highlighted passage is only
applicable to the case where S is not NULL-terminated as Emacs's strings
are.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]