From f98ca529d4573591b4826866940f8fd29dac936e Mon Sep 17 00:00:00 2001 From: Sergey Fionov Date: Sat, 27 Apr 2024 08:53:05 +0300 Subject: [PATCH 1/2] Add test for out-of-bound access in ip6addr_ntoa_r() --- test/unit/ip6/test_ip6.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/unit/ip6/test_ip6.c b/test/unit/ip6/test_ip6.c index a030ee5a..abd87910 100644 --- a/test/unit/ip6/test_ip6.c +++ b/test/unit/ip6/test_ip6.c @@ -268,15 +268,18 @@ END_TEST struct test_addr_and_str { ip_addr_t addr; + u32_t bytes_after; const char *str; }; START_TEST(test_ip6_ntoa) { struct test_addr_and_str tests[] = { - {IPADDR6_INIT_HOST(0xfe800000, 0x00000000, 0xb2a1a2ff, 0xfea3a4a5), "FE80::B2A1:A2FF:FEA3:A4A5"}, /* test shortened zeros */ - {IPADDR6_INIT_HOST(0xfe800000, 0xff000000, 0xb2a1a2ff, 0xfea3a4a5), "FE80:0:FF00:0:B2A1:A2FF:FEA3:A4A5"}, /* don't omit single zero blocks */ - {IPADDR6_INIT_HOST(0xfe800000, 0xff000000, 0xb2000000, 0x0000a4a5), "FE80:0:FF00:0:B200::A4A5"}, /* omit longest zero block */ + {IPADDR6_INIT_HOST(0xfe800000, 0x00000000, 0xb2a1a2ff, 0xfea3a4a5), 0, "FE80::B2A1:A2FF:FEA3:A4A5"}, /* test shortened zeros */ + {IPADDR6_INIT_HOST(0xfe800000, 0xff000000, 0xb2a1a2ff, 0xfea3a4a5), 0, "FE80:0:FF00:0:B2A1:A2FF:FEA3:A4A5"}, /* don't omit single zero blocks */ + {IPADDR6_INIT_HOST(0xfe800000, 0xff000000, 0xb2000000, 0x0000a4a5), 0, "FE80:0:FF00:0:B200::A4A5"}, /* omit longest zero block */ + {IPADDR6_INIT_HOST(0x20010db8, 0x00010002, 0x00030004, 0x00050000), 0, "2001:DB8:1:2:3:4:5:0"}, /* do not omit last zero due to out-of-bounds bug */ + {IPADDR6_INIT_HOST(0x20010db8, 0x00010002, 0x00030004, 0x00050000), ~0, "2001:DB8:1:2:3:4:5:0"}, /* do not omit last zero due to out-of-bounds bug */ }; char buf[128]; char *str; From 80e2be17ad32308c2c2eb283ccc8bb04bd38d39c Mon Sep 17 00:00:00 2001 From: Sergey Fionov Date: Sat, 27 Apr 2024 08:51:54 +0300 Subject: [PATCH 2/2] Fix out-of-bound access in ip6addr_ntoa_r() When detecting that zero is single, code reads the next group even if current group is last group. If next bytes are not-null, last zero is not omitted. If next bytes are null, last zero is omitted, but since there are no groups left, finishing ':' will not be written, resulting in invalid address. This commit turns off non-single zero check for the last group. --- src/core/ipv6/ip6_addr.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/core/ipv6/ip6_addr.c b/src/core/ipv6/ip6_addr.c index 6e0ac86b..48e0d639 100644 --- a/src/core/ipv6/ip6_addr.c +++ b/src/core/ipv6/ip6_addr.c @@ -270,15 +270,16 @@ ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) /* Check for empty block. */ if (current_block_value == 0) { - if (current_block_index == 7 && empty_block_flag == 1) { - /* special case, we must render a ':' for the last block. */ - buf[i++] = ':'; - if (i >= buflen) { - return NULL; + if (current_block_index == 7) { + if (empty_block_flag == 1) { + /* special case, we must render a ':' for the last block. */ + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + break; } - break; - } - if (empty_block_flag == 0) { + } else if (empty_block_flag == 0) { /* generate empty block "::", but only if more than one contiguous zero block, * according to current formatting suggestions RFC 5952. */ next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]);