diff options
| author | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 | 
|---|---|---|
| committer | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 | 
| commit | 33a9b234e7087f573ef08cd7318c6497ba08b439 (patch) | |
| tree | d0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/util/support/t_k5buf.c | |
Diffstat (limited to 'src/util/support/t_k5buf.c')
| -rw-r--r-- | src/util/support/t_k5buf.c | 260 | 
1 files changed, 260 insertions, 0 deletions
diff --git a/src/util/support/t_k5buf.c b/src/util/support/t_k5buf.c new file mode 100644 index 000000000000..ba86851dc47b --- /dev/null +++ b/src/util/support/t_k5buf.c @@ -0,0 +1,260 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* util/support/t_k5buf.c - Test the k5buf string buffer module */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + *   require a specific license from the United States Government. + *   It is the responsibility of any person or organization contemplating + *   export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission.  Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-platform.h" +#include "k5-buf.h" +#include <stdio.h> +#include <stdlib.h> + +static void +fail_if(int condition, const char *name) +{ +    if (condition) { +        fprintf(stderr, "%s failed\n", name); +        exit(1); +    } +} + +/* Test the invariants of a buffer. */ +static void +check_buf(struct k5buf *buf, const char *name) +{ +    fail_if(buf->buftype != K5BUF_FIXED && buf->buftype != K5BUF_DYNAMIC && +            buf->buftype != K5BUF_ERROR, name); +    if (buf->buftype == K5BUF_ERROR) { +        fail_if(buf->data != NULL, name); +        fail_if(buf->space != 0 || buf->len != 0, name); +    } else { +        fail_if(buf->space == 0, name); +        fail_if(buf->len >= buf->space, name); +        fail_if(((char *)buf->data)[buf->len] != 0, name); +    } +} + +static void +test_basic() +{ +    struct k5buf buf; +    char storage[1024]; + +    k5_buf_init_fixed(&buf, storage, sizeof(storage)); +    k5_buf_add(&buf, "Hello "); +    k5_buf_add_len(&buf, "world", 5); +    check_buf(&buf, "basic fixed"); +    fail_if(buf.data == NULL || buf.len != 11, "basic fixed"); +    fail_if(strcmp(buf.data, "Hello world") != 0, "basic fixed"); + +    k5_buf_init_dynamic(&buf); +    k5_buf_add_len(&buf, "Hello", 5); +    k5_buf_add(&buf, " world"); +    check_buf(&buf, "basic dynamic"); +    fail_if(buf.data == NULL || buf.len != 11, "basic dynamic"); +    fail_if(strcmp(buf.data, "Hello world") != 0, "basic dynamic"); +    k5_buf_free(&buf); +} + +static void +test_realloc() +{ +    struct k5buf buf; +    char data[1024]; +    size_t i; + +    for (i = 0; i < sizeof(data); i++) +        data[i] = 'a'; + +    /* Cause the buffer size to double from 128 to 256 bytes. */ +    k5_buf_init_dynamic(&buf); +    k5_buf_add_len(&buf, data, 10); +    k5_buf_add_len(&buf, data, 128); +    fail_if(buf.space != 256, "realloc 1"); +    check_buf(&buf, "realloc 1"); +    fail_if(buf.data == NULL || buf.len != 138, "realloc 1"); +    fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 1"); + +    /* Cause the same buffer to double in size to 512 bytes. */ +    k5_buf_add_len(&buf, data, 128); +    fail_if(buf.space != 512, "realloc 2"); +    check_buf(&buf, "realloc 2"); +    fail_if(buf.data == NULL || buf.len != 266, "realloc 2"); +    fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 2"); +    k5_buf_free(&buf); + +    /* Cause a buffer to increase from 128 to 512 bytes directly. */ +    k5_buf_init_dynamic(&buf); +    k5_buf_add_len(&buf, data, 10); +    k5_buf_add_len(&buf, data, 256); +    fail_if(buf.space != 512, "realloc 3"); +    check_buf(&buf, "realloc 3"); +    fail_if(buf.data == NULL || buf.len != 266, "realloc 3"); +    fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 3"); +    k5_buf_free(&buf); + +    /* Cause a buffer to increase from 128 to 1024 bytes directly. */ +    k5_buf_init_dynamic(&buf); +    k5_buf_add_len(&buf, data, 10); +    k5_buf_add_len(&buf, data, 512); +    fail_if(buf.space != 1024, "realloc 4"); +    check_buf(&buf, "realloc 4"); +    fail_if(buf.data == NULL || buf.len != 522, "realloc 4"); +    fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 4"); +    k5_buf_free(&buf); + +    /* Cause a reallocation to fail by integer overflow. */ +    k5_buf_init_dynamic(&buf); +    k5_buf_add_len(&buf, data, 100); +    k5_buf_add_len(&buf, NULL, SIZE_MAX); +    check_buf(&buf, "realloc 5"); +    fail_if(buf.buftype != K5BUF_ERROR, "realloc 5"); +    k5_buf_free(&buf); +} + +static void +test_overflow() +{ +    struct k5buf buf; +    char storage[10]; + +    /* Cause a fixed-sized buffer overflow. */ +    k5_buf_init_fixed(&buf, storage, sizeof(storage)); +    k5_buf_add(&buf, "12345"); +    k5_buf_add(&buf, "12345"); +    check_buf(&buf, "overflow 1"); +    fail_if(buf.buftype != K5BUF_ERROR, "overflow 1"); + +    /* Cause a fixed-sized buffer overflow with integer overflow. */ +    k5_buf_init_fixed(&buf, storage, sizeof(storage)); +    k5_buf_add(&buf, "12345"); +    k5_buf_add_len(&buf, NULL, SIZE_MAX); +    check_buf(&buf, "overflow 2"); +    fail_if(buf.buftype != K5BUF_ERROR, "overflow 2"); +} + +static void +test_error() +{ +    struct k5buf buf; +    char storage[1]; + +    /* Cause an overflow and then perform actions afterwards. */ +    k5_buf_init_fixed(&buf, storage, sizeof(storage)); +    k5_buf_add(&buf, "1"); +    fail_if(buf.buftype != K5BUF_ERROR, "error"); +    check_buf(&buf, "error"); +    k5_buf_add(&buf, "test"); +    check_buf(&buf, "error"); +    k5_buf_add_len(&buf, "test", 4); +    check_buf(&buf, "error"); +    k5_buf_truncate(&buf, 3); +    check_buf(&buf, "error"); +    fail_if(buf.buftype != K5BUF_ERROR, "error"); +} + +static void +test_truncate() +{ +    struct k5buf buf; + +    k5_buf_init_dynamic(&buf); +    k5_buf_add(&buf, "abcde"); +    k5_buf_add(&buf, "fghij"); +    k5_buf_truncate(&buf, 7); +    check_buf(&buf, "truncate"); +    fail_if(buf.data == NULL || buf.len != 7, "truncate"); +    fail_if(strcmp(buf.data, "abcdefg") != 0, "truncate"); +    k5_buf_free(&buf); +} + +static void +test_binary() +{ +    struct k5buf buf; +    char data[] = { 'a', 0, 'b' }, *s; + +    k5_buf_init_dynamic(&buf); +    k5_buf_add_len(&buf, data, 3); +    k5_buf_add_len(&buf, data, 3); +    check_buf(&buf, "binary"); +    fail_if(buf.data == NULL || buf.len != 6, "binary"); +    s = buf.data; +    fail_if(s[0] != 'a' || s[1] != 0 || s[2] != 'b', "binary"); +    fail_if(s[3] != 'a' || s[4] != 0 || s[5] != 'b', "binary"); +    k5_buf_free(&buf); +} + +static void +test_fmt() +{ +    struct k5buf buf; +    char storage[10], data[1024]; +    size_t i; + +    for (i = 0; i < sizeof(data) - 1; i++) +        data[i] = 'a'; +    data[i] = '\0'; + +    /* Format some text into a non-empty fixed buffer. */ +    k5_buf_init_fixed(&buf, storage, sizeof(storage)); +    k5_buf_add(&buf, "foo"); +    k5_buf_add_fmt(&buf, " %d ", 3); +    check_buf(&buf, "fmt 1"); +    fail_if(buf.data == NULL || buf.len != 6, "fmt 1"); +    fail_if(strcmp(buf.data, "foo 3 ") != 0, "fmt 1"); + +    /* Overflow the same buffer with formatted text. */ +    k5_buf_add_fmt(&buf, "%d%d%d%d", 1, 2, 3, 4); +    check_buf(&buf, "fmt 2"); +    fail_if(buf.buftype != K5BUF_ERROR, "fmt 2"); + +    /* Format some text into a non-empty dynamic buffer. */ +    k5_buf_init_dynamic(&buf); +    k5_buf_add(&buf, "foo"); +    k5_buf_add_fmt(&buf, " %d ", 3); +    check_buf(&buf, "fmt 3"); +    fail_if(buf.data == NULL || buf.len != 6, "fmt 3"); +    fail_if(strcmp(buf.data, "foo 3 ") != 0, "fmt 3"); + +    /* Format more text into the same buffer, causing a big resize. */ +    k5_buf_add_fmt(&buf, "%s", data); +    check_buf(&buf, "fmt 4"); +    fail_if(buf.space != 2048, "fmt 4"); +    fail_if(buf.data == NULL || buf.len != 1029, "fmt 4"); +    fail_if(strcmp((char *)buf.data + 6, data) != 0, "fmt 4"); +    k5_buf_free(&buf); +} + +int +main() +{ +    test_basic(); +    test_realloc(); +    test_overflow(); +    test_error(); +    test_truncate(); +    test_binary(); +    test_fmt(); +    return 0; +}  | 
