From ceab42c380901dee40dc8b1fda0453b8ca918cc8 Mon Sep 17 00:00:00 2001 From: Siddhesh Poyarekar Date: Wed, 25 Apr 2012 11:52:39 +0530 Subject: 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. --- ChangeLog | 6 ++++++ elf/dl-minimal.c | 32 +++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0f558fe37c..1a1d23a968 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-04-25 Siddhesh Poyarekar + Paul Pluzhnikov + + * elf/dl-minimal.c (__strtoul_internal): Parse hexadecimal and octal + strings correctly. + 2012-04-25 Chung-Lin Tang * sysdeps/sh/memcpy.S: Remove include of endian.h, change diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index 316de99b8f..4a97f56faa 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) -- cgit 1.4.1