Parse hexadecimal and octal strings correctly

The current implementation of __strtoul_internal seems to only pretend
to support hex and octal strings by detecting a preceding 0x or 0 and
marking base as 8 or 16. When it comes to the actual processing of the
string, it only considers numeric values within, thus breaking hex
values that may have [a-f] in them. Fixed with this commit.
This commit is contained in:
Siddhesh Poyarekar 2012-04-25 11:52:39 +05:30
parent 3ce2865f93
commit ceab42c380
2 changed files with 31 additions and 7 deletions

View file

@ -1,3 +1,9 @@
2012-04-25 Siddhesh Poyarekar <siddhesh@redhat.com>
Paul Pluzhnikov <ppluzhnikov@google.com>
* elf/dl-minimal.c (__strtoul_internal): Parse hexadecimal and octal
strings correctly.
2012-04-25 Chung-Lin Tang <cltang@codesourcery.com>
* sysdeps/sh/memcpy.S: Remove include of endian.h, change

View file

@ -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)