C2x strtol binary constant handling: Fix special case "0b"

Message ID 3614039.ZfL8zNpBrT@nimes
State Changes Requested
Headers
Series C2x strtol binary constant handling: Fix special case "0b" |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success Build for i686

Commit Message

Bruno Haible March 16, 2023, 3:14 p.m. UTC
  Hi Joseph,

While adding C2x support to the strtol, strtoll, strtoul, strtoull
functions in Gnulib, I was glad to see that you have already done
the support in glibc. But I noticed that the glibc implementation
apparently does not handle the input "0b" correctly. The unit test
cases for this special case are:

  {
    const char input[] = "0b";
    char *ptr;
    long result;
    errno = 0;
    result = strtol (input, &ptr, 2);
    assert (result == 0L);
    assert (ptr == input + 1);
    assert (errno == 0);
  }
  {
    const char input[] = "0b";
    char *ptr;
    long result;
    errno = 0;
    result = strtol (input, &ptr, 0);
    assert (result == 0L);
    assert (ptr == input + 1);
    assert (errno == 0);
  }

and likewise for strtoll, strtoul, strtoull.

Find attached a correction for this. I have tested it in Gnulib (which
has very similar source code as glibc for this functionality), not in
Glibc directly. Therefore, please review thoroughly.

Bruno
  

Comments

Adhemerval Zanella Netto March 16, 2023, 9:01 p.m. UTC | #1
On 16/03/23 12:14, Bruno Haible wrote:
> Hi Joseph,
> 
> While adding C2x support to the strtol, strtoll, strtoul, strtoull
> functions in Gnulib, I was glad to see that you have already done
> the support in glibc. But I noticed that the glibc implementation
> apparently does not handle the input "0b" correctly. The unit test
> cases for this special case are:
> 
>   {
>     const char input[] = "0b";
>     char *ptr;
>     long result;
>     errno = 0;
>     result = strtol (input, &ptr, 2);
>     assert (result == 0L);
>     assert (ptr == input + 1);
>     assert (errno == 0);
>   }
>   {
>     const char input[] = "0b";
>     char *ptr;
>     long result;
>     errno = 0;
>     result = strtol (input, &ptr, 0);
>     assert (result == 0L);
>     assert (ptr == input + 1);
>     assert (errno == 0);
>   }
> 
> and likewise for strtoll, strtoul, strtoull.
> 
> Find attached a correction for this. I have tested it in Gnulib (which
> has very similar source code as glibc for this functionality), not in
> Glibc directly. Therefore, please review thoroughly.
> 
> Bruno

Could you also add these testscase on strtol tests ?
  

Patch

From c11497ab8117f27680537abccda211c5be560452 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Thu, 16 Mar 2023 15:25:45 +0100
Subject: [PATCH] C2x strtol binary constant handling: Fix special case "0b".

This is a follow-up to commit 64924422a99690d147a166b4de3103f3bf3eaf6c
by Joseph Myers.

The special case of input "0b" was not handled correctly. Test cases:

  {
    const char input[] = "0b";
    char *ptr;
    long result;
    errno = 0;
    result = strtol (input, &ptr, 2);
    assert (result == 0L);
    assert (ptr == input + 1);
    assert (errno == 0);
  }
  {
    const char input[] = "0b";
    char *ptr;
    long result;
    errno = 0;
    result = strtol (input, &ptr, 0);
    assert (result == 0L);
    assert (ptr == input + 1);
    assert (errno == 0);
  }

* stdlib/strtol_l.c (INTERNAL (__strtol_l)): Handle the binary integers
also in the 'noconv' part of the code.
---
 stdlib/strtol_l.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/stdlib/strtol_l.c b/stdlib/strtol_l.c
index 3424c3feab..548b46aa52 100644
--- a/stdlib/strtol_l.c
+++ b/stdlib/strtol_l.c
@@ -526,11 +526,15 @@  INTERNAL (__strtol_l) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
 noconv:
   /* We must handle a special case here: the base is 0 or 16 and the
      first two characters are '0' and 'x', but the rest are no
-     hexadecimal digits.  This is no error case.  We return 0 and
-     ENDPTR points to the `x`.  */
+     hexadecimal digits.  Likewise when the base is 0 or 2 and the
+     first two characters are '0' and 'b', but the rest are no binary
+     digits.  This is no error case.  We return 0 and ENDPTR points to
+     the 'x' or 'b'.  */
   if (endptr != NULL)
     {
-      if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
+      if (save - nptr >= 2
+	  && (TOUPPER (save[-1]) == L_('X')
+	      || (bin_cst && TOUPPER (save[-1]) == L_('B')))
 	  && save[-2] == L_('0'))
 	*endptr = (STRING_TYPE *) &save[-1];
       else
-- 
2.34.1