aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-06-08 12:52:42 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-06-08 12:52:42 -0700
commit37b66c0b1a2156a43fb813499326230639ba2773 (patch)
treeb39f1559b927e4e0487d7da71a826e032560de03
parent199fc19d3aaaf57944ef036e15904febe877fc93 (diff)
downloadglibc-37b66c0b1a2156a43fb813499326230639ba2773.zip
glibc-37b66c0b1a2156a43fb813499326230639ba2773.tar.gz
glibc-37b66c0b1a2156a43fb813499326230639ba2773.tar.bz2
ld.so: Consolidate 2 strtouls into _dl_strtoul [BZ #21528]
There are 2 minimal strtoul implementations in ld.so: 1. __strtoul_internal in elf/dl-minimal.c. 2. tunables_strtoul in elf/dl-tunables.c. This patch adds _dl_strtoul to replace them. Tested builds with and without --enable-tunables. [BZ #21528] * elf/dl-minimal.c (__strtoul_internal): Removed. (strtoul): Likewise. * elf/dl-misc.c (_dl_strtoul): New function. * elf/dl-tunables.c (tunables_strtoul): Removed. (tunable_initialize): Replace tunables_strtoul with _dl_strtoul. * elf/rtld.c (process_envvars): Likewise. * sysdeps/unix/sysv/linux/dl-librecon.h (_dl_osversion_init): Likewise. * sysdeps/generic/ldsodefs.h (_dl_strtoul): New prototype.
-rw-r--r--ChangeLog13
-rw-r--r--elf/dl-minimal.c84
-rw-r--r--elf/dl-misc.c84
-rw-r--r--elf/dl-tunables.c69
-rw-r--r--elf/rtld.c3
-rw-r--r--sysdeps/generic/ldsodefs.h4
-rw-r--r--sysdeps/unix/sysv/linux/dl-librecon.h2
7 files changed, 104 insertions, 155 deletions
diff --git a/ChangeLog b/ChangeLog
index 69035e8..72e5341 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2017-06-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #21528]
+ * elf/dl-minimal.c (__strtoul_internal): Removed.
+ (strtoul): Likewise.
+ * elf/dl-misc.c (_dl_strtoul): New function.
+ * elf/dl-tunables.c (tunables_strtoul): Removed.
+ (tunable_initialize): Replace tunables_strtoul with _dl_strtoul.
+ * elf/rtld.c (process_envvars): Likewise.
+ * sysdeps/unix/sysv/linux/dl-librecon.h (_dl_osversion_init):
+ Likewise.
+ * sysdeps/generic/ldsodefs.h (_dl_strtoul): New prototype.
+
2017-06-08 Zack Weinberg <zackw@panix.com>
* libio/bits/types/FILE.h, libio/bits/types/__FILE.h
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
index 1a35baf..59e159a 100644
--- a/elf/dl-minimal.c
+++ b/elf/dl-minimal.c
@@ -41,12 +41,6 @@ static void *alloc_ptr, *alloc_end, *alloc_last_block;
/* Declarations of global functions. */
extern void weak_function free (void *ptr);
extern void * weak_function realloc (void *ptr, size_t n);
-extern unsigned long int weak_function __strtoul_internal (const char *nptr,
- char **endptr,
- int base,
- int group);
-extern unsigned long int weak_function strtoul (const char *nptr,
- char **endptr, int base);
/* Allocate an aligned memory block. */
@@ -236,84 +230,6 @@ Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s.\n",
rtld_hidden_weak (__assert_perror_fail)
#endif
-unsigned long int weak_function
-__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;
-
- if (*nptr == '-')
- {
- sign = -1;
- ++nptr;
- }
- else if (*nptr == '+')
- ++nptr;
-
- if (*nptr < '0' || *nptr > '9')
- {
- if (endptr != NULL)
- *endptr = (char *) nptr;
- return 0UL;
- }
-
- assert (base == 0);
- base = 10;
- max_digit = 9;
- if (*nptr == '0')
- {
- if (nptr[1] == 'x' || nptr[1] == 'X')
- {
- base = 16;
- nptr += 2;
- }
- else
- {
- base = 8;
- max_digit = 7;
- }
- }
-
- while (1)
- {
- 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)
- *endptr = (char *) nptr;
- return ULONG_MAX;
- }
- result *= base;
- result += digval;
- ++nptr;
- }
-
- if (endptr != NULL)
- *endptr = (char *) nptr;
- return result * sign;
-}
-
-
#undef _itoa
/* We always use _itoa instead of _itoa_word in ld.so since the former
also has to be present and it is never about speed when these
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
index c5d3e0e..c469b5a 100644
--- a/elf/dl-misc.c
+++ b/elf/dl-misc.c
@@ -360,3 +360,87 @@ _dl_higher_prime_number (unsigned long int n)
return *low;
}
+
+/* A stripped down strtoul-like implementation for very early use. It
+ does not set errno if the result is outside bounds because it may get
+ called before errno may have been set up. */
+
+uint64_t
+internal_function
+_dl_strtoul (const char *nptr, char **endptr)
+{
+ uint64_t result = 0;
+ bool positive = true;
+ unsigned max_digit;
+
+ while (*nptr == ' ' || *nptr == '\t')
+ ++nptr;
+
+ if (*nptr == '-')
+ {
+ positive = false;
+ ++nptr;
+ }
+ else if (*nptr == '+')
+ ++nptr;
+
+ if (*nptr < '0' || *nptr > '9')
+ {
+ if (endptr != NULL)
+ *endptr = (char *) nptr;
+ return 0UL;
+ }
+
+ int base = 10;
+ max_digit = 9;
+ if (*nptr == '0')
+ {
+ if (nptr[1] == 'x' || nptr[1] == 'X')
+ {
+ base = 16;
+ nptr += 2;
+ }
+ else
+ {
+ base = 8;
+ max_digit = 7;
+ }
+ }
+
+ while (1)
+ {
+ 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 >= (UINT64_MAX - digval) / base)
+ {
+ if (endptr != NULL)
+ *endptr = (char *) nptr;
+ return UINT64_MAX;
+ }
+ result *= base;
+ result += digval;
+ ++nptr;
+ }
+
+ if (endptr != NULL)
+ *endptr = (char *) nptr;
+
+ /* Avoid 64-bit multiplication. */
+ if (!positive)
+ result = -result;
+
+ return result;
+}
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index 76e8c5c..b3c1392 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -102,73 +102,6 @@ get_next_env (char **envp, char **name, size_t *namelen, char **val,
return NULL;
}
-/* A stripped down strtoul-like implementation for very early use. It does not
- set errno if the result is outside bounds because it gets called before
- errno may have been set up. */
-static uint64_t
-tunables_strtoul (const char *nptr)
-{
- uint64_t result = 0;
- long int sign = 1;
- unsigned max_digit;
-
- while (*nptr == ' ' || *nptr == '\t')
- ++nptr;
-
- if (*nptr == '-')
- {
- sign = -1;
- ++nptr;
- }
- else if (*nptr == '+')
- ++nptr;
-
- if (*nptr < '0' || *nptr > '9')
- return 0UL;
-
- int base = 10;
- max_digit = 9;
- if (*nptr == '0')
- {
- if (nptr[1] == 'x' || nptr[1] == 'X')
- {
- base = 16;
- nptr += 2;
- }
- else
- {
- base = 8;
- max_digit = 7;
- }
- }
-
- while (1)
- {
- 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 >= (UINT64_MAX - digval) / base)
- return UINT64_MAX;
- result *= base;
- result += digval;
- ++nptr;
- }
-
- return result * sign;
-}
-
#define TUNABLE_SET_VAL_IF_VALID_RANGE(__cur, __val, __type, __default_min, \
__default_max) \
({ \
@@ -233,7 +166,7 @@ tunable_initialize (tunable_t *cur, const char *strval)
if (cur->type.type_code != TUNABLE_TYPE_STRING)
{
- val = tunables_strtoul (strval);
+ val = _dl_strtoul (strval, NULL);
valp = &val;
}
else
diff --git a/elf/rtld.c b/elf/rtld.c
index 3746653..2446a87 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -2409,8 +2409,7 @@ process_envvars (enum mode *modep)
/* Mask for the important hardware capabilities. */
if (!__libc_enable_secure
&& memcmp (envline, "HWCAP_MASK", 10) == 0)
- GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL,
- 0, 0);
+ GLRO(dl_hwcap_mask) = _dl_strtoul (&envline[11], NULL);
break;
#endif
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 695ac24..4508365 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -254,6 +254,10 @@ extern int _dl_name_match_p (const char *__name, const struct link_map *__map)
extern unsigned long int _dl_higher_prime_number (unsigned long int n)
internal_function attribute_hidden;
+/* A stripped down strtoul-like implementation. */
+uint64_t internal_function _dl_strtoul (const char *, char **)
+ internal_function attribute_hidden;
+
/* Function used as argument for `_dl_receive_error' function. The
arguments are the error code, error string, and the objname the
error occurred in. */
diff --git a/sysdeps/unix/sysv/linux/dl-librecon.h b/sysdeps/unix/sysv/linux/dl-librecon.h
index a6e54be..e726ff2 100644
--- a/sysdeps/unix/sysv/linux/dl-librecon.h
+++ b/sysdeps/unix/sysv/linux/dl-librecon.h
@@ -28,7 +28,7 @@ _dl_osversion_init (char *assume_kernel)
for (i = 0; i < 3; i++, p = q + 1)
{
- j = __strtoul_internal (p, &q, 0, 0);
+ j = _dl_strtoul (p, &q);
if (j >= 255 || p == q || (i < 2 && *q && *q != '.'))
{
osversion = 0;