This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] [BZ #21528] rtld: Add _dl_strtoul


On Mon, Jun 5, 2017 at 12:59 PM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> 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.
>
> OK for master?
>
> Thanks.
>
> H.J.
> ---
>         [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.
>

Here is the updated patch.  Any comments, objections?

-- 
H.J.
From 9f8e103a6c79db021f934c6b3b69dd5f423b2c0a Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 5 Jun 2017 12:42:58 -0700
Subject: [PATCH] ld.so: Consolidate 2 strtouls into _dl_strtoul

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.
---
 elf/dl-minimal.c                      | 84 -----------------------------------
 elf/dl-misc.c                         | 84 +++++++++++++++++++++++++++++++++++
 elf/dl-tunables.c                     | 69 +---------------------------
 elf/rtld.c                            |  3 +-
 sysdeps/generic/ldsodefs.h            |  4 ++
 sysdeps/unix/sysv/linux/dl-librecon.h |  2 +-
 6 files changed, 91 insertions(+), 155 deletions(-)

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;
-- 
2.9.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]