From 930c187c75dab8d4807f5df29e706c6433e36242 Mon Sep 17 00:00:00 2001 From: William Skellenger Date: Tue, 28 May 2024 18:42:59 -0400 Subject: [PATCH 1/7] added new ipv6 valid addr test --- test/unit/ip6/test_ip6.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/unit/ip6/test_ip6.c b/test/unit/ip6/test_ip6.c index a030ee5a..f9922aad 100644 --- a/test/unit/ip6/test_ip6.c +++ b/test/unit/ip6/test_ip6.c @@ -198,6 +198,8 @@ START_TEST(test_ip6_aton_ipv4mapped) const ip_addr_t addr_expected = IPADDR6_INIT_HOST(0, 0, 0xFFFF, 0xD4CC65D2); const char *full_ipv6_addr = "0:0:0:0:0:FFFF:D4CC:65D2"; const char *shortened_ipv6_addr = "::FFFF:D4CC:65D2"; + const char *shortened_ipv6_addr_unexpected_char = "::FFFF:D4CC:65DZ"; + const char *shortened_ipv6_addr_invalid = "::GGGGGGGG"; const char *full_ipv4_mapped_addr = "0:0:0:0:0:FFFF:212.204.101.210"; const char *shortened_ipv4_mapped_addr = "::FFFF:212.204.101.210"; const char *bogus_ipv4_mapped_addr = "::FFFF:212.204.101.2101"; @@ -223,6 +225,16 @@ START_TEST(test_ip6_aton_ipv4mapped) fail_unless(ret == 1); fail_unless(memcmp(&addr, &addr_expected, 16) == 0); + /* check shortened IPv6 with unexpected char */ + memset(&addr6, 0, sizeof(addr6)); + ret = ip6addr_aton(shortened_ipv6_addr_unexpected_char, &addr6); + fail_unless(ret == 0); + + /* check shortened IPv6 that is clearly invalid */ + memset(&addr6, 0, sizeof(addr6)); + ret = ip6addr_aton(shortened_ipv6_addr_invalid, &addr6); + fail_unless(ret == 0); + /* checked shortened mixed representation */ memset(&addr6, 0, sizeof(addr6)); ret = ip6addr_aton(shortened_ipv4_mapped_addr, &addr6); From edf2572e224a29eef96a2a7de09091314ce2983a Mon Sep 17 00:00:00 2001 From: William Skellenger Date: Tue, 28 May 2024 18:58:33 -0400 Subject: [PATCH 2/7] tests passing again --- src/core/ipv6/ip6_addr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ipv6/ip6_addr.c b/src/core/ipv6/ip6_addr.c index 6e0ac86b..f8e27987 100644 --- a/src/core/ipv6/ip6_addr.c +++ b/src/core/ipv6/ip6_addr.c @@ -96,7 +96,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) break; #endif /* LWIP_IPV4 */ } else if (!lwip_isxdigit(*s)) { - break; + return 0; } } @@ -166,7 +166,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) (u32_t)(10 + (lwip_islower(*s) ? *s - 'a' : *s - 'A'))); } else { /* unexpected digit, space? CRLF? */ - break; + return 0; } } From 5da7e95fa906675e6c22ea77b98c3624d95e65cf Mon Sep 17 00:00:00 2001 From: William Skellenger Date: Fri, 7 Jun 2024 13:40:15 -0400 Subject: [PATCH 3/7] block with five characters is now handled correctly --- src/core/ipv6/ip6_addr.c | 14 ++++++++++++++ test/unit/ip6/test_ip6.c | 11 ++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/core/ipv6/ip6_addr.c b/src/core/ipv6/ip6_addr.c index f8e27987..195623e2 100644 --- a/src/core/ipv6/ip6_addr.c +++ b/src/core/ipv6/ip6_addr.c @@ -73,6 +73,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) { u32_t addr_index, zero_blocks, current_block_index, current_block_value; const char *s; + int block_length; #if LWIP_IPV4 int check_ipv4_mapped = 0; #endif /* LWIP_IPV4 */ @@ -104,8 +105,12 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) addr_index = 0; current_block_index = 0; current_block_value = 0; + block_length = 0; for (s = cp; *s != 0; s++) { if (*s == ':') { + if (block_length > 4) { + return 0; //invalid block length + } if (addr) { if (current_block_index & 0x1) { addr->addr[addr_index++] |= current_block_value; @@ -132,6 +137,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) } #endif /* LWIP_IPV4 */ current_block_value = 0; + block_length = 0; if (current_block_index > 7) { /* address too long! */ return 0; @@ -160,6 +166,10 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) } } } else if (lwip_isxdigit(*s)) { + if (block_length == 4) { + return 0; //invalid block length + } + block_length++; /* add current digit */ current_block_value = (current_block_value << 4) + (lwip_isdigit(*s) ? (u32_t)(*s - '0') : @@ -170,6 +180,10 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) } } + if (block_length > 4) { + return 0; //invalid block length + } + if (addr) { if (current_block_index & 0x1) { addr->addr[addr_index++] |= current_block_value; diff --git a/test/unit/ip6/test_ip6.c b/test/unit/ip6/test_ip6.c index f9922aad..d5bb9e1c 100644 --- a/test/unit/ip6/test_ip6.c +++ b/test/unit/ip6/test_ip6.c @@ -203,7 +203,8 @@ START_TEST(test_ip6_aton_ipv4mapped) const char *full_ipv4_mapped_addr = "0:0:0:0:0:FFFF:212.204.101.210"; const char *shortened_ipv4_mapped_addr = "::FFFF:212.204.101.210"; const char *bogus_ipv4_mapped_addr = "::FFFF:212.204.101.2101"; - LWIP_UNUSED_ARG(_i); + const char *ipv6_block_too_long = "1234:5678:9aBc:acDef:1122:3344:5566:7788"; + LWIP_UNUSED_ARG(_i); /* check IPv6 representation */ memset(&addr6, 0, sizeof(addr6)); @@ -262,6 +263,14 @@ START_TEST(test_ip6_aton_ipv4mapped) memset(&addr, 0, sizeof(addr)); ret = ipaddr_aton(bogus_ipv4_mapped_addr, &addr); fail_unless(ret == 0); + + /* checking incorrect representation with a block containing 5 characters */ + memset(&addr6, 0, sizeof(addr6)); + ret = ip6addr_aton(ipv6_block_too_long, &addr6); + fail_unless(ret == 0); + memset(&addr, 0, sizeof(addr)); + ret = ipaddr_aton(ipv6_block_too_long, &addr); + fail_unless(ret == 0); } END_TEST From 2a292470815797c0f40e5047fa4fb7f3d05db070 Mon Sep 17 00:00:00 2001 From: William Skellenger Date: Fri, 7 Jun 2024 13:54:46 -0400 Subject: [PATCH 4/7] test passing --- test/unit/ip6/test_ip6.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unit/ip6/test_ip6.c b/test/unit/ip6/test_ip6.c index d5bb9e1c..14ae48bb 100644 --- a/test/unit/ip6/test_ip6.c +++ b/test/unit/ip6/test_ip6.c @@ -204,7 +204,8 @@ START_TEST(test_ip6_aton_ipv4mapped) const char *shortened_ipv4_mapped_addr = "::FFFF:212.204.101.210"; const char *bogus_ipv4_mapped_addr = "::FFFF:212.204.101.2101"; const char *ipv6_block_too_long = "1234:5678:9aBc:acDef:1122:3344:5566:7788"; - LWIP_UNUSED_ARG(_i); + + LWIP_UNUSED_ARG(_i); /* check IPv6 representation */ memset(&addr6, 0, sizeof(addr6)); From 748cd807c72d3c7456a565af6e3cc0eb0f849203 Mon Sep 17 00:00:00 2001 From: William Skellenger Date: Fri, 7 Jun 2024 15:40:31 -0400 Subject: [PATCH 5/7] more broken test cases for ipv6 --- src/core/ipv6/ip6_addr.c | 36 ++++++++++++++++++++++++++++++++---- test/unit/ip6/test_ip6.c | 27 ++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/core/ipv6/ip6_addr.c b/src/core/ipv6/ip6_addr.c index 195623e2..41eda387 100644 --- a/src/core/ipv6/ip6_addr.c +++ b/src/core/ipv6/ip6_addr.c @@ -57,6 +57,8 @@ /* used by IP6_ADDR_ANY(6) in ip6_addr.h */ const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul); +#define SMALLEST_POSSIBLE_IPV6_STRLEN 2 //"::" is the smallest possible + #define lwip_xchar(i) ((char)((i) < 10 ? '0' + (i) : 'A' + (i) - 10)) /** @@ -71,19 +73,40 @@ const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul); int ip6addr_aton(const char *cp, ip6_addr_t *addr) { - u32_t addr_index, zero_blocks, current_block_index, current_block_value; + u32_t addr_index, current_block_index, current_block_value, double_colon_found; + s32_t zero_blocks; + size_t len; const char *s; int block_length; #if LWIP_IPV4 int check_ipv4_mapped = 0; #endif /* LWIP_IPV4 */ + if (!cp) { + return 0; + } + + len = strlen(cp); + + if (len < SMALLEST_POSSIBLE_IPV6_STRLEN) { + return 0; + } + + //if last character is a colon but not a double colon, invalid + if ((cp[len-1] == ':') && (cp[len-2] != ':')) { + return 0; + } + /* Count the number of colons, to count the number of blocks in a "::" sequence zero_blocks may be 1 even if there are no :: sequences */ zero_blocks = 8; + double_colon_found = 0; for (s = cp; *s != 0; s++) { if (*s == ':') { zero_blocks--; + if (s[1] == ':') { + double_colon_found = 1; + } #if LWIP_IPV4 } else if (*s == '.') { if ((zero_blocks == 5) ||(zero_blocks == 2)) { @@ -101,6 +124,11 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) } } + /* we found a double colon but it is impossible to populate it */ + if (double_colon_found && zero_blocks <= 0) { + return 0; + } + /* parse each block */ addr_index = 0; current_block_index = 0; @@ -109,7 +137,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) for (s = cp; *s != 0; s++) { if (*s == ':') { if (block_length > 4) { - return 0; //invalid block length + return 0; /* invalid block length */ } if (addr) { if (current_block_index & 0x1) { @@ -167,7 +195,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) } } else if (lwip_isxdigit(*s)) { if (block_length == 4) { - return 0; //invalid block length + return 0; /* invalid block length */ } block_length++; /* add current digit */ @@ -181,7 +209,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) } if (block_length > 4) { - return 0; //invalid block length + return 0; /* invalid block length */ } if (addr) { diff --git a/test/unit/ip6/test_ip6.c b/test/unit/ip6/test_ip6.c index 14ae48bb..625b4a73 100644 --- a/test/unit/ip6/test_ip6.c +++ b/test/unit/ip6/test_ip6.c @@ -204,6 +204,10 @@ START_TEST(test_ip6_aton_ipv4mapped) const char *shortened_ipv4_mapped_addr = "::FFFF:212.204.101.210"; const char *bogus_ipv4_mapped_addr = "::FFFF:212.204.101.2101"; const char *ipv6_block_too_long = "1234:5678:9aBc:acDef:1122:3344:5566:7788"; + const char *ipv6_trailing_single_colon = "fE80::1:"; + const char *ipv6_impossible_compression1 = "1234:5678:9aBc::cDef:1122:3344:5566:7788"; + const char *ipv6_impossible_compression2 = "1234:5678:9aBc:cDef:1122:3344:5566:7788::"; + const char *ipv6_valid_compression = "fE80::1:1"; LWIP_UNUSED_ARG(_i); @@ -269,9 +273,26 @@ START_TEST(test_ip6_aton_ipv4mapped) memset(&addr6, 0, sizeof(addr6)); ret = ip6addr_aton(ipv6_block_too_long, &addr6); fail_unless(ret == 0); - memset(&addr, 0, sizeof(addr)); - ret = ipaddr_aton(ipv6_block_too_long, &addr); - fail_unless(ret == 0); + + /* trailing single colon, invalid */ + memset(&addr6, 0, sizeof(addr6)); + ret = ip6addr_aton(ipv6_trailing_single_colon, &addr6); + fail_unless(ret == 0) + + /* impossible to support compression, already enough blocks, invalid */ + memset(&addr6, 0, sizeof(addr6)); + ret = ip6addr_aton(ipv6_impossible_compression1, &addr6); + fail_unless(ret == 0) + + /* impossible to support compression at the end of the address, already enough blocks, invalid */ + memset(&addr6, 0, sizeof(addr6)); + ret = ip6addr_aton(ipv6_impossible_compression2, &addr6); + fail_unless(ret == 0) + + /* valid ipv6 with compression */ + memset(&addr6, 0, sizeof(addr6)); + ret = ip6addr_aton(ipv6_valid_compression, &addr6); + fail_unless(ret == 1) } END_TEST From 21c970c1b57a9c925871781948449dcf5386b53d Mon Sep 17 00:00:00 2001 From: William Skellenger Date: Fri, 7 Jun 2024 15:44:44 -0400 Subject: [PATCH 6/7] fix c++ comments --- src/core/ipv6/ip6_addr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ipv6/ip6_addr.c b/src/core/ipv6/ip6_addr.c index 41eda387..0ca18499 100644 --- a/src/core/ipv6/ip6_addr.c +++ b/src/core/ipv6/ip6_addr.c @@ -57,7 +57,7 @@ /* used by IP6_ADDR_ANY(6) in ip6_addr.h */ const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul); -#define SMALLEST_POSSIBLE_IPV6_STRLEN 2 //"::" is the smallest possible +#define SMALLEST_POSSIBLE_IPV6_STRLEN 2 /* "::" is the smallest possible ipv6 address */ #define lwip_xchar(i) ((char)((i) < 10 ? '0' + (i) : 'A' + (i) - 10)) @@ -92,7 +92,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) return 0; } - //if last character is a colon but not a double colon, invalid + /* if last character is a colon but not a double colon, invalid */ if ((cp[len-1] == ':') && (cp[len-2] != ':')) { return 0; } From 95c7c731c010c281239ca6102872a2f132c50ccb Mon Sep 17 00:00:00 2001 From: William Skellenger Date: Fri, 7 Jun 2024 16:00:09 -0400 Subject: [PATCH 7/7] fix typos, test runs --- test/unit/ip6/test_ip6.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/ip6/test_ip6.c b/test/unit/ip6/test_ip6.c index 625b4a73..ccafca96 100644 --- a/test/unit/ip6/test_ip6.c +++ b/test/unit/ip6/test_ip6.c @@ -277,22 +277,22 @@ START_TEST(test_ip6_aton_ipv4mapped) /* trailing single colon, invalid */ memset(&addr6, 0, sizeof(addr6)); ret = ip6addr_aton(ipv6_trailing_single_colon, &addr6); - fail_unless(ret == 0) + fail_unless(ret == 0); /* impossible to support compression, already enough blocks, invalid */ memset(&addr6, 0, sizeof(addr6)); ret = ip6addr_aton(ipv6_impossible_compression1, &addr6); - fail_unless(ret == 0) + fail_unless(ret == 0); /* impossible to support compression at the end of the address, already enough blocks, invalid */ memset(&addr6, 0, sizeof(addr6)); ret = ip6addr_aton(ipv6_impossible_compression2, &addr6); - fail_unless(ret == 0) + fail_unless(ret == 0); /* valid ipv6 with compression */ memset(&addr6, 0, sizeof(addr6)); ret = ip6addr_aton(ipv6_valid_compression, &addr6); - fail_unless(ret == 1) + fail_unless(ret == 1); } END_TEST