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:
parent
3ce2865f93
commit
ceab42c380
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user