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