121 lines
4.6 KiB
Diff
121 lines
4.6 KiB
Diff
From a3708cf6b0a5a68e2ed1ce3db28a03ed21d368d2 Mon Sep 17 00:00:00 2001
|
|
From: Joseph Myers <joseph@codesourcery.com>
|
|
Date: Mon, 19 Dec 2022 14:45:44 +0000
|
|
Subject: [PATCH] Avoid use of atoi in some places in libc
|
|
|
|
This patch is split out of
|
|
<https://sourceware.org/pipermail/libc-alpha/2022-December/144122.html>.
|
|
|
|
atoi has undefined behavior on out-of-range input, which makes it
|
|
problematic to use anywhere in glibc that might be processing input
|
|
out-of-range for atoi but not specified to produce undefined behavior
|
|
for the function calling atoi. Change some uses of atoi to call
|
|
strtol instead; this avoids the undefined behavior, though there is no
|
|
guarantee that the overflow handling of strtol is really right in
|
|
those places either. This also serves to avoid localplt test failures
|
|
given an installed header redirection for strtol (which means that the
|
|
call from the inline atoi implementation doesn't end up at a hidden
|
|
alias from libc_hidden_proto).
|
|
|
|
Certainly, the use of atoi is questionable in argp-help.c (shared with
|
|
gnulib, so shouldn't depend on glibc implementation details, and
|
|
processing user-provided input), and maybe also in argp-parse.c (I'm
|
|
not sure what that code in argp-parse.c is meant to be used for). I
|
|
also changed inet/rexec.c and resolv/res_init.c similarly to use
|
|
strtol to avoid such localplt failures, although given those files (in
|
|
those versions) are only used in glibc it's not problematic for them
|
|
to rely on the specific behavior of glibc's atoi on out-of-range input
|
|
(in the absence of compiler optimizations based on the undefined
|
|
behavior) in the same way it's problematic for gnulib code to do so.
|
|
|
|
There may be other uses of atoi (or atol or atoll), in any of glibc's
|
|
installed code, for which it would also be appropriate to avoid the
|
|
undefined behavior on out-of-range input; this patch only fixes the
|
|
specific cases needed to avoid localplt failures.
|
|
|
|
Tested for x86_64.
|
|
---
|
|
argp/argp-help.c | 6 +++---
|
|
argp/argp-parse.c | 2 +-
|
|
inet/rexec.c | 2 +-
|
|
resolv/res_init.c | 6 +++---
|
|
4 files changed, 8 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/argp/argp-help.c b/argp/argp-help.c
|
|
index 90a2795cef..f7f1134c80 100644
|
|
--- a/argp/argp-help.c
|
|
+++ b/argp/argp-help.c
|
|
@@ -210,9 +210,9 @@ fill_in_uparams (const struct argp_state *state)
|
|
}
|
|
else if (isdigit ((unsigned char) *arg))
|
|
{
|
|
- val = atoi (arg);
|
|
- while (isdigit ((unsigned char) *arg))
|
|
- arg++;
|
|
+ char *ep;
|
|
+ val = strtol (arg, &ep, 10);
|
|
+ arg = ep;
|
|
SKIPWS (arg);
|
|
}
|
|
|
|
diff --git a/argp/argp-parse.c b/argp/argp-parse.c
|
|
index 68dc45417b..1533b43aaf 100644
|
|
--- a/argp/argp-parse.c
|
|
+++ b/argp/argp-parse.c
|
|
@@ -147,7 +147,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
|
|
break;
|
|
|
|
case OPT_HANG:
|
|
- _argp_hang = atoi (arg ? arg : "3600");
|
|
+ _argp_hang = arg ? strtol (arg, NULL, 10) : 3600;
|
|
while (_argp_hang-- > 0)
|
|
__sleep (1);
|
|
break;
|
|
diff --git a/inet/rexec.c b/inet/rexec.c
|
|
index 064e979d68..c647b7ac34 100644
|
|
--- a/inet/rexec.c
|
|
+++ b/inet/rexec.c
|
|
@@ -134,7 +134,7 @@ retry:
|
|
if (!getnameinfo(&sa2.sa, sa2len,
|
|
NULL, 0, servbuff, sizeof(servbuff),
|
|
NI_NUMERICSERV))
|
|
- port = atoi(servbuff);
|
|
+ port = strtol(servbuff, NULL, 10);
|
|
(void) sprintf(num, "%u", port);
|
|
(void) __write(s, num, strlen(num)+1);
|
|
{ socklen_t len = sizeof (from);
|
|
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
|
index 2c0bea658e..61b958a437 100644
|
|
--- a/resolv/res_init.c
|
|
+++ b/resolv/res_init.c
|
|
@@ -654,7 +654,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
|
|
/* Search for and process individual options. */
|
|
if (!strncmp (cp, "ndots:", sizeof ("ndots:") - 1))
|
|
{
|
|
- int i = atoi (cp + sizeof ("ndots:") - 1);
|
|
+ int i = strtol (cp + sizeof ("ndots:") - 1, NULL, 10);
|
|
if (i <= RES_MAXNDOTS)
|
|
parser->template.ndots = i;
|
|
else
|
|
@@ -662,7 +662,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
|
|
}
|
|
else if (!strncmp (cp, "timeout:", sizeof ("timeout:") - 1))
|
|
{
|
|
- int i = atoi (cp + sizeof ("timeout:") - 1);
|
|
+ int i = strtol (cp + sizeof ("timeout:") - 1, NULL, 10);
|
|
if (i <= RES_MAXRETRANS)
|
|
parser->template.retrans = i;
|
|
else
|
|
@@ -670,7 +670,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
|
|
}
|
|
else if (!strncmp (cp, "attempts:", sizeof ("attempts:") - 1))
|
|
{
|
|
- int i = atoi (cp + sizeof ("attempts:") - 1);
|
|
+ int i = strtol (cp + sizeof ("attempts:") - 1, NULL, 10);
|
|
if (i <= RES_MAXRETRY)
|
|
parser->template.retry = i;
|
|
else
|
|
--
|
|
2.33.0
|
|
|