[PATCH 1/2] Parse hex and octal strings correctly in __strtoul_internal

Paul Pluzhnikov ppluzhnikov@google.com
Wed Apr 25 05:53:00 GMT 2012


On Tue, Apr 24, 2012 at 10:27 PM, Siddhesh Poyarekar
<siddhesh@redhat.com> wrote:

> Ugh, no I did not. Here's the right patch.

Looks good to me. Minor nits:

  while (1)
    {
      unsigned long int digval;
      unsigned max_digit = (base <= 10) ? base - 1 : 9;
      if (*nptr >= '0' && *nptr <= '0' + max_digit)

max_digit computation could be moved out of the loop, as base is
constant after this point.

It may make sense to set max_digit when base is set (a couple lines
earlier), and avoid extra conditionals (as in attached patch).

-- 
Paul Pluzhnikov
-------------- next part --------------
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
index 316de99..9cf1ef0 100644
--- a/elf/dl-minimal.c
+++ b/elf/dl-minimal.c
@@ -1,6 +1,5 @@
 /* Minimal replacements for basic facilities used in the dynamic linker.
-   Copyright (C) 1995-1998,2000-2002,2004-2006,2007,2009
-   Free Software Foundation, Inc.
+   Copyright (C) 1995-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -232,6 +231,7 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group)
 {
   unsigned long int result = 0;
   long int sign = 1;
+  unsigned max_digit;
 
   while (*nptr == ' ' || *nptr == '\t')
     ++nptr;
@@ -253,6 +253,7 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group)
 
   assert (base == 0);
   base = 10;
+  max_digit = 9;
   if (*nptr == '0')
     {
       if (nptr[1] == 'x' || nptr[1] == 'X')
@@ -261,14 +262,31 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group)
 	  nptr += 2;
 	}
       else
-	base = 8;
+ 	{
+	  base = 8;
+	  max_digit = 7;
+	}
     }
 
-  while (*nptr >= '0' && *nptr <= '9')
+  while (1)
     {
-      unsigned long int digval = *nptr - '0';
-      if (result > ULONG_MAX / 10
-	  || (result == ULONG_MAX / 10 && digval > ULONG_MAX % 10))
+      unsigned long int digval;
+      if (*nptr >= '0' && *nptr <= '0' + max_digit)
+        digval = *nptr - '0';
+      else if (base == 16)
+        {
+	  if (*nptr >= 'a' && *nptr <= 'f')
+	    digval = *nptr - 'a' + 10;
+	  else if (*nptr >= 'A' && *nptr <= 'F')
+	    digval = *nptr - 'A' + 10;
+	  else
+	    break;
+	}
+      else
+        break;
+
+      if (result > ULONG_MAX / base
+	  || (result == ULONG_MAX / base && digval > ULONG_MAX % base))
 	{
 	  errno = ERANGE;
 	  if (endptr != NULL)


More information about the Libc-alpha mailing list