From 271a1f830acb229c380ae95c6c2e4c4df367fa82 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Mon, 2 Dec 2019 15:39:30 -0500 Subject: Beef up XDR unit tests. --- tests/test-xdr.c | 426 +++++++++++++++++++++++++++++++++++++++++++++++-------- xdr.c | 22 ++- 2 files changed, 391 insertions(+), 57 deletions(-) diff --git a/tests/test-xdr.c b/tests/test-xdr.c index f084e01..6f4eadc 100644 --- a/tests/test-xdr.c +++ b/tests/test-xdr.c @@ -42,70 +42,384 @@ #include "hal_internal.h" /* htonl/ntohl */ #include "xdr_internal.h" -static void hexdump(uint8_t *buf, uint32_t len) +static int verbose = 0; + +/* suppress assert() error messages */ +void hal_log(const hal_log_level_t level, const char *format, ...) { - for (uint32_t i = 0; i < len; ++i) - printf("%02x%c", buf[i], ((i & 0x07) == 0x07) ? '\n' : ' '); - if ((len & 0x07) != 0) - printf("\n"); } -int main(int argc, char *argv[]) +#define DEFINE_HAL_ERROR(_code_,_text_) #_code_, +static char *err_name[] = { HAL_ERROR_LIST }; +#undef DEFINE_HAL_ERROR + +static void hexdump(uint8_t *buf, uint32_t len) { - uint32_t i; - uint8_t buf[256] = {0}; - uint8_t *bufptr = buf; - const uint8_t *readptr; - uint8_t *limit = buf + sizeof(buf); - hal_error_t ret; - uint8_t alphabet[] = "abcdefghijklmnopqrstuvwxyz"; - uint8_t readbuf[256] = {0}; - - printf("hal_xdr_encode_int: work to failure\n"); - for (i = 1; i < 100; ++i) { - if ((ret = hal_xdr_encode_int(&bufptr, limit, i)) != HAL_OK) { - printf("%d: %s\n", i, hal_error_string(ret)); - break; - } + for (uint32_t i = 0; i < len; ++i) { + printf("%02x", buf[i]); + if (i < len - 1) + printf(" "); } - hexdump(buf, ((uint8_t *)bufptr - buf)); - - printf("\nhal_xdr_decode_int:\n"); - readptr = buf; - while (readptr < bufptr) { - if ((ret = hal_xdr_decode_int(&readptr, limit, &i)) != HAL_OK) { - printf("%s\n", hal_error_string(ret)); - break; - } - printf("%u ", i); +} + +#define test(name, result, expected) \ + if ((err = result) != expected) { \ + if (!verbose) printf("%s: ", func); \ + printf("%s test returned %s, expected %s\n", \ + name, err_name[err], err_name[expected]); \ + ++nerr; \ } - printf("\n"); - printf("\nhal_xdr_encode_variable_opaque: work to failure\n"); - memset(buf, 0, sizeof(buf)); - bufptr = buf; - for (i = 1; ; ++i) { - if ((ret = hal_xdr_encode_variable_opaque(&bufptr, limit, alphabet, i)) != HAL_OK) { - printf("%d: %s\n", i, hal_error_string(ret)); - break; - } +#define test_value(val, exp) \ + if (val != exp) { \ + if (!verbose) printf("%s: ", func); \ + printf("value = %u, expected %u\n", val, exp); \ + ++nerr; \ + } + +#define test_len(len, exp) \ + if (len != exp) { \ + if (!verbose) printf("%s: ", func); \ + printf("len = %lu, expected %u\n", len, exp); \ + ++nerr; \ + } + +#define test_memcmp(buf, exp, len) \ + if (memcmp(buf, exp, len) != 0) { \ + if (!verbose) printf("%s: ", func); \ + printf("buffer = ["); \ + hexdump(buf, len); \ + printf("], expected ["); \ + hexdump(exp, len); \ + printf("]\n"); \ + ++nerr; \ } - hexdump(buf, ((uint8_t *)bufptr - buf)); - - printf("\nhal_xdr_decode_variable_opaque:\n"); - readptr = buf; - while (readptr < bufptr) { - size_t len; - if ((ret = hal_xdr_decode_variable_opaque(&readptr, limit, readbuf, &len, bufptr - readptr)) != HAL_OK) { - printf("%s\n", hal_error_string(ret)); - break; - } - printf("%lu: ", len); - for (size_t j = 0; j < len; ++j) - putchar(readbuf[j]); - putchar('\n'); - memset(readbuf, 0, sizeof(readbuf)); + +#define test_bufptr(bfp, exp) \ + if (bfp != exp) { \ + if (!verbose) printf("%s: ", func); \ + printf("buf ptr = %p, expected %p\n", bfp, exp); \ + ++nerr; \ } - return 0; +static int test_hal_xdr_encode_int(void) +{ + hal_error_t err = HAL_OK; + int nerr = 0; + uint8_t *null = NULL; + uint8_t buf[4] = {0}; + uint8_t *bufptr = buf; + uint8_t *limit = buf + sizeof(buf); + uint8_t exp[4] = { 0x00, 0x11, 0x22, 0x33 }; + uint32_t value = 0x00112233; + const char *func = "hal_xdr_encode_int"; + + if (verbose) + printf("%s... ", func); + + test("null outbuf", hal_xdr_encode_int(NULL, limit, value), HAL_ERROR_ASSERTION_FAILED); + test("null outbuf", hal_xdr_encode_int(&null, limit, value), HAL_ERROR_ASSERTION_FAILED); + test("null limit", hal_xdr_encode_int(&bufptr, NULL, value), HAL_ERROR_ASSERTION_FAILED); + test("outbuf overflow", hal_xdr_encode_int(&bufptr, buf, value), HAL_ERROR_XDR_BUFFER_OVERFLOW); + test("outbuf overflow", hal_xdr_encode_int(&bufptr, buf + 3, value), HAL_ERROR_XDR_BUFFER_OVERFLOW); + + test("valid write", hal_xdr_encode_int(&bufptr, limit, value), HAL_OK); + test_memcmp(buf, exp, sizeof(exp)); + test_bufptr(bufptr, buf + 4); + + if (verbose && nerr == 0) + printf("PASS\n"); + + return nerr; +} + +static int test_hal_xdr_decode_int(void) +{ + hal_error_t err = HAL_OK; + int nerr = 0; + const uint8_t *null = NULL; + const uint8_t buf[4] = { 0x00, 0x11, 0x22, 0x33 }; + const uint8_t *bufptr = buf; + const uint8_t * const limit = buf + sizeof(buf); + uint32_t value = 0; + const uint32_t exp = 0x00112233; + const char *func = "hal_xdr_decode_int"; + + if (verbose) + printf("%s... ", func); + + test("null inbuf", hal_xdr_decode_int(NULL, limit, &value), HAL_ERROR_ASSERTION_FAILED); + test("null inbuf", hal_xdr_decode_int(&null, limit, &value), HAL_ERROR_ASSERTION_FAILED); + test("null limit", hal_xdr_decode_int(&bufptr, NULL, &value), HAL_ERROR_ASSERTION_FAILED); + test("null value", hal_xdr_decode_int(&bufptr, limit, NULL), HAL_ERROR_ASSERTION_FAILED); + + test("inbuf overflow", hal_xdr_decode_int(&bufptr, buf, &value), HAL_ERROR_XDR_BUFFER_OVERFLOW); + test("inbuf overflow", hal_xdr_decode_int(&bufptr, buf + 3, &value), HAL_ERROR_XDR_BUFFER_OVERFLOW); + + test("valid read", hal_xdr_decode_int(&bufptr, limit, &value), HAL_OK); + test_value(value, exp); + test_bufptr(bufptr, buf + 4); + + if (verbose && nerr == 0) + printf("PASS\n"); + + return nerr; +} + +static int test_hal_xdr_decode_int_peek(void) +{ + hal_error_t err = HAL_OK; + int nerr = 0; + const uint8_t buf[4] = { 0x00, 0x11, 0x22, 0x33 }; + const uint8_t *bufptr = buf; + const uint8_t * const limit = buf + sizeof(buf); + uint32_t value = 0; + const uint32_t exp = 0x00112233; + const char *func = "hal_xdr_decode_int_peek"; + + if (verbose) + printf("%s... ", func); + + test("valid read", hal_xdr_decode_int_peek(&bufptr, limit, &value), HAL_OK); + test_value(value, exp); + test_bufptr(bufptr, buf); + + if (verbose && nerr == 0) + printf("PASS\n"); + + return nerr; +} + +static int test_hal_xdr_encode_fixed_opaque(void) +{ + hal_error_t err = HAL_OK; + int nerr = 0; + uint8_t *null = NULL; + uint8_t buf[8]; + uint8_t *bufptr = buf; + uint8_t *limit = buf + sizeof(buf); + uint8_t src[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + uint8_t exp3[4] = { 0x00, 0x11, 0x22, 0x00 }; + uint8_t exp4[4] = { 0x00, 0x11, 0x22, 0x33 }; + uint8_t exp5[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00 }; + const char *func = "hal_xdr_encode_fixed_opaque"; + + if (verbose) + printf("%s... ", func); + + test("null outbuf", hal_xdr_encode_fixed_opaque(NULL, limit, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); + test("null outbuf", hal_xdr_encode_fixed_opaque(&null, limit, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); + test("null limit", hal_xdr_encode_fixed_opaque(&bufptr, NULL, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); + test("null value", hal_xdr_encode_fixed_opaque(&bufptr, limit, NULL, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); + test("outbuf overflow", hal_xdr_encode_fixed_opaque(&bufptr, buf, src, sizeof(src)), HAL_ERROR_XDR_BUFFER_OVERFLOW); + + memset(buf, 0xff, sizeof(buf)); + test("write 3", hal_xdr_encode_fixed_opaque(&bufptr, limit, src, 3), HAL_OK); + test_memcmp(buf, exp3, sizeof(exp3)); + test_bufptr(bufptr, buf + 4); + + bufptr = buf; + memset(buf, 0xff, sizeof(buf)); + test("write 4", hal_xdr_encode_fixed_opaque(&bufptr, limit, src, 4), HAL_OK); + test_memcmp(buf, exp4, sizeof(exp4)); + test_bufptr(bufptr, buf + 4) + + bufptr = buf; + memset(buf, 0xff, sizeof(buf)); + test("write 5", hal_xdr_encode_fixed_opaque(&bufptr, limit, src, 5), HAL_OK); + test_memcmp(buf, exp5, sizeof(exp5)); + test_bufptr(bufptr, buf + 8); + + bufptr = buf; + memset(buf, 0xff, sizeof(buf)); + test("write 8", hal_xdr_encode_fixed_opaque(&bufptr, limit, src, 8), HAL_OK); + test_memcmp(buf, src, sizeof(src)); + test_bufptr(bufptr, buf + 8) + + if (verbose && nerr == 0) + printf("PASS\n"); + + return nerr; +} + +static int test_hal_xdr_decode_fixed_opaque(void) +{ + hal_error_t err = HAL_OK; + int nerr = 0; + const uint8_t *null = NULL; + const uint8_t buf[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + const uint8_t *bufptr = buf; + const uint8_t *limit = buf + sizeof(buf); + uint8_t value[8]; + uint8_t exp3[4] = { 0x00, 0x11, 0x22, 0x00 }; + uint8_t exp4[4] = { 0x00, 0x11, 0x22, 0x33 }; + uint8_t exp5[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00 }; + const char *func = "hal_xdr_decode_fixed_opaque"; + + if (verbose) + printf("%s... ", func); + + test("null inbuf", hal_xdr_decode_fixed_opaque(NULL, limit, value, sizeof(value)), HAL_ERROR_ASSERTION_FAILED); + test("null inbuf", hal_xdr_decode_fixed_opaque(&null, limit, value, sizeof(value)), HAL_ERROR_ASSERTION_FAILED); + test("null limit", hal_xdr_decode_fixed_opaque(&bufptr, NULL, value, sizeof(value)), HAL_ERROR_ASSERTION_FAILED); + test("null value", hal_xdr_decode_fixed_opaque(&bufptr, limit, NULL, sizeof(value)), HAL_ERROR_ASSERTION_FAILED); + test("inbuf overflow", hal_xdr_decode_fixed_opaque(&bufptr, buf, value, sizeof(value)), HAL_ERROR_XDR_BUFFER_OVERFLOW); + + memset(value, 0xff, sizeof(value)); + test("read 3", hal_xdr_decode_fixed_opaque(&bufptr, limit, value, 3), HAL_OK); + test_memcmp(value, exp3, sizeof(exp3)); + test_bufptr(bufptr, buf + 4); + + bufptr = buf; + memset(value, 0xff, sizeof(value)); + test("read 4", hal_xdr_decode_fixed_opaque(&bufptr, limit, value, 4), HAL_OK); + test_memcmp(value, exp4, sizeof(exp4)); + test_bufptr(bufptr, buf + 4); + + bufptr = buf; + memset(value, 0xff, sizeof(value)); + test("read 5", hal_xdr_decode_fixed_opaque(&bufptr, limit, value, 5), HAL_OK); + test_memcmp(value, exp5, sizeof(exp5)); + test_bufptr(bufptr, buf + 8); + + if (verbose && nerr == 0) + printf("PASS\n"); + + return nerr; +} + +static int test_hal_xdr_encode_variable_opaque(void) +{ + hal_error_t err = HAL_OK; + int nerr = 0; + uint8_t *null = NULL; + uint8_t buf[12]; + uint8_t *bufptr = buf; + uint8_t *limit = buf + sizeof(buf); + uint8_t src[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + uint8_t exp3[8] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x11, 0x22, 0x00 }; + uint8_t exp4[8] = { 0x00, 0x00, 0x00, 0x04, 0x00, 0x11, 0x22, 0x33 }; + uint8_t exp5[12] = { 0x00, 0x00, 0x00, 0x05, 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00 }; + uint8_t exp8[12] = { 0x00, 0x00, 0x00, 0x08, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + const char *func = "hal_xdr_encode_variable_opaque"; + + if (verbose) + printf("%s... ", func); + + test("null outbuf", hal_xdr_encode_variable_opaque(NULL, limit, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); + test("null outbuf", hal_xdr_encode_variable_opaque(&null, limit, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); + test("null limit", hal_xdr_encode_variable_opaque(&bufptr, NULL, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); + test("null value", hal_xdr_encode_variable_opaque(&bufptr, limit, NULL, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); + test("outbuf overflow", hal_xdr_encode_variable_opaque(&bufptr, buf, src, sizeof(src)), HAL_ERROR_XDR_BUFFER_OVERFLOW); + + memset(buf, 0xff, sizeof(buf)); + test("write 3", hal_xdr_encode_variable_opaque(&bufptr, limit, src, 3), HAL_OK); + test_memcmp(buf, exp3, sizeof(exp3)); + test_bufptr(bufptr, buf + 8); + + bufptr = buf; + memset(buf, 0xff, sizeof(buf)); + test("write 4", hal_xdr_encode_variable_opaque(&bufptr, limit, src, 4), HAL_OK); + test_memcmp(buf, exp4, sizeof(exp4)); + test_bufptr(bufptr, buf + 8) + + bufptr = buf; + memset(buf, 0xff, sizeof(buf)); + test("write 5", hal_xdr_encode_variable_opaque(&bufptr, limit, src, 5), HAL_OK); + test_memcmp(buf, exp5, sizeof(exp5)); + test_bufptr(bufptr, buf + 12); + + bufptr = buf; + memset(buf, 0xff, sizeof(buf)); + test("write 8", hal_xdr_encode_variable_opaque(&bufptr, limit, src, 8), HAL_OK); + test_memcmp(buf, exp8, sizeof(exp8)); + test_bufptr(bufptr, buf + 12) + + if (verbose && nerr == 0) + printf("PASS\n"); + + return nerr; +} + +static int test_hal_xdr_decode_variable_opaque(void) +{ + hal_error_t err = HAL_OK; + int nerr = 0; + const uint8_t *null = NULL; + uint8_t buf[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + const uint8_t *bufptr = buf; + const uint8_t *limit = buf + sizeof(buf); + uint8_t value[12]; + size_t len; + uint8_t exp3[4] = { 0x00, 0x11, 0x22, 0x00 }; + uint8_t exp4[4] = { 0x00, 0x11, 0x22, 0x33 }; + uint8_t exp5[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00 }; + uint8_t exp8[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + const char *func = "hal_xdr_decode_variable_opaque"; + + if (verbose) + printf("%s... ", func); + + test("null inbuf", hal_xdr_decode_variable_opaque(NULL, limit, value, &len, sizeof(value)), HAL_ERROR_ASSERTION_FAILED); + test("null inbuf", hal_xdr_decode_variable_opaque(&null, limit, value, &len, sizeof(value)), HAL_ERROR_ASSERTION_FAILED); + test("null limit", hal_xdr_decode_variable_opaque(&bufptr, NULL, value, &len, sizeof(value)), HAL_ERROR_ASSERTION_FAILED); + test("null value", hal_xdr_decode_variable_opaque(&bufptr, limit, NULL, &len, sizeof(value)), HAL_ERROR_ASSERTION_FAILED); + test("inbuf overflow", hal_xdr_decode_variable_opaque(&bufptr, buf, value, &len, sizeof(value)), HAL_ERROR_XDR_BUFFER_OVERFLOW); + + buf[3] = 0x03; + memset(value, 0xff, sizeof(value)); + test("read 3", hal_xdr_decode_variable_opaque(&bufptr, limit, value, &len, sizeof(value)), HAL_OK); + test_len(len, 3); + test_memcmp(value, exp3, sizeof(exp3)); + test_bufptr(bufptr, buf + 8); + + bufptr = buf; + buf[3] = 0x04; + memset(value, 0xff, sizeof(value)); + test("read 4", hal_xdr_decode_variable_opaque(&bufptr, limit, value, &len, sizeof(value)), HAL_OK); + test_len(len, 4); + test_memcmp(value, exp4, sizeof(exp4)); + test_bufptr(bufptr, buf + 8); + + bufptr = buf; + buf[3] = 0x05; + memset(value, 0xff, sizeof(value)); + test("read 5", hal_xdr_decode_variable_opaque(&bufptr, limit, value, &len, sizeof(value)), HAL_OK); + test_len(len, 5); + test_memcmp(value, exp5, sizeof(exp5)); + test_bufptr(bufptr, buf + 12); + + bufptr = buf; + buf[3] = 0x08; + memset(value, 0xff, sizeof(value)); + test("read 8", hal_xdr_decode_variable_opaque(&bufptr, limit, value, &len, sizeof(value)), HAL_OK); + test_len(len, 8); + test_memcmp(value, exp8, sizeof(exp8)); + test_bufptr(bufptr, buf + 12); + + if (verbose && nerr == 0) + printf("PASS\n"); + + return nerr; +} + + +int main(int argc, char *argv[]) +{ + if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'v') + verbose = 1; + + int nerr = 0; + nerr += test_hal_xdr_encode_int(); + nerr += test_hal_xdr_decode_int(); + nerr += test_hal_xdr_decode_int_peek(); + nerr += test_hal_xdr_encode_fixed_opaque(); + nerr += test_hal_xdr_decode_fixed_opaque(); + nerr += test_hal_xdr_encode_variable_opaque(); + nerr += test_hal_xdr_decode_variable_opaque(); + + if (nerr) + printf("%d failures\n", nerr); + + return nerr; } diff --git a/xdr.c b/xdr.c index 92c2b64..3c02635 100644 --- a/xdr.c +++ b/xdr.c @@ -94,6 +94,9 @@ hal_error_t hal_xdr_encode_fixed_opaque(uint8_t ** const outbuf, const uint8_t * /* arg checks */ hal_assert(outbuf != NULL && *outbuf != NULL && limit != NULL && limit >= *outbuf && (value != NULL || len == 0)); + if (len == 0) + return HAL_OK; + /* buffer overflow check */ /* We need to explicitly check (len > 0xfffffffc) because padding will * round it up to 0. @@ -135,11 +138,22 @@ hal_error_t hal_xdr_decode_fixed_opaque(const uint8_t ** const inbuf, const uint const uint8_t *p; hal_error_t err; + /* arg checks */ + hal_assert(value != NULL || len == 0); + + if (len == 0) + return HAL_OK; + /* get and advance the input data pointer */ - if ((err = hal_xdr_decode_fixed_opaque_ptr(inbuf, limit, &p, len)) == HAL_OK) + if ((err = hal_xdr_decode_fixed_opaque_ptr(inbuf, limit, &p, len)) == HAL_OK) { /* read the data */ memcpy(value, p, len); + /* pad if necessary */ + for (size_t i = len; (i & 3) != 0; ++i) + value[i] = 0; + } + return err; } @@ -204,8 +218,14 @@ hal_error_t hal_xdr_decode_variable_opaque(const uint8_t ** const inbuf, const u /* user buffer overflow check */ if (len_max < xdr_len) return HAL_ERROR_XDR_BUFFER_OVERFLOW; + /* read the data */ memcpy(value, p, xdr_len); + + /* pad if necessary */ + for (size_t i = xdr_len; (i & 3) != 0; ++i) + value[i] = 0; + *len = xdr_len; } -- cgit v1.2.3