summaryrefslogtreecommitdiff
path: root/tests/t_vector.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-26 23:25:21 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-10-26 23:25:21 +0100
commit05efe6bde3a884d4fcca88a227efaeee2c7e3b8a (patch)
treed17e4a5020a044e54e8e5e8202b1f475e75853bb /tests/t_vector.c
parent687ef7fece04fb5dffa90b5d784fb1e34066c85a (diff)
Avoid an UB of adding NULL + 0 by keeping an offset instead of advancing the pointer into a vector struct
Diffstat (limited to 'tests/t_vector.c')
-rw-r--r--tests/t_vector.c46
1 files changed, 46 insertions, 0 deletions
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) {
112 free(vector.data); 112 free(vector.data);
113} 113}
114 114
115/* The peer variant is reached with an empty vector on every first announce
116 for a torrent, and again whenever a swarm empties and refills, because
117 vector_fixup_peers drops the allocation and nulls the data pointer. */
118
119static void case_insert_peer_into_empty_vector(void) {
120 ot_vector vector = {NULL, 0, 0};
121 ot_peer6 low, high;
122 int exactmatch;
123 ot_peer *slot;
124
125 memset(low, 0x11, sizeof(low));
126 memset(high, 0x99, sizeof(high));
127
128 test_case("the first peer goes into a vector that has no allocation yet");
129 slot = vector_find_or_insert_peer(&vector, low, OT_PEER_SIZE6, &exactmatch);
130 CHECK(slot != NULL);
131 CHECK_INT(exactmatch, 0);
132 memcpy(slot, low, OT_PEER_SIZE6);
133 CHECK_INT(vector.size, 1);
134 CHECK_INT(vector.space, OT_VECTOR_MIN_MEMBERS);
135 CHECK_PTR(slot, vector.data);
136
137 test_case("a second peer keeps the order");
138 slot = vector_find_or_insert_peer(&vector, high, OT_PEER_SIZE6, &exactmatch);
139 CHECK(slot != NULL);
140 CHECK_INT(exactmatch, 0);
141 memcpy(slot, high, OT_PEER_SIZE6);
142 CHECK_INT(vector.size, 2);
143 CHECK_MEM((char *)vector.data, low, OT_PEER_COMPARE_SIZE6);
144 CHECK_MEM((char *)vector.data + OT_PEER_SIZE6, high, OT_PEER_COMPARE_SIZE6);
145
146 test_case("and emptying the vector hands the allocation back");
147 CHECK(vector_remove_peer(&vector, low, OT_PEER_SIZE6) != 0);
148 CHECK(vector_remove_peer(&vector, high, OT_PEER_SIZE6) != 0);
149 CHECK_INT(vector.size, 0);
150 CHECK_PTR(vector.data, NULL);
151
152 test_case("so the next peer starts from no allocation again");
153 slot = vector_find_or_insert_peer(&vector, low, OT_PEER_SIZE6, &exactmatch);
154 CHECK(slot != NULL);
155 CHECK_INT(vector.size, 1);
156
157 free(vector.data);
158}
159
115static void case_insert_finds_existing(void) { 160static void case_insert_finds_existing(void) {
116 ot_vector vector = {NULL, 0, 0}; 161 ot_vector vector = {NULL, 0, 0};
117 const unsigned char five[4] = {0, 0, 0, 5}; 162 const unsigned char five[4] = {0, 0, 0, 5};
@@ -257,6 +302,7 @@ void test_vector(void) {
257 case_search_past_the_end(); 302 case_search_past_the_end();
258 case_search_empty(); 303 case_search_empty();
259 case_insert_keeps_order(); 304 case_insert_keeps_order();
305 case_insert_peer_into_empty_vector();
260 case_insert_finds_existing(); 306 case_insert_finds_existing();
261 case_insert_compare_prefix(); 307 case_insert_compare_prefix();
262 case_redistribute_holds_every_peer(); 308 case_redistribute_holds_every_peer();