From 33e78be2e60ed9ac918dec13271d1bd9dce6e94e Mon Sep 17 00:00:00 2001 From: Jacek Tomasiak Date: Mon, 6 Feb 2023 13:39:44 +0100 Subject: [PATCH] ping: Fix the errno handling for strtod The setlocale(LC_ALL, "") following the strtod() for the '-i' option can fail if the LC_CTYPE is invalid. Hence the errno check following the setlocale(LC_ALL, "") thinks wrongly that strtod() failed with the errno and prints a warning: $ LC_ALL=XXX ping -i 1.9 -c1 8.8.8.8 ping: option argument contains garbage: ping: this will become fatal error in the future PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=58 time=1.34 ms The errno got from the execution of strtod() is saved and restored after setlocale() to be checked for any errors. The problem is only on Fedora/CentOS/RHEL with applied patch [1] from 2012 for glibc bug #14247. [1] https://src.fedoraproject.org/rpms/glibc/blob/rawhide/f/glibc-rh827510.patch Link: https://sourceware.org/bugzilla/show_bug.cgi?id=14247 Closes: https://github.com/iputils/iputils/pull/450 Reference:https://github.com/iputils/iputils/commit/33e78be2e60ed9ac918dec13271d1bd9dce6e94e Conflict:NA Fixes: 918e824 ("ping: add support for sub-second timeouts") Co-Developed-by: Sriram Rajagopalan Reviewed-by: Petr Vorel [ pvorel: mention glibc bug and Fedora/CentOS/RHEL ] Signed-off-by: Sriram Rajagopalan Signed-off-by: Jacek Tomasiak --- ping/ping.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ping/ping.c b/ping/ping.c index 89b0fa19..8f442037 100644 --- a/ping/ping.c +++ b/ping/ping.c @@ -214,6 +214,7 @@ static double ping_strtod(const char *str, const char *err_msg) { double num; char *end = NULL; + int strtod_errno = 0; if (str == NULL || *str == '\0') goto err; @@ -225,7 +226,10 @@ static double ping_strtod(const char *str, const char *err_msg) */ setlocale(LC_ALL, "C"); num = strtod(str, &end); + strtod_errno = errno; setlocale(LC_ALL, ""); + /* Ignore setlocale() errno (e.g. invalid locale in env). */ + errno = strtod_errno; if (errno || str == end || (end && *end)) { error(0, 0, _("option argument contains garbage: %s"), end);