mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-01 09:20:19 +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>
|
2017-06-08 Zack Weinberg <zackw@panix.com>
|
||||||
|
|
||||||
* libio/bits/types/FILE.h, libio/bits/types/__FILE.h
|
* 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. */
|
/* Declarations of global functions. */
|
||||||
extern void weak_function free (void *ptr);
|
extern void weak_function free (void *ptr);
|
||||||
extern void * weak_function realloc (void *ptr, size_t n);
|
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. */
|
/* 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)
|
rtld_hidden_weak (__assert_perror_fail)
|
||||||
#endif
|
#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
|
#undef _itoa
|
||||||
/* We always use _itoa instead of _itoa_word in ld.so since the former
|
/* 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
|
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;
|
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;
|
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, \
|
#define TUNABLE_SET_VAL_IF_VALID_RANGE(__cur, __val, __type, __default_min, \
|
||||||
__default_max) \
|
__default_max) \
|
||||||
({ \
|
({ \
|
||||||
@ -233,7 +166,7 @@ tunable_initialize (tunable_t *cur, const char *strval)
|
|||||||
|
|
||||||
if (cur->type.type_code != TUNABLE_TYPE_STRING)
|
if (cur->type.type_code != TUNABLE_TYPE_STRING)
|
||||||
{
|
{
|
||||||
val = tunables_strtoul (strval);
|
val = _dl_strtoul (strval, NULL);
|
||||||
valp = &val;
|
valp = &val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2409,8 +2409,7 @@ process_envvars (enum mode *modep)
|
|||||||
/* Mask for the important hardware capabilities. */
|
/* Mask for the important hardware capabilities. */
|
||||||
if (!__libc_enable_secure
|
if (!__libc_enable_secure
|
||||||
&& memcmp (envline, "HWCAP_MASK", 10) == 0)
|
&& memcmp (envline, "HWCAP_MASK", 10) == 0)
|
||||||
GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL,
|
GLRO(dl_hwcap_mask) = _dl_strtoul (&envline[11], NULL);
|
||||||
0, 0);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#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)
|
extern unsigned long int _dl_higher_prime_number (unsigned long int n)
|
||||||
internal_function attribute_hidden;
|
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
|
/* Function used as argument for `_dl_receive_error' function. The
|
||||||
arguments are the error code, error string, and the objname the
|
arguments are the error code, error string, and the objname the
|
||||||
error occurred in. */
|
error occurred in. */
|
||||||
|
@ -28,7 +28,7 @@ _dl_osversion_init (char *assume_kernel)
|
|||||||
|
|
||||||
for (i = 0; i < 3; i++, p = q + 1)
|
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 != '.'))
|
if (j >= 255 || p == q || (i < 2 && *q && *q != '.'))
|
||||||
{
|
{
|
||||||
osversion = 0;
|
osversion = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user