From 6cbd810206a3a5c7bd5f959267cdb8fbfffa2f1e Mon Sep 17 00:00:00 2001 From: "Sergio R. Caprile" Date: Tue, 28 Jul 2026 14:36:40 -0300 Subject: [PATCH] improve mg_aton6 and tests --- mongoose.c | 31 +++++++++++++++++++++---------- src/net.c | 31 +++++++++++++++++++++---------- test/unit_test.c | 7 +++++++ 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/mongoose.c b/mongoose.c index 01627d18..603758a7 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7883,22 +7883,31 @@ static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) { static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { size_t i, j = 0, n = 0, dc = 42; + uint16_t val = 0; + bool have = false; addr->scope_id = 0; if (str.len > 2 && str.buf[0] == '[') str.buf++, str.len -= 2; if (mg_v4mapped(str, addr)) return true; // sets addr->is_ip6 for (i = 0; i < str.len; i++) { - if ((str.buf[i] >= '0' && str.buf[i] <= '9') || - (str.buf[i] >= 'a' && str.buf[i] <= 'f') || - (str.buf[i] >= 'A' && str.buf[i] <= 'F')) { - unsigned long val = 0; // TODO(): This loops on chars, refactor + int x = str.buf[i] >= '0' && str.buf[i] <= '9' ? str.buf[i] - '0' + : str.buf[i] >= 'a' && str.buf[i] <= 'f' ? str.buf[i] - 'a' + 10 + : str.buf[i] >= 'A' && str.buf[i] <= 'F' ? str.buf[i] - 'A' + 10 + : -1; + if (x >= 0) { if (i > j + 3) return false; - // MG_DEBUG(("%lu %lu [%.*s]", i, j, (int) (i - j + 1), &str.buf[j])); - mg_str_to_num(mg_str_n(&str.buf[j], i - j + 1), 16, &val, sizeof(val)); - addr->addr.ip[n] = (uint8_t) ((val >> 8) & 255); - addr->addr.ip[n + 1] = (uint8_t) (val & 255); - } else if (str.buf[i] == ':') { + val = (uint16_t) ((val << 4) | (uint16_t) x); + have = true; + continue; + } + if (have) { + addr->addr.ip[n] = (uint8_t) (val >> 8), + addr->addr.ip[n + 1] = (uint8_t) val; + val = 0, have = false; + } + if (str.buf[i] == ':') { j = i + 1; if (i > 0 && str.buf[i - 1] == ':') { + if (dc != 42) return false; dc = n; // Double colon if (i > 1 && str.buf[i - 2] == ':') return false; } else if (i > 0) { @@ -7918,12 +7927,14 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { return false; } } + if (have) + addr->addr.ip[n] = (uint8_t) (val >> 8), + addr->addr.ip[n + 1] = (uint8_t) val; if (n < 14 && dc == 42) return false; if (n < 14) { memmove(&addr->addr.ip[dc + (14 - n)], &addr->addr.ip[dc], n - dc + 2); memset(&addr->addr.ip[dc], 0, 14 - n); } - addr->is_ip6 = true; return true; } diff --git a/src/net.c b/src/net.c index c2dd53b5..4211d4b3 100644 --- a/src/net.c +++ b/src/net.c @@ -85,22 +85,31 @@ static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) { static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { size_t i, j = 0, n = 0, dc = 42; + uint16_t val = 0; + bool have = false; addr->scope_id = 0; if (str.len > 2 && str.buf[0] == '[') str.buf++, str.len -= 2; if (mg_v4mapped(str, addr)) return true; // sets addr->is_ip6 for (i = 0; i < str.len; i++) { - if ((str.buf[i] >= '0' && str.buf[i] <= '9') || - (str.buf[i] >= 'a' && str.buf[i] <= 'f') || - (str.buf[i] >= 'A' && str.buf[i] <= 'F')) { - unsigned long val = 0; // TODO(): This loops on chars, refactor + int x = str.buf[i] >= '0' && str.buf[i] <= '9' ? str.buf[i] - '0' + : str.buf[i] >= 'a' && str.buf[i] <= 'f' ? str.buf[i] - 'a' + 10 + : str.buf[i] >= 'A' && str.buf[i] <= 'F' ? str.buf[i] - 'A' + 10 + : -1; + if (x >= 0) { if (i > j + 3) return false; - // MG_DEBUG(("%lu %lu [%.*s]", i, j, (int) (i - j + 1), &str.buf[j])); - mg_str_to_num(mg_str_n(&str.buf[j], i - j + 1), 16, &val, sizeof(val)); - addr->addr.ip[n] = (uint8_t) ((val >> 8) & 255); - addr->addr.ip[n + 1] = (uint8_t) (val & 255); - } else if (str.buf[i] == ':') { + val = (uint16_t) ((val << 4) | (uint16_t) x); + have = true; + continue; + } + if (have) { + addr->addr.ip[n] = (uint8_t) (val >> 8), + addr->addr.ip[n + 1] = (uint8_t) val; + val = 0, have = false; + } + if (str.buf[i] == ':') { j = i + 1; if (i > 0 && str.buf[i - 1] == ':') { + if (dc != 42) return false; dc = n; // Double colon if (i > 1 && str.buf[i - 2] == ':') return false; } else if (i > 0) { @@ -120,12 +129,14 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { return false; } } + if (have) + addr->addr.ip[n] = (uint8_t) (val >> 8), + addr->addr.ip[n + 1] = (uint8_t) val; if (n < 14 && dc == 42) return false; if (n < 14) { memmove(&addr->addr.ip[dc + (14 - n)], &addr->addr.ip[dc], n - dc + 2); memset(&addr->addr.ip[dc], 0, 14 - n); } - addr->is_ip6 = true; return true; } diff --git a/test/unit_test.c b/test/unit_test.c index e8af21f7..f35ccae9 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -2855,6 +2855,13 @@ static void test_util(void) { e = "\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00\x88\x88"; ASSERT(memcmp(&a.addr.ip6, e, sizeof(a.addr.ip6)) == 0); + ASSERT(mg_aton(mg_str("12345::1"), &a) == false); + ASSERT(mg_aton(mg_str("1:::2"), &a) == false); + ASSERT(mg_aton(mg_str("1::2::3"), &a) == false); + ASSERT(mg_aton(mg_str("1:2:3:4:5:6:7"), &a) == false); + ASSERT(mg_aton(mg_str("1:2:3:4:5:6:7:8:9"), &a) == false); + ASSERT(mg_aton(mg_str("1:2:3:4:5:6:7:g"), &a) == false); + ASSERT(mg_url_decode("a=%", 3, buf, sizeof(buf), 0) < 0); ASSERT(mg_url_decode("&&&a=%", 6, buf, sizeof(buf), 0) < 0); ASSERT(mg_url_decode("a=%1", 4, buf, sizeof(buf), 0) < 0);