aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2024-03-21 23:08:22 +0100
committerBen Hutchings <ben@decadent.org.uk>2024-03-21 23:28:39 +0100
commitd539458148cb998600b4596227cd52eb1ca930da (patch)
tree97276762d5e43d86ac64e18ddcc9a3c17aac6c53
parentd4821f1d5417be8d8ecb7eb90a0def34c384b5bd (diff)
downloadklibc-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.c30
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;
}