From 02daf25560e2b9978fa0666948614b286b71ca9b Mon Sep 17 00:00:00 2001 From: NoxToxCipher Date: Mon, 24 Aug 2026 21:42:08 +1000 Subject: [PATCH] fix(network): check buffer length before reading family in unpack_ip_port In unpack_ip_port, data[0] was accessed without verifying that length > 0, causing a potential 1-byte out-of-bounds read on 0-length input. Additionally, checked ip_port and data before dereferencing. In unpack_nodes, add an entry check verifying nodes is non-null when max_num_nodes > 0. Added boundary unit tests in auto_tests/network_test.c covering zero-length inputs, truncated IPv4/IPv6 buffers, and invalid address families. --- auto_tests/network_test.c | 30 ++++++++++++++++++++++++++++++ toxcore/DHT.c | 4 ++++ toxcore/network.c | 2 +- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/auto_tests/network_test.c b/auto_tests/network_test.c index 7079120dce..2c9a85e9cd 100644 --- a/auto_tests/network_test.c +++ b/auto_tests/network_test.c @@ -159,12 +159,42 @@ static void test_ip_equal(void) ck_assert_msg(res == 0, "ip_equal( {TOX_AF_INET6, ::1}, {TOX_AF_INET6, ::2} ): expected result 0, got %d.", res); } +static void test_unpack_ip_port_bounds(void) +{ + IP_Port ipp; + ipport_reset(&ipp); + + const uint8_t dummy_v4[7] = {TOX_AF_INET, 192, 168, 1, 1, 0x12, 0x34}; + ck_assert_int_eq(unpack_ip_port(&ipp, dummy_v4, 0, false), -1); + + for (uint16_t len = 1; len < (uint16_t)sizeof(dummy_v4); ++len) { + ck_assert_int_eq(unpack_ip_port(&ipp, dummy_v4, len, false), -1); + } + + ck_assert_int_eq(unpack_ip_port(&ipp, dummy_v4, sizeof(dummy_v4), false), (int)sizeof(dummy_v4)); + ck_assert(net_family_is_ipv4(ipp.ip.family)); + + uint8_t dummy_v6[19]; + memset(dummy_v6, 0, sizeof(dummy_v6)); + dummy_v6[0] = TOX_AF_INET6; + for (uint16_t len = 1; len < (uint16_t)sizeof(dummy_v6); ++len) { + ck_assert_int_eq(unpack_ip_port(&ipp, dummy_v6, len, false), -1); + } + + ck_assert_int_eq(unpack_ip_port(&ipp, dummy_v6, sizeof(dummy_v6), false), (int)sizeof(dummy_v6)); + ck_assert(net_family_is_ipv6(ipp.ip.family)); + + const uint8_t invalid_family[7] = {0xFF, 1, 2, 3, 4, 5, 6}; + ck_assert_int_eq(unpack_ip_port(&ipp, invalid_family, sizeof(invalid_family), false), -1); +} + int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); test_addr_resolv_localhost(); test_ip_equal(); + test_unpack_ip_port_bounds(); return 0; } diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 5a4228533f..a1983106c9 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -429,6 +429,10 @@ int pack_nodes(const Logger *logger, uint8_t *data, uint16_t length, const Node_ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data, uint16_t length, bool tcp_enabled) { + if (nodes == nullptr && max_num_nodes > 0) { + return -1; + } + uint32_t num = 0; uint32_t len_processed = 0; diff --git a/toxcore/network.c b/toxcore/network.c index 7950c51007..6cd977d56f 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -804,7 +804,7 @@ int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_ int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool tcp_enabled) { - if (data == nullptr) { + if (data == nullptr || length == 0 || ip_port == nullptr) { return -1; }