ld.so: Consolidate 2 strtouls into _dl_strtoul [BZ #21528]
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 8 Jun 2017 19:52:42 +0000 (12:52 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 8 Jun 2017 19:52:42 +0000 (12:52 -0700)
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.

ChangeLog
elf/dl-minimal.c
elf/dl-misc.c
elf/dl-tunables.c
elf/rtld.c
sysdeps/generic/ldsodefs.h
sysdeps/unix/sysv/linux/dl-librecon.h

index 69035e8..72e5341 100644 (file)
--- 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
index 1a35baf..59e159a 100644 (file)
@@ -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
 \f
-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
index c5d3e0e..c469b5a 100644 (file)
@@ -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;
+}
index 76e8c5c..b3c1392 100644 (file)
@@ -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
index 3746653..2446a87 100644 (file)
@@ -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
 
index 695ac24..4508365 100644 (file)
@@ -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.  */
index a6e54be..e726ff2 100644 (file)
@@ -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;