mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-28 15:51:07 +00:00
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.
This commit is contained in:
parent
199fc19d3a
commit
37b66c0b1a
13
ChangeLog
13
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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user