diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2024-03-21 23:08:22 +0100 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2024-03-21 23:28:39 +0100 |
commit | d539458148cb998600b4596227cd52eb1ca930da (patch) | |
tree | 97276762d5e43d86ac64e18ddcc9a3c17aac6c53 | |
parent | d4821f1d5417be8d8ecb7eb90a0def34c384b5bd (diff) | |
download | klibc-d539458148cb998600b4596227cd52eb1ca930da.tar.gz |
[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 <ben@decadent.org.uk>
-rw-r--r-- | usr/klibc/inet/inet_aton.c | 30 |
1 files 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 <arpa/inet.h> +#include <ctype.h> #include <stdio.h> 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; } |