From d539458148cb998600b4596227cd52eb1ca930da Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 21 Mar 2024 23:08:22 +0100 Subject: [klibc] inet: Stricter byte parsing in inet_aton() sscanf() skips spaces in some places, and accepts values that are out-of-range for a byte, so the following strings are wrongly accepted: "1.2.3.256" "256.1.2.3" "-1.2.3.4" "1.2.3.-4" " 1.2.3.4" "1. 2.3.4" "1.2.3.4 " "1.2.3.0x4" Implement our own strict conversion of decimal digits to bytes. Signed-off-by: Ben Hutchings --- usr/klibc/inet/inet_aton.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/usr/klibc/inet/inet_aton.c b/usr/klibc/inet/inet_aton.c index beceeea36a733..954e5d8d90be6 100644 --- a/usr/klibc/inet/inet_aton.c +++ b/usr/klibc/inet/inet_aton.c @@ -3,20 +3,38 @@ */ #include +#include #include int inet_aton(const char *str, struct in_addr *addr) { + int i = 0, digits = 0, val = 0; union { uint8_t b[4]; uint32_t l; } a; + char ch; - if (sscanf(str, "%hhu.%hhu.%hhu.%hhu", - &a.b[0], &a.b[1], &a.b[2], &a.b[3]) == 4) { - addr->s_addr = a.l; /* Always in network byte order */ - return 1; - } else { - return 0; + for (;;) { + ch = *str++; + if (ch == (i == 3 ? 0 : '.')) { + if (digits == 0) + return 0; + a.b[i] = val; + if (++i == 4) + break; + digits = 0; + val = 0; + } else if (isdigit((unsigned char)ch)) { + digits++; + val = val * 10 + (ch - '0'); + if (val > 0xff) + return 0; + } else { + return 0; + } } + + addr->s_addr = a.l; + return 1; } -- cgit 1.2.3-korg