From 05efe6bde3a884d4fcca88a227efaeee2c7e3b8a Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Mon, 26 Oct 2026 23:25:21 +0100 Subject: Avoid an UB of adding NULL + 0 by keeping an offset instead of advancing the pointer into a vector struct --- tests/t_vector.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'tests') diff --git a/tests/t_vector.c b/tests/t_vector.c index 541a6da..6e048e1 100644 --- a/tests/t_vector.c +++ b/tests/t_vector.c @@ -112,6 +112,51 @@ static void case_insert_keeps_order(void) { free(vector.data); } +/* The peer variant is reached with an empty vector on every first announce + for a torrent, and again whenever a swarm empties and refills, because + vector_fixup_peers drops the allocation and nulls the data pointer. */ + +static void case_insert_peer_into_empty_vector(void) { + ot_vector vector = {NULL, 0, 0}; + ot_peer6 low, high; + int exactmatch; + ot_peer *slot; + + memset(low, 0x11, sizeof(low)); + memset(high, 0x99, sizeof(high)); + + test_case("the first peer goes into a vector that has no allocation yet"); + slot = vector_find_or_insert_peer(&vector, low, OT_PEER_SIZE6, &exactmatch); + CHECK(slot != NULL); + CHECK_INT(exactmatch, 0); + memcpy(slot, low, OT_PEER_SIZE6); + CHECK_INT(vector.size, 1); + CHECK_INT(vector.space, OT_VECTOR_MIN_MEMBERS); + CHECK_PTR(slot, vector.data); + + test_case("a second peer keeps the order"); + slot = vector_find_or_insert_peer(&vector, high, OT_PEER_SIZE6, &exactmatch); + CHECK(slot != NULL); + CHECK_INT(exactmatch, 0); + memcpy(slot, high, OT_PEER_SIZE6); + CHECK_INT(vector.size, 2); + CHECK_MEM((char *)vector.data, low, OT_PEER_COMPARE_SIZE6); + CHECK_MEM((char *)vector.data + OT_PEER_SIZE6, high, OT_PEER_COMPARE_SIZE6); + + test_case("and emptying the vector hands the allocation back"); + CHECK(vector_remove_peer(&vector, low, OT_PEER_SIZE6) != 0); + CHECK(vector_remove_peer(&vector, high, OT_PEER_SIZE6) != 0); + CHECK_INT(vector.size, 0); + CHECK_PTR(vector.data, NULL); + + test_case("so the next peer starts from no allocation again"); + slot = vector_find_or_insert_peer(&vector, low, OT_PEER_SIZE6, &exactmatch); + CHECK(slot != NULL); + CHECK_INT(vector.size, 1); + + free(vector.data); +} + static void case_insert_finds_existing(void) { ot_vector vector = {NULL, 0, 0}; const unsigned char five[4] = {0, 0, 0, 5}; @@ -257,6 +302,7 @@ void test_vector(void) { case_search_past_the_end(); case_search_empty(); case_insert_keeps_order(); + case_insert_peer_into_empty_vector(); case_insert_finds_existing(); case_insert_compare_prefix(); case_redistribute_holds_every_peer(); -- cgit v1.3