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-2021 Fox Crypto B.V. <openvpn@foxcrypto.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, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include "syshead.h"
29 
30 #include <setjmp.h>
31 #include <cmocka.h>
32 
33 #include "buffer.h"
34 #include "buffer.c"
35 #include "test_common.h"
36 
37 static void
38 test_buffer_strprefix(void **state)
39 {
40  assert_true(strprefix("123456", "123456"));
41  assert_true(strprefix("123456", "123"));
42  assert_true(strprefix("123456", ""));
43  assert_false(strprefix("123456", "456"));
44  assert_false(strprefix("12", "123"));
45 }
46 
47 #define testsep ","
48 #define testnosep ""
49 #define teststr1 "one"
50 #define teststr2 "two"
51 #define teststr3 "three"
52 #define teststr4 "four"
53 
54 #define assert_buf_equals_str(buf, str) \
55  assert_int_equal(BLEN(buf), strlen(str)); \
56  assert_memory_equal(BPTR(buf), str, BLEN(buf));
57 
58 static void
60 {
61  struct gc_arena gc = gc_new();
62  struct buffer buf = alloc_buf_gc(16, &gc);
63 
64  buf_printf(&buf, "%d", 123);
65  buf_printf(&buf, "%s", "some text, too long to fit");
66  assert_buf_equals_str(&buf, "123some text, t");
67 
68  buf_catrunc(&buf, "...");
69  assert_buf_equals_str(&buf, "123some text...");
70 
71  buf_catrunc(&buf, "some other text, much too long to fit");
72  assert_buf_equals_str(&buf, "123some text...");
73 
74  buf_catrunc(&buf, "something else"); /* exactly right */
75  assert_buf_equals_str(&buf, "1something else");
76 
77  buf_catrunc(&buf, "something other"); /* 1 byte too long */
78  assert_buf_equals_str(&buf, "1something else");
79 
80  gc_free(&gc);
81 }
82 
83 static void
85 {
86  const int input_size = 10;
87  const uint8_t input[] = {
88  0x01, 0x00, 0xff, 0x10, 0xff, 0x00, 0xf0, 0x0f, 0x09, 0x0a
89  };
90  char *output;
91  struct gc_arena gc = gc_new();
92 
93  int maxoutput = 0;
94  unsigned int blocksize = 5;
95  char *separator = " ";
96  output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
97  assert_string_equal(output, "0100ff10ff 00f00f090a");
98 
99  maxoutput = 14;
100  output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
101  assert_string_equal(output, "0100[more...]");
102 
103  maxoutput = 11;
104  output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
105  assert_string_equal(output, "0[more...]");
106 
107  maxoutput = 10;
108  output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
109  assert_string_equal(output, "0100ff10f");
110 
111  maxoutput = 9;
112  output = format_hex_ex(input, input_size, maxoutput, blocksize, separator, &gc);
113  assert_string_equal(output, "0100ff10");
114 
115  gc_free(&gc);
116 }
117 
123 };
124 
125 static int
127 {
128  struct test_buffer_list_aggregate_ctx *ctx = calloc(1, sizeof(*ctx));
129  ctx->empty = buffer_list_new();
130 
135 
139 
141  uint8_t data = 0;
142  buffer_list_push_data(ctx->empty_buffers, &data, 0);
143  buffer_list_push_data(ctx->empty_buffers, &data, 0);
144 
145  *state = ctx;
146  return 0;
147 }
148 
149 static int
151 {
152  struct test_buffer_list_aggregate_ctx *ctx = *state;
153 
154  buffer_list_free(ctx->empty);
158  free(ctx);
159  return 0;
160 }
161 
162 static void
164 {
165  struct test_buffer_list_aggregate_ctx *ctx = *state;
166 
167  /* aggregating an empty buffer list results in an empty buffer list */
169  assert_null(ctx->empty->head);
170 }
171 
172 static void
174 {
175  struct test_buffer_list_aggregate_ctx *ctx = *state;
176 
177  /* With a max length of 2, no aggregation should take place */
179  assert_int_equal(ctx->one_two_three->size, 3);
180  struct buffer *buf = buffer_list_peek(ctx->one_two_three);
182 }
183 
184 static void
186 {
187  struct test_buffer_list_aggregate_ctx *ctx = *state;
188  const char *expected = teststr1 testsep teststr2 testsep;
189 
190  /* Aggregate the first two elements
191  * (add 1 to max_len to test if "three" is not sneaked in too)
192  */
193  buffer_list_aggregate_separator(ctx->one_two_three, strlen(expected) + 1,
194  testsep);
195  assert_int_equal(ctx->one_two_three->size, 2);
196  struct buffer *buf = buffer_list_peek(ctx->one_two_three);
197  assert_buf_equals_str(buf, expected);
198 }
199 
200 static void
202 {
203  struct test_buffer_list_aggregate_ctx *ctx = *state;
204 
205  /* Aggregate all */
207  assert_int_equal(ctx->one_two_three->size, 1);
208  struct buffer *buf = buffer_list_peek(ctx->one_two_three);
211 }
212 
213 static void
215 {
216  struct test_buffer_list_aggregate_ctx *ctx = *state;
217 
218  /* Aggregate all */
220  assert_int_equal(ctx->one_two_three->size, 1);
221  struct buffer *buf = buffer_list_peek(ctx->one_two_three);
223 }
224 
225 static void
227 {
228  struct test_buffer_list_aggregate_ctx *ctx = *state;
229  struct buffer_list *bl_zerolen = ctx->zero_length_strings;
230 
231  /* Aggregate all */
232  buffer_list_aggregate_separator(bl_zerolen, 1<<16, testnosep);
233  assert_int_equal(bl_zerolen->size, 1);
234  struct buffer *buf = buffer_list_peek(bl_zerolen);
235  assert_buf_equals_str(buf, "");
236 }
237 
238 static void
240 {
241  struct test_buffer_list_aggregate_ctx *ctx = *state;
242  struct buffer_list *bl_emptybuffers = ctx->empty_buffers;
243 
244  /* Aggregate all */
245  buffer_list_aggregate_separator(bl_emptybuffers, 1<<16, testnosep);
246  assert_int_equal(bl_emptybuffers->size, 1);
247  struct buffer *buf = buffer_list_peek(bl_emptybuffers);
248  assert_int_equal(BLEN(buf), 0);
249 }
250 
251 static void
253 {
254  struct gc_arena gc = gc_new();
255  struct buffer buf = alloc_buf_gc(1024, &gc);
256 
257  assert_ptr_equal(gc.list + 1, buf.data);
258  free_buf_gc(&buf, &gc);
259  assert_null(gc.list);
260 
261  gc_free(&gc);
262 }
263 
264 static void
266 {
267  struct gc_arena gc = gc_new();
268  struct buffer buf1 = alloc_buf_gc(1024, &gc);
269  struct buffer buf2 = alloc_buf_gc(1024, &gc);
270  struct buffer buf3 = alloc_buf_gc(1024, &gc);
271 
272  struct gc_entry *e;
273 
274  e = gc.list;
275 
276  assert_ptr_equal(e + 1, buf3.data);
277  assert_ptr_equal(e->next + 1, buf2.data);
278  assert_ptr_equal(e->next->next + 1, buf1.data);
279 
280  free_buf_gc(&buf2, &gc);
281 
282  assert_non_null(gc.list);
283 
284  while (e)
285  {
286  assert_ptr_not_equal(e + 1, buf2.data);
287  e = e->next;
288  }
289 
290  gc_free(&gc);
291 }
292 
293 
294 static void
296 {
297  struct gc_arena gc = gc_new();
298 
299  void *p1 = gc_realloc(NULL, 512, &gc);
300  void *p2 = gc_realloc(NULL, 512, &gc);
301 
302  assert_ptr_not_equal(p1, p2);
303 
304  memset(p1, '1', 512);
305  memset(p2, '2', 512);
306 
307  p1 = gc_realloc(p1, 512, &gc);
308 
309  /* allocate 512kB to ensure the pointer needs to change */
310  void *p1new = gc_realloc(p1, 512ul * 1024, &gc);
311  assert_ptr_not_equal(p1, p1new);
312 
313  void *p2new = gc_realloc(p2, 512ul * 1024, &gc);
314  assert_ptr_not_equal(p2, p2new);
315 
316  void *p3 = gc_realloc(NULL, 512, &gc);
317  memset(p3, '3', 512);
318 
319 
320  gc_free(&gc);
321 }
322 
323 static void
324 test_character_class(void **state)
325 {
326  char buf[256];
327  strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
328  assert_false(string_mod(buf, CC_PRINT, 0, '@'));
329  assert_string_equal(buf, "There is @ a nice 1234 year old tr@ ee!");
330 
331  strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
332  assert_true(string_mod(buf, CC_ANY, 0, '@'));
333  assert_string_equal(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
334 
335  /* 0 as replace removes characters */
336  strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
337  assert_false(string_mod(buf, CC_PRINT, 0, '\0'));
338  assert_string_equal(buf, "There is a nice 1234 year old tr ee!");
339 
340  strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
341  assert_false(string_mod(buf, CC_PRINT, CC_DIGIT, '@'));
342  assert_string_equal(buf, "There is @ a nice @@@@ year old tr@ ee!");
343 
344  strcpy(buf, "There is \x01 a nice 1234 year old tr\x7f ee!");
345  assert_false(string_mod(buf, CC_ALPHA, CC_DIGIT, '.'));
346  assert_string_equal(buf, "There.is...a.nice......year.old.tr..ee.");
347 
348  strcpy(buf, "There is \x01 a 'nice' \"1234\"\n year old \ntr\x7f ee!");
350  assert_string_equal(buf, "There.is...a.'nice'..1234.\n.year.old.\ntr..ee.");
351 
352  strcpy(buf, "There is a \\'nice\\' \"1234\" [*] year old \ntree!");
353  assert_false(string_mod(buf, CC_PRINT, CC_BACKSLASH|CC_ASTERISK, '.'));
354  assert_string_equal(buf, "There is a .'nice.' \"1234\" [.] year old .tree!");
355 }
356 
357 
358 static void
360 {
361  struct gc_arena gc = gc_new();
362 
363  struct buffer buf = alloc_buf_gc(1024, &gc);
364 
365  const char test1[] = "There is a nice 1234\x00 year old tree!";
366  buf_write(&buf, test1, sizeof(test1));
367 
368  /* allow the null bytes and string but not the ! */
369  assert_false(string_check_buf(&buf, CC_ALNUM | CC_SPACE | CC_NULL, 0));
370 
371  /* remove final ! and null byte to pass */
372  buf_inc_len(&buf, -2);
373  assert_true(string_check_buf(&buf, CC_ALNUM | CC_SPACE | CC_NULL, 0));
374 
375  /* Check excluding digits works */
376  assert_false(string_check_buf(&buf, CC_ALNUM | CC_SPACE | CC_NULL, CC_DIGIT));
377  gc_free(&gc);
378 }
379 
380 static void
381 test_snprintf(void **state)
382 {
383  /* we used to have a custom openvpn_snprintf function because some
384  * OS (the comment did not specify which) did not always put the
385  * null byte there. So we unit test this to be sure.
386  *
387  * This probably refers to the MSVC behaviour, see also
388  * https://stackoverflow.com/questions/7706936/is-snprintf-always-null-terminating
389  */
390 
391  /* Instead of trying to trick the compiler here, disable the warnings
392  * for this unit test. We know that the results will be truncated
393  * and we want to test that */
394 #if defined(__GNUC__)
395 /* some clang version do not understand -Wformat-truncation, so ignore the
396  * warning to avoid warnings/errors (-Werror) about unknown pragma/option */
397 #if defined(__clang__)
398 #pragma clang diagnostic push
399 #pragma clang diagnostic ignored "-Wunknown-warning-option"
400 #endif
401 #pragma GCC diagnostic push
402 #pragma GCC diagnostic ignored "-Wformat-truncation"
403 #endif
404 
405  char buf[10] = { 'a' };
406  int ret = 0;
407 
408  ret = snprintf(buf, sizeof(buf), "0123456789abcde");
409  assert_int_equal(ret, 15);
410  assert_int_equal(buf[9], '\0');
411 
412  memset(buf, 'b', sizeof(buf));
413  ret = snprintf(buf, sizeof(buf), "- %d - %d -", 77, 88);
414  assert_int_equal(ret, 11);
415  assert_int_equal(buf[9], '\0');
416 
417  memset(buf, 'c', sizeof(buf));
418  ret = snprintf(buf, sizeof(buf), "- %8.2f", 77.8899);
419  assert_int_equal(ret, 10);
420  assert_int_equal(buf[9], '\0');
421 
422 #if defined(__GNUC__)
423 #pragma GCC diagnostic pop
424 #if defined(__clang__)
425 #pragma clang diagnostic pop
426 #endif
427 #endif
428 }
429 
430 int
431 main(void)
432 {
434  const struct CMUnitTest tests[] = {
435  cmocka_unit_test(test_buffer_strprefix),
436  cmocka_unit_test(test_buffer_printf_catrunc),
437  cmocka_unit_test(test_buffer_format_hex_ex),
438  cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_empty,
441  cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_noop,
444  cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_two,
447  cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_all,
450  cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_nosep,
453  cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_zerolen,
456  cmocka_unit_test_setup_teardown(test_buffer_list_aggregate_separator_emptybuffers,
459  cmocka_unit_test(test_buffer_free_gc_one),
460  cmocka_unit_test(test_buffer_free_gc_two),
461  cmocka_unit_test(test_buffer_gc_realloc),
462  cmocka_unit_test(test_character_class),
463  cmocka_unit_test(test_character_string_mod_buf),
464  cmocka_unit_test(test_snprintf)
465  };
466 
467  return cmocka_run_group_tests_name("buffer", tests, NULL, NULL);
468 }
gc_arena::list
struct gc_entry * list
First element of the linked list of gc_entry structures.
Definition: buffer.h:118
test_buffer_list_aggregate_separator_all
static void test_buffer_list_aggregate_separator_all(void **state)
Definition: test_buffer.c:201
CC_BACKSLASH
#define CC_BACKSLASH
backslash
Definition: buffer.h:905
test_buffer_list_aggregate_ctx::empty_buffers
struct buffer_list * empty_buffers
Definition: test_buffer.c:122
test_character_class
static void test_character_class(void **state)
Definition: test_buffer.c:324
test_buffer_free_gc_two
static void test_buffer_free_gc_two(void **state)
Definition: test_buffer.c:265
assert_buf_equals_str
#define assert_buf_equals_str(buf, str)
Definition: test_buffer.c:54
gc_new
static struct gc_arena gc_new(void)
Definition: buffer.h:1030
gc_entry::next
struct gc_entry * next
Pointer to the next item in the linked list.
Definition: buffer.h:89
test_common.h
CC_ASTERISK
#define CC_ASTERISK
asterisk
Definition: buffer.h:921
alloc_buf_gc
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:88
gc_entry
Garbage collection entry for one dynamically allocated block of memory.
Definition: buffer.h:87
buffer_list_peek
struct buffer * buffer_list_peek(struct buffer_list *ol)
Retrieve the head buffer.
Definition: buffer.c:1257
buffer_list_aggregate_separator
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:1270
test_buffer_list_aggregate_ctx::empty
struct buffer_list * empty
Definition: test_buffer.c:119
format_hex_ex
char * format_hex_ex(const uint8_t *data, int size, int maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Definition: buffer.c:501
test_buffer_format_hex_ex
static void test_buffer_format_hex_ex(void **state)
Definition: test_buffer.c:84
testnosep
#define testnosep
Definition: test_buffer.c:48
CC_ALNUM
#define CC_ALNUM
alphanumeric isalnum()
Definition: buffer.h:891
test_buffer_list_aggregate_ctx
Definition: test_buffer.c:118
test_buffer_list_aggregate_separator_zerolen
static void test_buffer_list_aggregate_separator_zerolen(void **state)
Definition: test_buffer.c:226
buffer_list_push_data
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:1230
CC_NEWLINE
#define CC_NEWLINE
newline
Definition: buffer.h:902
test_buffer_strprefix
static void test_buffer_strprefix(void **state)
Definition: test_buffer.c:38
CC_DOUBLE_QUOTE
#define CC_DOUBLE_QUOTE
double quote
Definition: buffer.h:913
test_buffer_printf_catrunc
static void test_buffer_printf_catrunc(void **state)
Definition: test_buffer.c:59
buf_inc_len
static bool buf_inc_len(struct buffer *buf, int inc)
Definition: buffer.h:595
CC_SINGLE_QUOTE
#define CC_SINGLE_QUOTE
single quote
Definition: buffer.h:912
BLEN
#define BLEN(buf)
Definition: buffer.h:127
CC_PRINT
#define CC_PRINT
printable (>= 32, != 127)
Definition: buffer.h:896
test_buffer_list_aggregate_separator_emptybuffers
static void test_buffer_list_aggregate_separator_emptybuffers(void **state)
Definition: test_buffer.c:239
string_mod
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:1059
buffer_list_push
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:1216
teststr3
#define teststr3
Definition: test_buffer.c:51
string_check_buf
bool string_check_buf(struct buffer *buf, const unsigned int inclusive, const unsigned int exclusive)
Check a buffer if it only consists of allowed characters.
Definition: buffer.c:1091
CC_DIGIT
#define CC_DIGIT
digit isdigit()
Definition: buffer.h:895
CC_BLANK
#define CC_BLANK
space or tab
Definition: buffer.h:901
test_buffer_list_aggregate_ctx::zero_length_strings
struct buffer_list * zero_length_strings
Definition: test_buffer.c:121
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
buffer_list::size
int size
Definition: buffer.h:1129
buffer_list_new
struct buffer_list * buffer_list_new(void)
Allocate an empty buffer list of capacity max_size.
Definition: buffer.c:1176
CC_SPACE
#define CC_SPACE
whitespace isspace()
Definition: buffer.h:898
buf_write
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition: buffer.h:673
CC_ANY
#define CC_ANY
any character
Definition: buffer.h:888
buffer.h
syshead.h
testsep
#define testsep
Definition: test_buffer.c:47
CC_ALPHA
#define CC_ALPHA
alphabetic isalpha()
Definition: buffer.h:892
gc_arena
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
free_buf_gc
static void free_buf_gc(struct buffer *buf, struct gc_arena *gc)
Definition: buffer.c:190
openvpn_unit_test_setup
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:36
test_buffer_free_gc_one
static void test_buffer_free_gc_one(void **state)
Definition: test_buffer.c:252
main
int main(void)
Definition: test_buffer.c:431
strprefix
static bool strprefix(const char *str, const char *prefix)
Return true iff str starts with prefix.
Definition: buffer.h:982
gc_free
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1038
test_buffer_list_aggregate_separator_nosep
static void test_buffer_list_aggregate_separator_nosep(void **state)
Definition: test_buffer.c:214
test_buffer_list_aggregate_separator_empty
static void test_buffer_list_aggregate_separator_empty(void **state)
Definition: test_buffer.c:163
config.h
buffer_list_free
void buffer_list_free(struct buffer_list *ol)
Frees a buffer list and all the buffers in it.
Definition: buffer.c:1185
teststr2
#define teststr2
Definition: test_buffer.c:50
CC_NULL
#define CC_NULL
null character \0
Definition: buffer.h:889
test_buffer_list_aggregate_ctx::one_two_three
struct buffer_list * one_two_three
Definition: test_buffer.c:120
teststr1
#define teststr1
Definition: test_buffer.c:49
test_buffer_list_setup
static int test_buffer_list_setup(void **state)
Definition: test_buffer.c:126
test_buffer_gc_realloc
static void test_buffer_gc_realloc(void **state)
Definition: test_buffer.c:295
buffer_list
Definition: buffer.h:1125
test_buffer_list_aggregate_separator_noop
static void test_buffer_list_aggregate_separator_noop(void **state)
Definition: test_buffer.c:173
gc_realloc
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:388
test_buffer_list_teardown
static int test_buffer_list_teardown(void **state)
Definition: test_buffer.c:150
buf_printf
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:240
buffer_list::head
struct buffer_entry * head
Definition: buffer.h:1127
buffer.c
test_snprintf
static void test_snprintf(void **state)
Definition: test_buffer.c:381
test_buffer_list_aggregate_separator_two
static void test_buffer_list_aggregate_separator_two(void **state)
Definition: test_buffer.c:185
buffer::data
uint8_t * data
Pointer to the allocated memory.
Definition: buffer.h:68
buf_catrunc
void buf_catrunc(struct buffer *buf, const char *str)
Definition: buffer.c:287
test_character_string_mod_buf
static void test_character_string_mod_buf(void **state)
Definition: test_buffer.c:359