Home | History | Annotate | Line # | Download | only in isc
dnsstream_utils_test.c revision 1.2
      1 /*	$NetBSD: dnsstream_utils_test.c,v 1.2 2025/01/26 16:25:49 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 #include <inttypes.h>
     17 #include <sched.h> /* IWYU pragma: keep */
     18 #include <setjmp.h>
     19 #include <stdarg.h>
     20 #include <stdbool.h>
     21 #include <stddef.h>
     22 #include <stdlib.h>
     23 #include <time.h>
     24 #include <unistd.h>
     25 
     26 #define UNIT_TESTING
     27 #include <cmocka.h>
     28 
     29 #include <isc/buffer.h>
     30 #include <isc/dnsstream.h>
     31 #include <isc/mem.h>
     32 #include <isc/os.h>
     33 #include <isc/random.h>
     34 
     35 #include "dnsstream_utils_test_data.h"
     36 
     37 #include <tests/isc.h>
     38 
     39 #define STATIC_BUFFER_SIZE  (512)
     40 #define DYNAMIC_BUFFER_SIZE (STATIC_BUFFER_SIZE + ISC_BUFFER_INCR)
     41 
     42 static int
     43 setup_test_dnsbuf(void **state) {
     44 	isc_buffer_t **pdnsbuf = (isc_buffer_t **)state;
     45 	isc_buffer_allocate(mctx, pdnsbuf, STATIC_BUFFER_SIZE);
     46 
     47 	return 0;
     48 }
     49 
     50 static int
     51 teardown_test_dnsbuf(void **state) {
     52 	isc_buffer_free((isc_buffer_t **)state);
     53 
     54 	return 0;
     55 }
     56 
     57 static bool
     58 dnsasm_dummy(isc_dnsstream_assembler_t *dnsasm, const isc_result_t result,
     59 	     isc_region_t *restrict region, void *cbarg, void *userarg) {
     60 	UNUSED(dnsasm);
     61 	UNUSED(result);
     62 	UNUSED(region);
     63 	UNUSED(cbarg);
     64 	UNUSED(userarg);
     65 	return true;
     66 }
     67 
     68 static int
     69 setup_test_dnsasm(void **state) {
     70 	isc_dnsstream_assembler_t **pdnsasm =
     71 		(isc_dnsstream_assembler_t **)state;
     72 	*pdnsasm = isc_dnsstream_assembler_new(mctx, dnsasm_dummy, NULL);
     73 
     74 	return 0;
     75 }
     76 
     77 static int
     78 teardown_test_dnsasm(void **state) {
     79 	isc_dnsstream_assembler_free((isc_dnsstream_assembler_t **)state);
     80 
     81 	return 0;
     82 }
     83 
     84 ISC_RUN_TEST_IMPL(dnsbuffer_generic_test) {
     85 	uint8_t buf[STATIC_BUFFER_SIZE / 2] = { 0 };
     86 	isc_buffer_t *dnsbuf = (isc_buffer_t *)*state;
     87 	isc_region_t reg = { 0 };
     88 	size_t n = 0;
     89 
     90 	for (size_t i = 0; i < sizeof(buf); i++) {
     91 		buf[i] = (uint8_t)i;
     92 	}
     93 
     94 	/* sanity checks */
     95 	assert_true(isc_buffer_length(dnsbuf) == STATIC_BUFFER_SIZE);
     96 	assert_true(isc_buffer_usedlength(dnsbuf) == 0);
     97 	assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
     98 
     99 	isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
    100 
    101 	assert_true(isc_buffer_usedlength(dnsbuf) == sizeof(buf));
    102 	assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(buf));
    103 
    104 	assert_true(isc_buffer_current(dnsbuf) == dnsbuf->base);
    105 
    106 	isc_buffer_clear(dnsbuf);
    107 
    108 	assert_true(isc_buffer_length(dnsbuf) == STATIC_BUFFER_SIZE);
    109 	assert_true(isc_buffer_usedlength(dnsbuf) == 0);
    110 	assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
    111 
    112 	isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
    113 
    114 	assert_true(isc_buffer_usedlength(dnsbuf) == sizeof(buf));
    115 	assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(buf));
    116 
    117 	assert_true(isc_buffer_current(dnsbuf) == dnsbuf->base);
    118 
    119 	for (size_t i = 0; i < sizeof(buf); i++, isc_buffer_forward(dnsbuf, 1))
    120 	{
    121 		uint8_t *p = isc_buffer_current(dnsbuf);
    122 
    123 		assert_true(*p == i);
    124 	}
    125 
    126 	assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
    127 	assert_true(isc_buffer_usedlength(dnsbuf) == sizeof(buf));
    128 
    129 	isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
    130 
    131 	assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(buf));
    132 	assert_true(isc_buffer_usedlength(dnsbuf) == sizeof(buf) * 2);
    133 
    134 	assert_true(isc_buffer_length(dnsbuf) == STATIC_BUFFER_SIZE);
    135 
    136 	for (size_t i = 0; i < sizeof(buf); i++, isc_buffer_forward(dnsbuf, 1))
    137 	{
    138 		uint8_t *p = isc_buffer_current(dnsbuf);
    139 
    140 		assert_true(*p == i);
    141 	}
    142 
    143 	isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
    144 
    145 	assert_true(isc_buffer_length(dnsbuf) == DYNAMIC_BUFFER_SIZE);
    146 
    147 	for (size_t i = 0; i < sizeof(buf); i++, isc_buffer_forward(dnsbuf, 1))
    148 	{
    149 		uint8_t *p = isc_buffer_current(dnsbuf);
    150 
    151 		assert_true(*p == i);
    152 	}
    153 
    154 	assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
    155 	isc_buffer_trycompact(dnsbuf);
    156 
    157 	assert_true(isc_buffer_length(dnsbuf) == DYNAMIC_BUFFER_SIZE);
    158 
    159 	isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
    160 
    161 	isc_buffer_remainingregion(dnsbuf, &reg);
    162 	assert_true(isc_buffer_remaininglength(dnsbuf) == reg.length);
    163 	assert_true(reg.length == sizeof(buf));
    164 
    165 	for (size_t i = 0; i < reg.length; i++) {
    166 		uint8_t d = (uint8_t)reg.base[i];
    167 
    168 		assert_true(d == i);
    169 	}
    170 
    171 	isc_buffer_forward(dnsbuf, reg.length);
    172 	assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
    173 
    174 	isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
    175 	assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(buf));
    176 
    177 	isc_buffer_clear(dnsbuf);
    178 
    179 	assert_true(isc_buffer_length(dnsbuf) == DYNAMIC_BUFFER_SIZE);
    180 
    181 	assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
    182 
    183 	n = DYNAMIC_BUFFER_SIZE / sizeof(buf) + 1;
    184 	for (size_t i = 0; i < n; i++) {
    185 		isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
    186 	}
    187 
    188 	assert_true(isc_buffer_length(dnsbuf) > DYNAMIC_BUFFER_SIZE);
    189 	assert_true(isc_buffer_length(dnsbuf) >= n * sizeof(buf));
    190 
    191 	assert_true(isc_buffer_remaininglength(dnsbuf) == n * sizeof(buf));
    192 
    193 	for (size_t i = 0; i < n; i++) {
    194 		for (size_t k = 0; k < sizeof(buf);
    195 		     k++, isc_buffer_forward(dnsbuf, 1))
    196 		{
    197 			uint8_t *p = isc_buffer_current(dnsbuf);
    198 
    199 			assert_true(*p == k);
    200 		}
    201 	}
    202 }
    203 
    204 ISC_RUN_TEST_IMPL(dnsbuffer_resize_alloc_test) {
    205 	uint8_t buf[STATIC_BUFFER_SIZE / 2] = { 0 };
    206 	isc_buffer_t *dnsbuf = (isc_buffer_t *)*state;
    207 	size_t i = 0, n = 0;
    208 
    209 	for (i = 0; i < sizeof(buf); i++) {
    210 		buf[i] = (uint8_t)i;
    211 	}
    212 
    213 	isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
    214 
    215 	for (i = 0; i < (sizeof(buf) / 3) * 2;
    216 	     i++, isc_buffer_forward(dnsbuf, 1))
    217 	{
    218 		uint8_t *p = isc_buffer_current(dnsbuf);
    219 
    220 		assert_true(*p == i);
    221 	}
    222 
    223 	assert_true(isc_buffer_length(dnsbuf) == STATIC_BUFFER_SIZE);
    224 
    225 	n = DYNAMIC_BUFFER_SIZE / sizeof(buf) + 1;
    226 	for (size_t k = 0; k < n; k++) {
    227 		isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
    228 	}
    229 
    230 	assert_true(isc_buffer_length(dnsbuf) >= STATIC_BUFFER_SIZE);
    231 
    232 	for (; i < sizeof(buf); i++, isc_buffer_forward(dnsbuf, 1)) {
    233 		uint8_t *p = isc_buffer_current(dnsbuf);
    234 
    235 		assert_true(*p == i);
    236 	}
    237 }
    238 
    239 ISC_RUN_TEST_IMPL(dnsbuffer_be_test) {
    240 	isc_buffer_t *dnsbuf = (isc_buffer_t *)*state;
    241 	const uint16_t u16 = 0xBEEF;
    242 	uint16_t *pu16;
    243 	uint16_t u16v;
    244 
    245 	assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
    246 
    247 	isc_buffer_putuint16(dnsbuf, u16);
    248 
    249 	assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(u16));
    250 
    251 	pu16 = (uint16_t *)isc_buffer_current(dnsbuf);
    252 	assert_true(*pu16 == htons(u16));
    253 
    254 	assert_int_equal(isc_buffer_peekuint16(dnsbuf, &u16v), ISC_R_SUCCESS);
    255 	assert_int_equal(u16v, u16);
    256 	assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(u16));
    257 
    258 	assert_true(isc_buffer_getuint16(dnsbuf) == u16);
    259 	assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
    260 }
    261 
    262 typedef struct verify_cbdata {
    263 	uint8_t *verify_message;
    264 	bool cont_on_success;
    265 	bool clear_on_success;
    266 } verify_cbdata_t;
    267 
    268 static bool
    269 verify_dnsmsg(isc_dnsstream_assembler_t *dnsasm, const isc_result_t result,
    270 	      isc_region_t *restrict region, void *cbarg, void *userarg) {
    271 	size_t *processed = (size_t *)userarg;
    272 	verify_cbdata_t *vdata = (verify_cbdata_t *)cbarg;
    273 	uint8_t *message = (uint8_t *)vdata->verify_message;
    274 
    275 	UNUSED(dnsasm);
    276 
    277 	assert_true(result == isc_dnsstream_assembler_result(dnsasm));
    278 
    279 	if (vdata->verify_message != NULL) {
    280 		message += sizeof(uint16_t);
    281 	}
    282 
    283 	if (result != ISC_R_SUCCESS) {
    284 		return true;
    285 	}
    286 
    287 	if (vdata->verify_message != NULL &&
    288 	    memcmp(message, region->base, region->length) == 0)
    289 	{
    290 		*processed += 1;
    291 	} else {
    292 		*processed += 1;
    293 	}
    294 
    295 	if (vdata->clear_on_success) {
    296 		isc_dnsstream_assembler_clear(
    297 			(isc_dnsstream_assembler_t *)dnsasm);
    298 	}
    299 
    300 	return vdata->cont_on_success;
    301 }
    302 
    303 typedef struct verify_regions_cbdata {
    304 	isc_region_t *packets;
    305 	bool cont_on_success;
    306 } verify_regions_cbdata_t;
    307 
    308 static bool
    309 verify_dnsmsg_regions(isc_dnsstream_assembler_t *dnsasm,
    310 		      const isc_result_t result, isc_region_t *restrict region,
    311 		      void *cbarg, void *userarg) {
    312 	size_t *processed = (size_t *)userarg;
    313 	verify_regions_cbdata_t *vdata = (verify_regions_cbdata_t *)cbarg;
    314 	uint8_t *message = (uint8_t *)vdata->packets[0].base;
    315 
    316 	UNUSED(dnsasm);
    317 
    318 	assert_true(result == isc_dnsstream_assembler_result(dnsasm));
    319 
    320 	if (vdata->packets != NULL) {
    321 		message += sizeof(uint16_t);
    322 	}
    323 
    324 	if (result != ISC_R_SUCCESS) {
    325 		return true;
    326 	}
    327 
    328 	if (vdata->packets != NULL &&
    329 	    memcmp(message, region->base, region->length) == 0)
    330 	{
    331 		*processed += 1;
    332 	} else {
    333 		*processed += 1;
    334 	}
    335 
    336 	vdata->packets++;
    337 
    338 	return vdata->cont_on_success;
    339 }
    340 
    341 ISC_RUN_TEST_IMPL(dnsasm_sequence_test) {
    342 	isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
    343 	verify_cbdata_t cbdata = { 0 };
    344 	size_t verified = 0;
    345 
    346 	cbdata.cont_on_success = true;
    347 
    348 	cbdata.verify_message = (uint8_t *)request;
    349 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
    350 	isc_dnsstream_assembler_incoming(dnsasm, &verified, (void *)request,
    351 					 sizeof(request));
    352 	assert_true(verified == 1);
    353 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    354 
    355 	cbdata.verify_message = (uint8_t *)response;
    356 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
    357 	isc_dnsstream_assembler_incoming(dnsasm, &verified, (void *)response,
    358 					 sizeof(response));
    359 	assert_true(verified == 2);
    360 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    361 
    362 	cbdata.verify_message = (uint8_t *)request_large;
    363 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
    364 	isc_dnsstream_assembler_incoming(dnsasm, &verified,
    365 					 (void *)request_large,
    366 					 sizeof(request_large));
    367 	assert_true(verified == 3);
    368 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    369 
    370 	cbdata.verify_message = (uint8_t *)response_large;
    371 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
    372 	isc_dnsstream_assembler_incoming(dnsasm, &verified,
    373 					 (void *)response_large,
    374 					 sizeof(response_large));
    375 	assert_true(verified == 4);
    376 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    377 }
    378 
    379 ISC_RUN_TEST_IMPL(dnsasm_multiple_messages_test) {
    380 	isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
    381 	isc_buffer_t dnsbuf;
    382 	verify_cbdata_t cbdata = { 0 };
    383 	size_t verified = 0;
    384 
    385 	isc_buffer_init(&dnsbuf, NULL, 0);
    386 	isc_buffer_setmctx(&dnsbuf, mctx);
    387 	isc_buffer_putmem(&dnsbuf, (void *)request, sizeof(request));
    388 	isc_buffer_putmem(&dnsbuf, (void *)response, sizeof(response));
    389 	isc_buffer_putmem(&dnsbuf, (void *)request_large,
    390 			  sizeof(request_large));
    391 	isc_buffer_putmem(&dnsbuf, (void *)response_large,
    392 			  sizeof(response_large));
    393 
    394 	cbdata.cont_on_success = false;
    395 
    396 	/*
    397 	 * feed the data to the message assembler and handle the first message
    398 	 */
    399 	cbdata.verify_message = (uint8_t *)request;
    400 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
    401 	isc_dnsstream_assembler_incoming(dnsasm, &verified,
    402 					 isc_buffer_current(&dnsbuf),
    403 					 isc_buffer_remaininglength(&dnsbuf));
    404 
    405 	isc_buffer_clearmctx(&dnsbuf);
    406 	isc_buffer_invalidate(&dnsbuf);
    407 	assert_true(verified == 1);
    408 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    409 
    410 	/*
    411 	 * handle the next message (and so on)
    412 	 */
    413 	cbdata.verify_message = (uint8_t *)response;
    414 	isc_dnsstream_assembler_incoming(dnsasm, &verified, NULL, 0);
    415 	assert_true(verified == 2);
    416 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    417 
    418 	cbdata.verify_message = (uint8_t *)request_large;
    419 	isc_dnsstream_assembler_incoming(dnsasm, &verified, NULL, 0);
    420 	assert_true(verified == 3);
    421 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    422 
    423 	cbdata.verify_message = (uint8_t *)response_large;
    424 	isc_dnsstream_assembler_incoming(dnsasm, &verified, NULL, 0);
    425 	assert_true(verified == 4);
    426 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    427 
    428 	/*
    429 	 * no unprocessed data left
    430 	 */
    431 	isc_dnsstream_assembler_incoming(dnsasm, &verified, NULL, 0);
    432 	assert_true(verified == 4);
    433 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_NOMORE);
    434 }
    435 
    436 ISC_RUN_TEST_IMPL(dnsasm_torn_apart_test) {
    437 	isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
    438 	verify_cbdata_t cbdata = { 0 };
    439 	size_t verified = 0;
    440 	size_t left = 0;
    441 
    442 	cbdata.verify_message = (uint8_t *)response_large;
    443 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
    444 	isc_dnsstream_assembler_incoming(dnsasm, &verified, response_large,
    445 					 sizeof(response_large) / 3 * 2);
    446 
    447 	assert_true(verified == 0);
    448 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_NOMORE);
    449 
    450 	left = sizeof(response_large) -
    451 	       isc_dnsstream_assembler_remaininglength(dnsasm);
    452 	isc_dnsstream_assembler_incoming(
    453 		dnsasm, &verified,
    454 		&response_large[isc_dnsstream_assembler_remaininglength(dnsasm)],
    455 		left);
    456 	assert_true(verified == 1);
    457 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    458 }
    459 
    460 ISC_RUN_TEST_IMPL(dnsasm_error_data_test) {
    461 	isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
    462 	verify_cbdata_t cbdata = { 0 };
    463 	size_t verified = 0;
    464 	isc_buffer_t dnsbuf;
    465 	uint16_t bad_data = 0;
    466 
    467 	isc_buffer_init(&dnsbuf, NULL, 0);
    468 	isc_buffer_setmctx(&dnsbuf, mctx);
    469 
    470 	isc_buffer_putmem(&dnsbuf, (void *)request, sizeof(request));
    471 	isc_buffer_putmem(&dnsbuf, (void *)&bad_data, sizeof(bad_data));
    472 	isc_buffer_putmem(&dnsbuf, (void *)&bad_data, sizeof(bad_data));
    473 	isc_buffer_putmem(&dnsbuf, (void *)response_large,
    474 			  sizeof(response_large));
    475 
    476 	cbdata.cont_on_success = false;
    477 
    478 	cbdata.verify_message = (uint8_t *)request;
    479 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
    480 	isc_dnsstream_assembler_incoming(dnsasm, &verified,
    481 					 isc_buffer_current(&dnsbuf),
    482 					 isc_buffer_remaininglength(&dnsbuf));
    483 
    484 	isc_buffer_clearmctx(&dnsbuf);
    485 	isc_buffer_invalidate(&dnsbuf);
    486 
    487 	assert_true(verified == 1);
    488 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
    489 
    490 	assert_true(isc_dnsstream_assembler_remaininglength(dnsasm) > 0);
    491 	isc_dnsstream_assembler_incoming(dnsasm, &verified, NULL, 0);
    492 
    493 	assert_true(verified == 1);
    494 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_RANGE);
    495 	assert_true(isc_dnsstream_assembler_remaininglength(dnsasm) == 0);
    496 
    497 	isc_dnsstream_assembler_incoming(dnsasm, &verified, NULL, 0);
    498 	assert_true(verified == 1);
    499 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_NOMORE);
    500 }
    501 
    502 ISC_RUN_TEST_IMPL(dnsasm_torn_randomly_test) {
    503 	isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
    504 	verify_cbdata_t cbdata = { 0 };
    505 	verify_regions_cbdata_t cbdata_regions = { 0 };
    506 	isc_buffer_t dnsbuf;
    507 	size_t packetno;
    508 	isc_region_t packets[] = {
    509 		{ (void *)request, sizeof(request) },
    510 		{ (void *)response, sizeof(response) },
    511 		{ (void *)request_large, sizeof(request_large) },
    512 		{ (void *)response_large, sizeof(response_large) },
    513 		{ (void *)request, sizeof(request) },
    514 		{ (void *)response_large, sizeof(response_large) },
    515 		{ (void *)request_large, sizeof(request_large) },
    516 		{ (void *)response_large, sizeof(response_large) },
    517 		{ (void *)request, sizeof(request) },
    518 	};
    519 	const size_t npackets = sizeof(packets) / sizeof(packets[0]);
    520 
    521 	isc_buffer_init(&dnsbuf, NULL, 0);
    522 	isc_buffer_setmctx(&dnsbuf, mctx);
    523 
    524 	for (size_t i = 0; i < npackets; i++) {
    525 		isc_buffer_putmem(&dnsbuf, packets[i].base, packets[i].length);
    526 	}
    527 
    528 	/* process packet by packet */
    529 	packetno = 0;
    530 	cbdata.cont_on_success = false;
    531 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
    532 
    533 	/* process random amount of data */
    534 	for (; isc_buffer_remaininglength(&dnsbuf) > 0;) {
    535 		size_t sz = 1 + isc_random_uniform(
    536 					isc_buffer_remaininglength(&dnsbuf));
    537 
    538 		for (bool start = true; packetno < npackets; start = false) {
    539 			cbdata.verify_message =
    540 				(uint8_t *)packets[packetno].base;
    541 
    542 			if (start) {
    543 				isc_dnsstream_assembler_incoming(
    544 					dnsasm, &packetno,
    545 					isc_buffer_current(&dnsbuf), sz);
    546 			} else {
    547 				isc_dnsstream_assembler_incoming(
    548 					dnsasm, &packetno, NULL, 0);
    549 			}
    550 
    551 			if (isc_dnsstream_assembler_result(dnsasm) ==
    552 			    ISC_R_NOMORE)
    553 			{
    554 				break;
    555 			}
    556 		}
    557 
    558 		isc_buffer_forward(&dnsbuf, sz);
    559 	}
    560 
    561 	assert_true(packetno == npackets);
    562 	assert_true(isc_dnsstream_assembler_remaininglength(dnsasm) == 0);
    563 	assert_true(isc_buffer_remaininglength(&dnsbuf) == 0);
    564 
    565 	for (size_t i = 0; i < npackets; i++) {
    566 		isc_buffer_putmem(&dnsbuf, packets[i].base, packets[i].length);
    567 	}
    568 
    569 	/* try to process multiple packets at once, when possible */
    570 	packetno = 0;
    571 	cbdata_regions.cont_on_success = true;
    572 	cbdata_regions.packets = packets;
    573 
    574 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg_regions,
    575 				      (void *)&cbdata_regions);
    576 
    577 	/* process random amount of data */
    578 	for (; isc_buffer_remaininglength(&dnsbuf) > 0;) {
    579 		size_t sz = 1 + isc_random_uniform(
    580 					isc_buffer_remaininglength(&dnsbuf));
    581 
    582 		isc_dnsstream_assembler_incoming(
    583 			dnsasm, &packetno, isc_buffer_current(&dnsbuf), sz);
    584 
    585 		isc_buffer_forward(&dnsbuf, sz);
    586 	}
    587 
    588 	assert_true(packetno == npackets);
    589 	assert_true(isc_dnsstream_assembler_remaininglength(dnsasm) == 0);
    590 	assert_true(isc_buffer_remaininglength(&dnsbuf) == 0);
    591 
    592 	isc_buffer_clearmctx(&dnsbuf);
    593 	isc_buffer_invalidate(&dnsbuf);
    594 	dnsasm->cbarg = NULL; /* to make GCC happy about dangling pointers */
    595 }
    596 
    597 ISC_RUN_TEST_IMPL(dnsasm_clear_buffer_within_cb_test) {
    598 	isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
    599 	verify_cbdata_t cbdata = { 0 };
    600 	size_t verified = 0;
    601 	isc_buffer_t dnsbuf;
    602 
    603 	isc_buffer_init(&dnsbuf, NULL, 0);
    604 	isc_buffer_setmctx(&dnsbuf, mctx);
    605 
    606 	isc_buffer_putmem(&dnsbuf, (void *)request, sizeof(request));
    607 	isc_buffer_putmem(&dnsbuf, (void *)&response, sizeof(response));
    608 	isc_buffer_putmem(&dnsbuf, (void *)request, sizeof(request));
    609 	cbdata.cont_on_success = true;
    610 	cbdata.clear_on_success = true;
    611 
    612 	cbdata.verify_message = (uint8_t *)request;
    613 	isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
    614 	isc_dnsstream_assembler_incoming(dnsasm, &verified,
    615 					 isc_buffer_current(&dnsbuf),
    616 					 isc_buffer_remaininglength(&dnsbuf));
    617 
    618 	isc_buffer_clearmctx(&dnsbuf);
    619 	isc_buffer_invalidate(&dnsbuf);
    620 
    621 	assert_true(verified == 1);
    622 	assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_UNSET);
    623 
    624 	assert_true(isc_dnsstream_assembler_remaininglength(dnsasm) == 0);
    625 }
    626 
    627 ISC_TEST_LIST_START
    628 ISC_TEST_ENTRY_CUSTOM(dnsbuffer_generic_test, setup_test_dnsbuf,
    629 		      teardown_test_dnsbuf)
    630 ISC_TEST_ENTRY_CUSTOM(dnsbuffer_resize_alloc_test, setup_test_dnsbuf,
    631 		      teardown_test_dnsbuf)
    632 ISC_TEST_ENTRY_CUSTOM(dnsbuffer_be_test, setup_test_dnsbuf,
    633 		      teardown_test_dnsbuf)
    634 ISC_TEST_ENTRY_CUSTOM(dnsasm_sequence_test, setup_test_dnsasm,
    635 		      teardown_test_dnsasm)
    636 ISC_TEST_ENTRY_CUSTOM(dnsasm_multiple_messages_test, setup_test_dnsasm,
    637 		      teardown_test_dnsasm)
    638 ISC_TEST_ENTRY_CUSTOM(dnsasm_torn_apart_test, setup_test_dnsasm,
    639 		      teardown_test_dnsasm)
    640 ISC_TEST_ENTRY_CUSTOM(dnsasm_error_data_test, setup_test_dnsasm,
    641 		      teardown_test_dnsasm)
    642 ISC_TEST_ENTRY_CUSTOM(dnsasm_torn_randomly_test, setup_test_dnsasm,
    643 		      teardown_test_dnsasm)
    644 ISC_TEST_ENTRY_CUSTOM(dnsasm_clear_buffer_within_cb_test, setup_test_dnsasm,
    645 		      teardown_test_dnsasm)
    646 ISC_TEST_LIST_END
    647 
    648 ISC_TEST_MAIN
    649