OpenVPN
test_buffer.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2016-2026 Sentyron B.V. <openvpn@sentyron.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include <setjmp.h>
30#include <cmocka.h>
31
32#include "buffer.h"
33#include "buffer.c"
34#include "test_common.h"
35
36static void
38{
39 assert_true(strprefix("123456", "123456"));
40 assert_true(strprefix("123456", "123"));
41 assert_true(strprefix("123456", ""));
42 assert_false(strprefix("123456", "456"));
43 assert_false(strprefix("12", "123"));
44}
45
46#define testsep ","
47#define testnosep ""
48#define teststr1 "one"
49#define teststr2 "two"
50#define teststr3 "three"
51
52#define assert_buf_equals_str(buf, str) \
53 assert_int_equal(BLENZ(buf), strlen(str)); \
54 assert_memory_equal(CBPTR(buf), str, BLENZ(buf));
55
56static void
58{
59 struct gc_arena gc = gc_new();
60 struct buffer buf = alloc_buf_gc(16, &gc);
61
62 buf_printf(&buf, "%d", 123);
63 buf_printf(&buf, "%s", "some text, too long to fit");
64 assert_buf_equals_str(&buf, "123some text, t");
65 assert_int_equal(BCAP(&buf), 1); /* \0 byte not part of len */
66
67 buf_printf(&buf, "%s", "more");
68 assert_buf_equals_str(&buf, "123some text, t");
69
70 buf_catrunc(&buf, "...");
71 assert_buf_equals_str(&buf, "123some text...");
72
73 buf_catrunc(&buf, "some other text, much too long to fit");
74 assert_buf_equals_str(&buf, "123some text...");
75
76 buf_catrunc(&buf, "something else"); /* exactly right */
77 assert_buf_equals_str(&buf, "1something else");
78
79 buf_catrunc(&buf, "something other"); /* 1 byte too long */
80 assert_buf_equals_str(&buf, "1something else");
81
82 gc_free(&gc);
83}
84
85static void
86test_buffer_puts(void **state)
87{
88 struct gc_arena gc = gc_new();
89 struct buffer buf = alloc_buf_gc(5, &gc);
90
91 buf_puts(&buf, "1234");
92 assert_string_equal(BSTR(&buf), "1234");
93
94 buf_reset_len(&buf);
95 buf_puts(&buf, "12345");
96 assert_string_equal(BSTR(&buf), "1234");
97
98 /* buf already full */
99 buf_puts(&buf, "12345");
100 assert_string_equal(BSTR(&buf), "1234");
101
102 struct buffer one_byte_buf = alloc_buf_gc(1, &gc);
103 buf_puts(&one_byte_buf, "x");
105
106 gc_free(&gc);
107}
108
109static void
111{
112 const int input_size = 10;
113 const uint8_t input[] = { 0x01, 0x00, 0xff, 0x10, 0xff, 0x00, 0xf0, 0x0f, 0x09, 0x0a };
114 char *output;
115 struct gc_arena gc = gc_new();
116
117 int maxoutput = 0;
118 unsigned int blocksize = 5;
119 const char *separator = " ";
120 output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
121 assert_string_equal(output, "0100ff10ff 00f00f090a");
122
123 maxoutput = 14;
124 output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
125 assert_string_equal(output, "0100[more...]");
126
127 maxoutput = 11;
128 output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
129 assert_string_equal(output, "0[more...]");
130
131 maxoutput = 10;
132 output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
133 assert_string_equal(output, "0100ff10f");
134
135 maxoutput = 9;
136 output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
137 assert_string_equal(output, "0100ff10");
138
139 gc_free(&gc);
140}
141
149
150static int
152{
153 struct test_buffer_list_aggregate_ctx *ctx = calloc(1, sizeof(*ctx));
154 ctx->empty = buffer_list_new();
155
160
164
166 uint8_t data = 0;
167 buffer_list_push_data(ctx->empty_buffers, &data, 0);
168 buffer_list_push_data(ctx->empty_buffers, &data, 0);
169
170 *state = ctx;
171 return 0;
172}
173
174static int
176{
177 struct test_buffer_list_aggregate_ctx *ctx = *state;
178
183 free(ctx);
184 return 0;
185}
186
187static void
189{
190 struct test_buffer_list_aggregate_ctx *ctx = *state;
191
192 /* aggregating an empty buffer list results in an empty buffer list */
194 assert_null(ctx->empty->head);
195}
196
197static void
199{
200 struct test_buffer_list_aggregate_ctx *ctx = *state;
201
202 /* With a max length of 2, no aggregation should take place */
204 assert_int_equal(ctx->one_two_three->size, 3);
205 const struct buffer *buf = buffer_list_peek(ctx->one_two_three);
207}
208
209static void
211{
212 struct test_buffer_list_aggregate_ctx *ctx = *state;
213 const char *expected = teststr1 testsep teststr2 testsep;
214
215 /* Aggregate the first two elements
216 * (add 1 to max_len to test if "three" is not sneaked in too)
217 */
218 buffer_list_aggregate_separator(ctx->one_two_three, strlen(expected) + 1, testsep);
219 assert_int_equal(ctx->one_two_three->size, 2);
220 const struct buffer *buf = buffer_list_peek(ctx->one_two_three);
222}
223
224static void
226{
227 struct test_buffer_list_aggregate_ctx *ctx = *state;
228
229 /* Aggregate all */
231 assert_int_equal(ctx->one_two_three->size, 1);
232 const struct buffer *buf = buffer_list_peek(ctx->one_two_three);
234}
235
236static void
238{
239 struct test_buffer_list_aggregate_ctx *ctx = *state;
240
241 /* Aggregate all */
243 assert_int_equal(ctx->one_two_three->size, 1);
244 const struct buffer *buf = buffer_list_peek(ctx->one_two_three);
246}
247
248static void
250{
251 struct test_buffer_list_aggregate_ctx *ctx = *state;
252 struct buffer_list *bl_zerolen = ctx->zero_length_strings;
253
254 /* Aggregate all */
255 buffer_list_aggregate_separator(bl_zerolen, 1 << 16, testnosep);
256 assert_int_equal(bl_zerolen->size, 1);
257 const struct buffer *buf = buffer_list_peek(bl_zerolen);
258 assert_buf_equals_str(buf, "");
259}
260
261static void
263{
264 struct test_buffer_list_aggregate_ctx *ctx = *state;
265 struct buffer_list *bl_emptybuffers = ctx->empty_buffers;
266
267 /* Aggregate all */
268 buffer_list_aggregate_separator(bl_emptybuffers, 1 << 16, testnosep);
269 assert_int_equal(bl_emptybuffers->size, 1);
270 const struct buffer *buf = buffer_list_peek(bl_emptybuffers);
271 assert_int_equal(BLEN(buf), 0);
272}
273
274static void
276{
277 struct gc_arena gc = gc_new();
278 struct buffer buf = alloc_buf_gc(1024, &gc);
279
280 assert_ptr_equal(gc.list + 1, buf.data);
281 free_buf_gc(&buf, &gc);
283
284 gc_free(&gc);
285}
286
287static void
289{
290 struct gc_arena gc = gc_new();
291 struct buffer buf1 = alloc_buf_gc(1024, &gc);
292 struct buffer buf2 = alloc_buf_gc(1024, &gc);
293 struct buffer buf3 = alloc_buf_gc(1024, &gc);
294
295 struct gc_entry *e;
296
297 e = gc.list;
298
299 assert_ptr_equal(e + 1, buf3.data);
300 assert_ptr_equal(e->next + 1, buf2.data);
301 assert_ptr_equal(e->next->next + 1, buf1.data);
302
303 free_buf_gc(&buf2, &gc);
304
305 assert_non_null(gc.list);
306
307 while (e)
308 {
309 assert_ptr_not_equal(e + 1, buf2.data);
310 e = e->next;
311 }
312
313 gc_free(&gc);
314}
315
316
317static void
319{
320 struct gc_arena gc = gc_new();
321
322 void *p1 = gc_realloc(NULL, 512, &gc);
323 void *p2 = gc_realloc(NULL, 512, &gc);
324
325 assert_ptr_not_equal(p1, p2);
326
327 memset(p1, '1', 512);
328 memset(p2, '2', 512);
329
330 p1 = gc_realloc(p1, 512, &gc);
331
332 /* allocate 512kB to ensure the pointer needs to change */
333 void *p1new = gc_realloc(p1, 512ul * 1024, &gc);
334 assert_ptr_not_equal(p1, p1new);
335
336 void *p2new = gc_realloc(p2, 512ul * 1024, &gc);
337 assert_ptr_not_equal(p2, p2new);
338
339 void *p3 = gc_realloc(NULL, 512, &gc);
340 memset(p3, '3', 512);
341
342
343 gc_free(&gc);
344}
345
346static void
348{
349 char buf[256];
350 strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
351 assert_false(string_mod(buf, CC_PRINT, 0, '@'));
352 assert_string_equal(buf, "There is @ a nice 1234 year old tr@ ee!");
353
354 strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
355 assert_true(string_mod(buf, CC_ANY, 0, '@'));
356 assert_string_equal(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
357
358 /* 0 as replace removes characters */
359 strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
360 assert_false(string_mod(buf, CC_PRINT, 0, '\0'));
361 assert_string_equal(buf, "There is a nice 1234 year old tr ee!");
362
363 strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
364 assert_false(string_mod(buf, CC_PRINT, CC_DIGIT, '@'));
365 assert_string_equal(buf, "There is @ a nice @@@@ year old tr@ ee!");
366
367 strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
368 assert_false(string_mod(buf, CC_ALPHA, CC_DIGIT, '.'));
369 assert_string_equal(buf, "There.is...a.nice......year.old.tr..ee.");
370
371 strcpy(buf, "There is \x01 a 'nice' \"1234\"\n year old \ntr\x7f ee!");
372 assert_false(string_mod(buf, CC_ALPHA | CC_DIGIT | CC_NEWLINE | CC_SINGLE_QUOTE,
373 CC_DOUBLE_QUOTE | CC_BLANK, '.'));
374 assert_string_equal(buf, "There.is...a.'nice'..1234.\n.year.old.\ntr..ee.");
375
376 strcpy(buf, "There is a \\'nice\\' \"1234\" [*] year old \ntree!");
377 assert_false(string_mod(buf, CC_PRINT, CC_BACKSLASH | CC_ASTERISK, '.'));
378 assert_string_equal(buf, "There is a .'nice.' \"1234\" [.] year old .tree!");
379}
380
381
382static void
384{
385 struct gc_arena gc = gc_new();
386
387 struct buffer buf = alloc_buf_gc(1024, &gc);
388
389 const char test1[] = "There is a nice 1234\x00 year old tree!";
390 buf_write(&buf, test1, sizeof(test1));
391
392 /* allow the null bytes and string but not the ! */
394
395 /* remove final ! and null byte to pass */
396 buf_inc_len(&buf, -2);
398
399 /* Check excluding digits works */
401 gc_free(&gc);
402}
403
404static void
405test_snprintf(void **state)
406{
407 /* we used to have a custom openvpn_snprintf function because some
408 * OS (the comment did not specify which) did not always put the
409 * null byte there. So we unit test this to be sure.
410 *
411 * This probably refers to the MSVC behaviour, see also
412 * https://stackoverflow.com/questions/7706936/is-snprintf-always-null-terminating
413 */
414
415 /* Instead of trying to trick the compiler here, disable the warnings
416 * for this unit test. We know that the results will be truncated
417 * and we want to test that. Note we need the clang as clang-cl (msvc) does
418 * not define __GNUC__ like it does under UNIX(-like) platforms */
419#if defined(__GNUC__) || defined(__clang__)
420/* some clang version do not understand -Wformat-truncation, so ignore the
421 * warning to avoid warnings/errors (-Werror) about unknown pragma/option */
422#if defined(__clang__)
423#pragma clang diagnostic push
424#pragma clang diagnostic ignored "-Wunknown-warning-option"
425#endif
426#pragma GCC diagnostic push
427#pragma GCC diagnostic ignored "-Wformat-truncation"
428#endif
429
430 char buf[10] = { 'a' };
431 int ret = 0;
432
433 ret = snprintf(buf, sizeof(buf), "0123456789abcde");
435 assert_int_equal(buf[9], '\0');
436
437 memset(buf, 'b', sizeof(buf));
438 ret = snprintf(buf, sizeof(buf), "- %d - %d -", 77, 88);
440 assert_int_equal(buf[9], '\0');
441
442 memset(buf, 'c', sizeof(buf));
443 ret = snprintf(buf, sizeof(buf), "- %8.2f", 77.8899);
445 assert_int_equal(buf[9], '\0');
446
447#if defined(__GNUC__) || defined(__clang__)
448#pragma GCC diagnostic pop
449#if defined(__clang__)
450#pragma clang diagnostic pop
451#endif
452#endif
453}
454
455static void
457{
458 char buf[10];
459 assert_true(checked_snprintf(buf, sizeof(buf), "%s", "Hello"));
460 assert_true(checked_snprintf(buf, sizeof(buf), "%s", "Hello Foo"));
461 assert_false(checked_snprintf(buf, sizeof(buf), "%s", "Hello Foo!"));
462 assert_false(checked_snprintf(buf, sizeof(buf), "%s", "Hello World!"));
463}
464
465void
466test_string_chomp(void **state)
467{
468 char string[10];
469
470 strcpy(string, "Foo\n");
471 chomp(string);
472 assert_string_equal(string, "Foo");
473
474 strcpy(string, "Foo\r\n\n\r");
475 chomp(string);
476 assert_string_equal(string, "Foo");
477
478 strcpy(string, "Foo");
479 chomp(string);
480 assert_string_equal(string, "Foo");
481
482 strcpy(string, "F\ro\no");
483 chomp(string);
484 assert_string_equal(string, "F\ro\no");
485
486 string[2] = '\0';
487 chomp(string);
488 assert_string_equal(string, "F");
489
490 strcpy(string, "");
491 chomp(string);
492 assert_string_equal(string, "");
493
494 strcpy(string, "Foo");
495 rm_trailing_chars(string, "o");
496 assert_string_equal(string, "F");
497
498 strcpy(string, "Foo");
499 rm_trailing_chars(string, "oF");
500 assert_string_equal(string, "");
501}
502
503void
504test_buffer_chomp(void **state)
505{
506 struct gc_arena gc = gc_new();
507 struct buffer buf = alloc_buf_gc(1024, &gc);
508
509 const char test1[] = "There is a nice 1234 year old tree!\n\r";
510 buf_write(&buf, test1, sizeof(test1));
511 buf_chomp(&buf);
512 /* Check that our own method agrees */
514 assert_string_equal(BSTR(&buf), "There is a nice 1234 year old tree!");
515
516 struct buffer buf2 = alloc_buf_gc(1024, &gc);
517 const char test2[] = "CR_RESPONSE,MTIx\x0a\x00";
518 buf_write(&buf2, test2, sizeof(test2));
519 buf_chomp(&buf2);
520
521 buf_chomp(&buf2);
522 /* Check that our own method agrees */
524 assert_string_equal(BSTR(&buf2), "CR_RESPONSE,MTIx");
525 gc_free(&gc);
526}
527
528static void
530{
531 struct gc_arena gc = gc_new();
532 struct buffer buf = alloc_buf_gc(1000, &gc);
533 assert_null(buf_extract_field(&buf, ',', &gc));
534
535 buf = alloc_buf_gc(5, &gc);
536 buf_write(&buf, "12345", 5);
537 const char *ret = buf_extract_field(&buf, '5', &gc);
538 assert_string_equal(ret, "1234");
539 /* nothing left after the 5 */
540 assert_int_equal(buf_len(&buf), 0);
541
542 buf = alloc_buf_gc(5, &gc);
543 buf_write(&buf, "12345", 5);
544 ret = buf_extract_field(&buf, '4', &gc);
545 assert_string_equal(ret, "123");
546
547 /* 5 should be left */
548 assert_int_equal(buf_len(&buf), 1);
549 assert_memory_equal(buf_bptr(&buf), "5", 1);
550
551 buf = alloc_buf_gc(5, &gc);
552 buf_write(&buf, "12345", 5);
553 assert_null(buf_extract_field(&buf, '6', &gc));
554
555 gc_free(&gc);
556}
557
558void
560{
561 struct gc_arena gc = gc_new();
562
563 struct buffer buf = alloc_buf_gc(5, &gc);
564 const char test1[] = "1234";
565 const char test2[] = "12345";
566 assert_true(buf_write(&buf, test1, sizeof(test1)));
567 assert_string_equal(BSTR(&buf), "1234");
568 buf_null_terminate(&buf);
569 assert_string_equal(BSTR(&buf), "1234");
570
571 assert_true(buf_inc_len(&buf, -1));
572 assert_true(buf_write_u8(&buf, '5'));
574 buf_null_terminate(&buf);
575 assert_string_equal(BSTR(&buf), "1234");
576
577 struct buffer buf2;
578 CLEAR(buf2);
580
581 gc_free(&gc);
582}
583
584/* for building long texts */
585#define A_TIMES_256 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO"
586
587static void
589{
590 struct buffer buf = alloc_buf(16);
591
592 /* The validity predicates must tolerate a NULL buffer pointer rather than
593 * dereferencing it, so that the whole buf_* family is NULL-safe. */
597
599 assert_true(buf_valid(&buf));
600
601 free_buf(&buf);
602
603 /* A freed buffer is neither defined nor valid. */
605 assert_false(buf_valid(&buf));
606 assert_int_equal(buf_len(&buf), 0);
607}
608
609void
610test_buffer_parse(void **state)
611{
612 struct gc_arena gc = gc_new();
613 struct buffer buf = alloc_buf_gc(1024, &gc);
614 char line[512];
615 bool status;
616 const char test1[] = A_TIMES_256 "EOL\n" A_TIMES_256 "EOF";
617
618 /* line buffer bigger than actual line */
619 assert_true(buf_write(&buf, test1, sizeof(test1)));
620 status = buf_parse(&buf, '\n', line, sizeof(line));
623 status = buf_parse(&buf, '\n', line, sizeof(line));
626
627 /* line buffer exactly same size as actual line + terminating \0 */
628 buf_reset_len(&buf);
629 assert_true(buf_write(&buf, test1, sizeof(test1)));
630 status = buf_parse(&buf, '\n', line, 260);
633 status = buf_parse(&buf, '\n', line, 260);
636
637 /* line buffer smaller than actual line */
638 buf_reset_len(&buf);
639 assert_true(buf_write(&buf, test1, sizeof(test1)));
640 status = buf_parse(&buf, '\n', line, 257);
643 status = buf_parse(&buf, '\n', line, 257);
646 status = buf_parse(&buf, '\n', line, 257);
649 status = buf_parse(&buf, '\n', line, 257);
652
653 gc_free(&gc);
654}
655
656int
657main(void)
658{
660 const struct CMUnitTest tests[] = {
661 cmocka_unit_test(test_buffer_strprefix),
662 cmocka_unit_test(test_buffer_printf_catrunc),
663 cmocka_unit_test(test_buffer_puts),
664 cmocka_unit_test(test_buffer_format_hex_ex),
665 cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_empty,
667 cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_noop,
669 cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_two,
671 cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_all,
673 cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_nosep,
675 cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_zerolen,
677 cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_emptybuffers,
679 cmocka_unit_test(test_buffer_free_gc_one),
680 cmocka_unit_test(test_buffer_free_gc_two),
681 cmocka_unit_test(test_buffer_gc_realloc),
682 cmocka_unit_test(test_character_class),
683 cmocka_unit_test(test_character_string_mod_buf),
684 cmocka_unit_test(test_snprintf),
685 cmocka_unit_test(test_checked_snprintf),
686 cmocka_unit_test(test_string_chomp),
687 cmocka_unit_test(test_buffer_chomp),
688 cmocka_unit_test(test_buffer_null_terminate),
689 cmocka_unit_test(test_buffer_null_predicates),
690 cmocka_unit_test(test_buffer_parse),
691 cmocka_unit_test(test_buffer_extract_field)
692 };
693
694 return cmocka_run_group_tests_name("buffer", tests, NULL, NULL);
695}
struct buffer_entry * buffer_list_push_data(struct buffer_list *ol, const void *data, size_t size)
Allocates and appends a new buffer containing data of length size.
Definition buffer.c:1204
void rm_trailing_chars(char *str, const char *what_to_delete)
Remove all trailing characters that appear in a given set.
Definition buffer.c:588
void free_buf(struct buffer *buf)
Free the memory allocated for a buffer.
Definition buffer.c:169
void buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max_len, const char *sep)
Aggregates as many buffers as possible from bl in a new buffer of maximum length max_len .
Definition buffer.c:1245
static void free_buf_gc(struct buffer *buf, struct gc_arena *gc)
Definition buffer.c:176
void buf_catrunc(struct buffer *buf, const char *str)
Append a string to the physical end of a buffer that was truncated by buf_printf().
Definition buffer.c:268
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
Definition buffer.c:226
char * buf_extract_field(struct buffer *buf, char sep, struct gc_arena *gc)
Extract a field from buf that ends with the sep character.
Definition buffer.c:1383
void buf_null_terminate(struct buffer *buf)
Force a null terminator at the end of the buffer content.
Definition buffer.c:496
void * gc_realloc(void *ptr, size_t size, struct gc_arena *a)
allows to realloc a pointer previously allocated by gc_malloc or gc_realloc
Definition buffer.c:338
struct buffer_list * buffer_list_new(void)
Allocate an empty buffer list of capacity max_size.
Definition buffer.c:1150
void chomp(char *str)
Remove trailing newline and carriage-return characters from a string.
Definition buffer.c:579
struct buffer * buffer_list_peek(struct buffer_list *ol)
Retrieve the head buffer.
Definition buffer.c:1232
void buffer_list_free(struct buffer_list *ol)
Frees a buffer list and all the buffers in it.
Definition buffer.c:1159
void buf_puts(struct buffer *buf, const char *str)
Append a string to a buffer with overflow check.
Definition buffer.c:252
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
Definition buffer.c:77
char * format_hex_ex(const uint8_t *data, size_t size, size_t maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Format a binary buffer as a hex string.
Definition buffer.c:447
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
Modifies a string in place by replacing certain classes of characters of it with a specified characte...
Definition buffer.c:986
struct buffer alloc_buf(size_t size)
Allocate a buffer of the given size.
Definition buffer.c:60
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Extract the next token from a buffer, delimited by a given character.
Definition buffer.c:757
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
Definition buffer.c:1115
void buffer_list_push(struct buffer_list *ol, const char *str)
Allocates and appends a new buffer containing str as data to ol.
Definition buffer.c:1190
void buf_chomp(struct buffer *buf)
Remove trailing newline and carriage-return characters from a buffer.
Definition buffer.c:517
bool string_check_buf(const struct buffer *buf, const unsigned int inclusive, const unsigned int exclusive)
Check a buffer if it only consists of allowed characters.
Definition buffer.c:1020
Buffer management functions and garbage collection.
#define CC_DOUBLE_QUOTE
double quote
Definition buffer.h:1702
#define CC_BLANK
space or tab
Definition buffer.h:1690
static uint8_t * buf_bptr(struct buffer *buf)
Return a pointer to the start of the buffer content.
Definition buffer.h:449
#define BSTR(buf)
Return the buffer content pointer cast to char *.
Definition buffer.h:157
#define CC_ANY
any character
Definition buffer.h:1677
#define BPTR(buf)
Return a pointer to the start of the buffer content.
Definition buffer.h:139
#define CC_SINGLE_QUOTE
single quote
Definition buffer.h:1701
static bool buf_inc_len(struct buffer *buf, int inc)
Increase or decrease the length of a buffer.
Definition buffer.h:1119
#define CC_DIGIT
digit isdigit()
Definition buffer.h:1684
static bool buf_valid(const struct buffer *buf)
Return true iff buf is valid.
Definition buffer.h:414
#define CC_CRLF
carriage return or newline
Definition buffer.h:1714
#define CC_ASTERISK
asterisk
Definition buffer.h:1710
#define CC_ALPHA
alphabetic isalpha()
Definition buffer.h:1681
#define CC_NEWLINE
newline
Definition buffer.h:1691
static int buf_len(const struct buffer *buf)
Return the length of the buffer content.
Definition buffer.h:462
#define CC_SPACE
whitespace isspace()
Definition buffer.h:1687
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Append data to a buffer.
Definition buffer.h:1239
#define CC_BACKSLASH
backslash
Definition buffer.h:1694
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Append a uint8_t to a buffer.
Definition buffer.h:1283
#define BLEN(buf)
Return the length of the buffer content in bytes.
Definition buffer.h:151
static void buf_reset_len(struct buffer *buf)
Reset the length and offset of a buffer to zero.
Definition buffer.h:616
#define BCAP(buf)
Return the number of bytes available for appending to the buffer.
Definition buffer.h:161
#define CC_NULL
null character \0
Definition buffer.h:1678
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1965
#define CC_PRINT
printable (>= 32, != 127)
Definition buffer.h:1685
static bool buf_defined(const struct buffer *buf)
Return true iff buf has a non-NULL data pointer.
Definition buffer.h:399
#define CC_ALNUM
alphanumeric isalnum()
Definition buffer.h:1680
static bool strprefix(const char *str, const char *prefix)
Return true iff str starts with prefix.
Definition buffer.h:1805
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1949
static SERVICE_STATUS status
Definition interactive.c:52
#define CLEAR(x)
Definition basic.h:32
A singly-linked list of buffers, with head/tail pointers for O(1) push.
Definition buffer.h:2159
size_t size
Current number of entries.
Definition buffer.h:2162
struct buffer_entry * head
Next item to pop/peek.
Definition buffer.h:2160
Wrapper structure for dynamically allocated memory.
Definition buffer.h:71
uint8_t * data
Pointer to the allocated memory.
Definition buffer.h:78
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:76
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:127
struct gc_entry * list
First element of the linked list of gc_entry structures.
Definition buffer.h:128
Garbage collection entry for one dynamically allocated block of memory.
Definition buffer.h:98
struct gc_entry * next
Pointer to the next item in the linked list.
Definition buffer.h:99
struct buffer_list * zero_length_strings
struct buffer_list * one_two_three
struct buffer_list * empty
struct buffer_list * empty_buffers
static void test_character_class(void **state)
static void test_buffer_format_hex_ex(void **state)
static int test_buffer_list_setup(void **state)
static void test_buffer_list_aggregate_separator_all(void **state)
#define assert_buf_equals_str(buf, str)
Definition test_buffer.c:52
static void test_checked_snprintf(void **state)
static void test_buffer_free_gc_two(void **state)
static void test_snprintf(void **state)
static void test_buffer_puts(void **state)
Definition test_buffer.c:86
static void test_character_string_mod_buf(void **state)
#define A_TIMES_256
void test_buffer_parse(void **state)
#define teststr1
Definition test_buffer.c:48
static void test_buffer_list_aggregate_separator_zerolen(void **state)
static void test_buffer_printf_catrunc(void **state)
Definition test_buffer.c:57
void test_buffer_chomp(void **state)
int main(void)
void test_buffer_null_terminate(void **state)
static void test_buffer_list_aggregate_separator_two(void **state)
static void test_buffer_extract_field(void **state)
#define testnosep
Definition test_buffer.c:47
static void test_buffer_list_aggregate_separator_noop(void **state)
static void test_buffer_free_gc_one(void **state)
#define teststr2
Definition test_buffer.c:49
static void test_buffer_list_aggregate_separator_nosep(void **state)
static void test_buffer_gc_realloc(void **state)
static void test_buffer_list_aggregate_separator_empty(void **state)
static int test_buffer_list_teardown(void **state)
void test_string_chomp(void **state)
static void test_buffer_null_predicates(void **state)
static void test_buffer_list_aggregate_separator_emptybuffers(void **state)
static void test_buffer_strprefix(void **state)
Definition test_buffer.c:37
#define teststr3
Definition test_buffer.c:50
#define testsep
Definition test_buffer.c:46
static void openvpn_unit_test_setup(void)
Sets up the environment for unit tests like making both stderr and stdout non-buffered to avoid messa...
Definition test_common.h:63
struct gc_arena gc
Definition test_ssl.c:138