aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorSiddhesh Poyarekar <siddhesh@redhat.com>2012-04-25 11:52:39 +0530
committerSiddhesh Poyarekar <siddhesh@redhat.com>2012-04-25 12:27:03 +0530
commitceab42c380901dee40dc8b1fda0453b8ca918cc8 (patch)
tree60f68677ced022ef8e13cd686fac51635875eeaf /elf
parent3ce2865f93d42f4721d58088dd6ab1dac06ea85b (diff)
downloadglibc-ceab42c380901dee40dc8b1fda0453b8ca918cc8.zip
glibc-ceab42c380901dee40dc8b1fda0453b8ca918cc8.tar.gz
glibc-ceab42c380901dee40dc8b1fda0453b8ca918cc8.tar.bz2
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.
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-minimal.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
index 316de99..4a97f56 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)