From ecdd0cd44807c15ae3562a5ba5f05d5ea722ad7b Mon Sep 17 00:00:00 2001 From: Marcelo Politzer <251334+mpolitzer@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:17:13 -0300 Subject: [PATCH] fix!: error values and improve coverage refactor: move read/write file to util - remove unreachable if block --- sys-utils/libcmt/src/abi.c | 8 +- sys-utils/libcmt/src/io-mock.c | 46 +------ sys-utils/libcmt/src/merkle.c | 6 + sys-utils/libcmt/src/util.c | 39 ++++++ sys-utils/libcmt/src/util.h | 25 ++++ sys-utils/libcmt/tests/abi-single.c | 194 ++++++++++++++++++++++++++-- sys-utils/libcmt/tests/buf.c | 56 +++++++- sys-utils/libcmt/tests/gio.c | 44 +------ sys-utils/libcmt/tests/io.c | 54 ++++++++ sys-utils/libcmt/tests/merkle.c | 51 ++++++-- sys-utils/libcmt/tests/rollup.c | 86 ++++++------ 11 files changed, 457 insertions(+), 152 deletions(-) create mode 100644 sys-utils/libcmt/tests/io.c diff --git a/sys-utils/libcmt/src/abi.c b/sys-utils/libcmt/src/abi.c index a68f298a..ac33963c 100644 --- a/sys-utils/libcmt/src/abi.c +++ b/sys-utils/libcmt/src/abi.c @@ -39,7 +39,7 @@ int cmt_abi_put_funsel(cmt_buf_t *me, uint32_t funsel) { int cmt_abi_encode_uint_nr(size_t n, const uint8_t *data, uint8_t out[CMT_WORD_LENGTH]) { if (n > CMT_WORD_LENGTH) { - return EDOM; + return -EDOM; } for (size_t i = 0; i < n; ++i) { out[CMT_WORD_LENGTH - 1 - i] = data[i]; @@ -52,7 +52,7 @@ int cmt_abi_encode_uint_nr(size_t n, const uint8_t *data, uint8_t out[CMT_WORD_L int cmt_abi_encode_uint_nn(size_t n, const uint8_t *data, uint8_t out[CMT_WORD_LENGTH]) { if (n > CMT_WORD_LENGTH) { - return EDOM; + return -EDOM; } for (size_t i = 0; i < CMT_WORD_LENGTH - n; ++i) { out[i] = 0; @@ -73,7 +73,7 @@ int cmt_abi_encode_uint(size_t n, const void *data, uint8_t out[CMT_WORD_LENGTH] int cmt_abi_decode_uint_nr(const uint8_t data[CMT_WORD_LENGTH], size_t n, uint8_t *out) { if (n > CMT_WORD_LENGTH) { - return EDOM; + return -EDOM; } for (size_t i = 0; i < CMT_WORD_LENGTH - n; ++i) { if (data[i]) { @@ -88,7 +88,7 @@ int cmt_abi_decode_uint_nr(const uint8_t data[CMT_WORD_LENGTH], size_t n, uint8_ int cmt_abi_decode_uint_nn(const uint8_t data[CMT_WORD_LENGTH], size_t n, uint8_t *out) { if (n > CMT_WORD_LENGTH) { - return EDOM; + return -EDOM; } for (size_t i = 0; i < CMT_WORD_LENGTH - n; ++i) { if (data[i]) { diff --git a/sys-utils/libcmt/src/io-mock.c b/sys-utils/libcmt/src/io-mock.c index 79a1dd7c..6e80dba7 100644 --- a/sys-utils/libcmt/src/io-mock.c +++ b/sys-utils/libcmt/src/io-mock.c @@ -25,9 +25,6 @@ /** track the number of open "devices". Mimic the kernel driver behavior by limiting it to 1 */ static int open_count = 0; -static int read_whole_file(const char *name, size_t max, void *data, size_t *length); -static int write_whole_file(const char *name, size_t length, const void *data); - int cmt_io_init(cmt_io_driver_t *_me) { if (!_me) { return -EINVAL; @@ -116,7 +113,7 @@ static int load_next_input(cmt_io_driver_mock_t *me, struct cmt_io_yield *rr) { } size_t file_length = 0; - int rc = read_whole_file(filepath, cmt_buf_length(me->rx), me->rx->begin, &file_length); + int rc = cmt_util_read_whole_file(filepath, cmt_buf_length(me->rx), me->rx->begin, &file_length); if (rc) { if (cmt_util_debug_enabled()) { (void) fprintf(stderr, "failed to load \"%s\". %s\n", filepath, strerror(-rc)); @@ -150,7 +147,7 @@ static int store_output(cmt_io_driver_mock_t *me, const char *filepath, struct c return -ENOBUFS; } - int rc = write_whole_file(filepath, rr->data, me->tx->begin); + int rc = cmt_util_write_whole_file(filepath, rr->data, me->tx->begin); if (rc) { (void) fprintf(stderr, "failed to store \"%s\". %s\n", filepath, strerror(-rc)); return rc; @@ -205,7 +202,7 @@ static int mock_rx_rejected(cmt_io_driver_mock_t *me, struct cmt_io_yield *rr) { } (void) fprintf(stderr, "%s:%d no revert for the mock implementation\n", __FILE__, __LINE__); if (load_next_input(me, rr)) { - return -1; + return -ENOSYS; } return 0; } @@ -255,9 +252,6 @@ static int mock_tx_gio(cmt_io_driver_mock_t *me, struct cmt_io_yield *rr) { /* These behaviours are defined by the cartesi-machine emulator */ static int cmt_io_yield_inner(cmt_io_driver_t *_me, struct cmt_io_yield *rr) { - if (!_me) { - return -EINVAL; - } cmt_io_driver_mock_t *me = &_me->mock; if (rr->cmd == HTIF_YIELD_CMD_MANUAL) { @@ -327,37 +321,3 @@ int cmt_io_yield(cmt_io_driver_t *_me, struct cmt_io_yield *rr) { return rc; } -static int read_whole_file(const char *name, size_t max, void *data, size_t *length) { - int rc = 0; - - FILE *file = fopen(name, "rb"); - if (!file) { - return -errno; - } - - *length = fread(data, 1, max, file); - if (!feof(file)) { - rc = -ENOBUFS; - } - if (fclose(file) != 0) { - rc = -errno; - } - return rc; -} - -static int write_whole_file(const char *name, size_t length, const void *data) { - int rc = 0; - - FILE *file = fopen(name, "wb"); - if (!file) { - return -errno; - } - - if (fwrite(data, 1, length, file) != length) { - rc = -EIO; - } - if (fclose(file) != 0) { - rc = -errno; - } - return rc; -} diff --git a/sys-utils/libcmt/src/merkle.c b/sys-utils/libcmt/src/merkle.c index 261cc81f..bbd46fbf 100644 --- a/sys-utils/libcmt/src/merkle.c +++ b/sys-utils/libcmt/src/merkle.c @@ -128,6 +128,9 @@ void cmt_merkle_fini(cmt_merkle_t *me) { } int cmt_merkle_load(cmt_merkle_t *me, const char *filepath) { + if (!me) { + return -EINVAL; + } FILE *fin = fopen(filepath, "rb"); if (!fin) { return -errno; @@ -144,6 +147,9 @@ int cmt_merkle_load(cmt_merkle_t *me, const char *filepath) { } int cmt_merkle_save(cmt_merkle_t *me, const char *filepath) { + if (!me) { + return -EINVAL; + } FILE *fout = fopen(filepath, "wb"); if (!fout) { return -errno; diff --git a/sys-utils/libcmt/src/util.c b/sys-utils/libcmt/src/util.c index 07e806ae..e6205bfd 100644 --- a/sys-utils/libcmt/src/util.c +++ b/sys-utils/libcmt/src/util.c @@ -1,3 +1,6 @@ +#include +#include +#include #include #include #include @@ -13,3 +16,39 @@ bool cmt_util_debug_enabled(void) { return enabled; } + +int cmt_util_read_whole_file(const char *name, size_t max, void *data, size_t *length) { + int rc = 0; + + FILE *file = fopen(name, "rb"); + if (!file) { + return -errno; + } + + *length = fread(data, 1, max, file); + if (!feof(file)) { + rc = -ENOBUFS; + } + if (fclose(file) != 0) { + rc = -errno; + } + return rc; +} + +int cmt_util_write_whole_file(const char *name, size_t length, const void *data) { + int rc = 0; + + FILE *file = fopen(name, "wb"); + if (!file) { + return -errno; + } + + if (fwrite(data, 1, length, file) != length) { + rc = -EIO; + } + if (fclose(file) != 0) { + rc = -errno; + } + return rc; +} + diff --git a/sys-utils/libcmt/src/util.h b/sys-utils/libcmt/src/util.h index 5bdd3022..87d8c0ed 100644 --- a/sys-utils/libcmt/src/util.h +++ b/sys-utils/libcmt/src/util.h @@ -6,4 +6,29 @@ */ bool cmt_util_debug_enabled(void); +/** Read whole file `name` contents into `data` and set `length`. + * @param name[in] - file path + * @param max[in] - size of `data` in bytes + * @param data[out] - file contents + * @param length[out] - actual size in `bytes` written to `data` + * + * @return + * | | | + * |-----|--------------------| + * | 0 |success | + * | < 0 |negative errno value| */ +int cmt_util_read_whole_file(const char *name, size_t max, void *data, size_t *length); + +/** Write the contents of `data` into file `name`. + * @param name[in] - file path + * @param length[in] - size of `data` in bytes + * @param data[out] - file contents + * + * @return + * | | | + * |-----|--------------------| + * | 0 |success | + * | < 0 |negative errno value| */ +int cmt_util_write_whole_file(const char *name, size_t length, const void *data); + #endif /* CMT_UTIL_H */ diff --git a/sys-utils/libcmt/tests/abi-single.c b/sys-utils/libcmt/tests/abi-single.c index e4da5c2e..0ebdcad2 100644 --- a/sys-utils/libcmt/tests/abi-single.c +++ b/sys-utils/libcmt/tests/abi-single.c @@ -119,8 +119,8 @@ static void encode_edom(void) { // clang-format on }; uint8_t en[CMT_WORD_LENGTH]; - assert(cmt_abi_encode_uint_nr(sizeof(x), x, en) == EDOM); - assert(cmt_abi_encode_uint_nn(sizeof(x), x, en) == EDOM); + assert(cmt_abi_encode_uint_nr(sizeof(x), x, en) == -EDOM); + assert(cmt_abi_encode_uint_nn(sizeof(x), x, en) == -EDOM); } static void decode_u8(void) { @@ -193,16 +193,32 @@ static void decode_u256(void) { assert(memcmp(x, ex, sizeof(ex)) == 0); } -/* encoded value can't be represented in a uint64_t. */ -static void decode_edom(void) { - uint64_t x = 0; +static void decode_uint_edom(void) { uint8_t be[CMT_WORD_LENGTH] = { // clang-format off 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // clang-format on }; - assert(cmt_abi_decode_uint(be, sizeof(x), (void *) &x) == -EDOM); + { + uint8_t x[8] = {0}; + assert(cmt_abi_decode_uint_nr(be, sizeof(x), x) == -EDOM); + } + + { + uint8_t x[8] = {0}; + assert(cmt_abi_decode_uint_nn(be, sizeof(x), x) == -EDOM); + } + + { + uint8_t x [CMT_WORD_LENGTH+1] = {0}; + assert(cmt_abi_decode_uint_nr(be, sizeof(x), x) == -EDOM); + } + + { + uint8_t x [CMT_WORD_LENGTH+1] = {0}; + assert(cmt_abi_decode_uint_nn(be, sizeof(x), x) == -EDOM); + } } static void put_funsel(void) { @@ -215,6 +231,15 @@ static void put_funsel(void) { assert(memcmp(b->begin, data, 4) == 0); } +static void put_funsel_enobufs(void) { + uint8_t data[] = {0xcd, 0xcd, 0x77, 0xc0}; + uint32_t funsel = CMT_ABI_FUNSEL(data[0], data[1], data[2], data[3]); + CMT_BUF_DECL(b, 1); + cmt_buf_t it[1] = {*b}; + + assert(cmt_abi_put_funsel(it, funsel) == -ENOBUFS); +} + static void put_uint(void) { uint64_t x = UINT64_C(0x0123456789abcdef); uint8_t be[CMT_WORD_LENGTH] = { @@ -230,6 +255,24 @@ static void put_uint(void) { assert(memcmp(b->begin, be, sizeof(be)) == 0); } +static void put_uint_enobufs(void) { + uint64_t x = UINT64_C(0x0123456789abcdef); + CMT_BUF_DECL(b, 31); + cmt_buf_t it[1] = {*b}; + + assert(cmt_abi_put_uint(it, sizeof(x), &x) == -ENOBUFS); + assert(cmt_abi_put_uint_be(it, sizeof(x), &x) == -ENOBUFS); +} + +static void put_uint_edom(void) { + uint64_t x[CMT_WORD_LENGTH+1] = {0}; + CMT_BUF_DECL(b, CMT_WORD_LENGTH); + cmt_buf_t it[1] = {*b}; + + assert(cmt_abi_put_uint(it, sizeof(x), &x) == -EDOM); + assert(cmt_abi_put_uint_be(it, sizeof(x), &x) == -EDOM); +} + static void put_bool(void) { uint8_t be[CMT_WORD_LENGTH] = { // clang-format off @@ -264,6 +307,14 @@ static void put_address(void) { assert(memcmp(b->begin, be, sizeof(be)) == 0); } +static void put_address_enobufs(void) { + uint8_t x[CMT_ADDRESS_LENGTH] = {0}; + CMT_BUF_DECL(b, CMT_WORD_LENGTH-1); + cmt_buf_t it[1] = {*b}; + + assert(cmt_abi_put_address(it, x) == -ENOBUFS); +} + static void put_bytes(void) { uint64_t x = UINT64_C(0x0123456789abcdef); uint8_t be[] = { @@ -284,15 +335,38 @@ static void put_bytes(void) { assert(memcmp(b->begin, be, sizeof(be)) == 0); } +static void put_bytes_enobufs(void) { + uint64_t x = UINT64_C(0x0123456789abcdef); + cmt_buf_t of[1]; + + { + CMT_BUF_DECL(b, 3 * 32 - 1); + cmt_buf_t it[1] = {*b}; + assert(cmt_abi_put_bytes_s(it, of) == 0); + assert(cmt_abi_put_bytes_d(it, of, sizeof(x), &x, b->begin) == -ENOBUFS); + } +} + static void get_funsel(void) { CMT_BUF_DECL(b, 64); cmt_buf_t wr[1] = {*b}; cmt_buf_t rd[1] = {*b}; - uint32_t funsel = CMT_ABI_FUNSEL(1, 2, 3, 4); + uint32_t right = CMT_ABI_FUNSEL(1, 2, 3, 4); + uint32_t wrong = CMT_ABI_FUNSEL(1, 2, 3, 3); - assert(cmt_abi_put_funsel(wr, funsel) == 0); - assert(cmt_abi_peek_funsel(rd) == funsel); - assert(cmt_abi_check_funsel(rd, funsel) == 0); + assert(cmt_abi_put_funsel(wr, right) == 0); + assert(cmt_abi_peek_funsel(rd) == right); + assert(cmt_abi_check_funsel(rd, wrong) == -EBADMSG); // don't advance + assert(cmt_abi_check_funsel(rd, right) == 0); +} + +static void peek_funsel_error(void) { + CMT_BUF_DECL(b, 3); + uint32_t wrong = 0; // value doesn't matter + cmt_buf_t rd[1] = {*b}; + + assert(cmt_abi_peek_funsel(rd) == 0); + assert(cmt_abi_check_funsel(rd, wrong) == -ENOBUFS); // don't advance } static void get_uint(void) { @@ -311,6 +385,24 @@ static void get_uint(void) { assert(x == ex); } +static void get_uint_enobufs(void) { + uint64_t x = UINT64_C(0x0123456789abcdef); + CMT_BUF_DECL(b, 31); + cmt_buf_t it[1] = {*b}; + + assert(cmt_abi_get_uint(it, sizeof(x), &x) == -ENOBUFS); + assert(cmt_abi_get_uint_be(it, sizeof(x), &x) == -ENOBUFS); +} + +static void get_uint_edom(void) { + uint64_t x[CMT_WORD_LENGTH+1] = {0}; + CMT_BUF_DECL(b, CMT_WORD_LENGTH); + cmt_buf_t it[1] = {*b}; + + assert(cmt_abi_get_uint(it, sizeof(x), &x) == -EDOM); + assert(cmt_abi_get_uint_be(it, sizeof(x), &x) == -EDOM); +} + static void get_uint_be(void) { uint64_t x = 0; uint64_t ex = UINT64_C(0x0123456789abcdef); @@ -343,6 +435,20 @@ static void get_bool(void) { assert(x == ex); } +static void get_bool_enobufs(void) { + bool x = false; + uint8_t be[CMT_WORD_LENGTH-1] = { + // clang-format off + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // clang-format on + }; + CMT_BUF_DECL3(b, sizeof(be), be); + cmt_buf_t rd[1] = {*b}; + + assert(cmt_abi_get_bool(rd, &x) == -ENOBUFS); +} + static void get_address(void) { uint8_t x[CMT_ADDRESS_LENGTH]; uint8_t ex[CMT_ADDRESS_LENGTH] = { @@ -364,6 +470,19 @@ static void get_address(void) { assert(memcmp(x, ex, sizeof(ex)) == 0); } +static void get_address_enobufs(void) { + uint8_t x[CMT_ADDRESS_LENGTH]; + uint8_t be[CMT_WORD_LENGTH-1] = { + // clang-format off + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, + 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, + // clang-format on + }; + CMT_BUF_DECL3(b, sizeof(be), be); + cmt_buf_t it[1] = {*b}; + assert(cmt_abi_get_address(it, x) == -ENOBUFS); +} + static void get_bytes(void) { uint64_t ex = UINT64_C(0x0123456789abcdef); uint8_t be[] = { @@ -385,6 +504,48 @@ static void get_bytes(void) { assert(memcmp(bytes->begin, &ex, sizeof(ex)) == 0); } +static void get_bytes_enobufs(void) { + uint8_t be[] = { + // clang-format off + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // clang-format on + }; + + { // when offset of dynamic reagion failed + CMT_BUF_DECL3(b, 1 * CMT_WORD_LENGTH - 1, be); + cmt_buf_t it[1] = {*b}; + cmt_buf_t of[1] = {0}; + cmt_buf_t bytes[1]; + + assert(cmt_abi_peek_bytes_d(it, of, bytes) == -ENOBUFS); + } + + { // dynamic reagion is too small to peek bytes + CMT_BUF_DECL3(b, 3 * CMT_WORD_LENGTH - 1, be); + cmt_buf_t it[1] = {*b}; + cmt_buf_t of[1] = {0}; + cmt_buf_t bytes[1]; + + assert(cmt_abi_get_bytes_s(it, of) == 0); + assert(cmt_abi_peek_bytes_d(it, of, bytes) == -ENOBUFS); + } + + { // dynamic reagion is too small to copy bytes + CMT_BUF_DECL3(b, 3 * CMT_WORD_LENGTH - 1, be); + cmt_buf_t it[1] = {*b}; + cmt_buf_t of[1] = {0}; + + size_t n; + void *data; + assert(cmt_abi_get_bytes_s(it, of) == 0); + assert(cmt_abi_get_bytes_d(it, of, &n, &data) == -ENOBUFS); + } +} + int main(void) { abi_funsel(); @@ -400,20 +561,31 @@ int main(void) { decode_u32(); decode_u64(); decode_u256(); - decode_edom(); + decode_uint_edom(); put_funsel(); + put_funsel_enobufs(); put_uint(); + put_uint_enobufs(); + put_uint_edom(); put_bool(); put_address(); + put_address_enobufs(); put_bytes(); + put_bytes_enobufs(); get_funsel(); + peek_funsel_error(); get_uint(); get_uint_be(); + get_uint_enobufs(); + get_uint_edom(); get_bool(); + get_bool_enobufs(); get_address(); + get_address_enobufs(); get_bytes(); + get_bytes_enobufs(); return 0; } diff --git a/sys-utils/libcmt/tests/buf.c b/sys-utils/libcmt/tests/buf.c index 3fc5669f..a5ff3d51 100644 --- a/sys-utils/libcmt/tests/buf.c +++ b/sys-utils/libcmt/tests/buf.c @@ -17,8 +17,17 @@ #include #include #include +#include -void split_in_bounds_must_succeed(void) { +static void passing_null(void) { + uint8_t _[8]; + + // just test if it crashes + cmt_buf_init(NULL, sizeof _, _); + assert(cmt_buf_length(NULL) == 0); +} + +static void split_in_bounds_must_succeed(void) { uint8_t _[8]; cmt_buf_t b; cmt_buf_init(&b, sizeof _, _); @@ -62,7 +71,7 @@ void split_in_bounds_must_succeed(void) { printf("test_buf_split_in_bounds_must_succeed passed\n"); } -void split_out_of_bounds_must_fail(void) { +static void split_out_of_bounds_must_fail(void) { uint8_t _[8]; cmt_buf_t b; cmt_buf_t lhs; @@ -74,8 +83,51 @@ void split_out_of_bounds_must_fail(void) { printf("test_buf_split_out_of_bounds_must_fail passed\n"); } +static void split_invalid_parameters(void) { + uint8_t _[8]; + cmt_buf_t b; + cmt_buf_t lhs; + cmt_buf_t rhs; + cmt_buf_init(&b, sizeof _, _); + + assert(cmt_buf_split(NULL, 8, &lhs, &rhs) == -EINVAL); + assert(cmt_buf_split(&b, 8, NULL, &rhs) == -EINVAL); + assert(cmt_buf_split(&b, 8, &lhs, NULL) == -EINVAL); +} + +static void split_by_comma_until_the_end(void) { + uint8_t _[] = "a,b,c"; + cmt_buf_t x; + cmt_buf_t xs; + + cmt_buf_init(&x, sizeof _ - 1, _); + cmt_buf_init(&xs, sizeof _ - 1, _); + assert(cmt_buf_split_by_comma(&x, &xs) == true); + assert(strncmp((char *)x.begin, "a", 1UL) == 0); + assert(cmt_buf_split_by_comma(&x, &xs) == true); + assert(strncmp((char *)x.begin, "b", 1UL) == 0); + assert(cmt_buf_split_by_comma(&x, &xs) == true); + assert(strncmp((char *)x.begin, "c", 1UL) == 0); + assert(cmt_buf_split_by_comma(&x, &xs) == false); +} + +static void xxd(void) +{ + uint8_t _[] = ""; + cmt_buf_xxd(_, _ + sizeof _, 0); + cmt_buf_xxd(_, _ + sizeof _, 1); + cmt_buf_xxd(_, _ + sizeof _, 3); + cmt_buf_xxd(NULL, _ + sizeof _, 1); + cmt_buf_xxd(_, NULL, 1); + cmt_buf_xxd(_, _, 1); +} + int main(void) { + passing_null(); split_in_bounds_must_succeed(); split_out_of_bounds_must_fail(); + split_invalid_parameters(); + split_by_comma_until_the_end(); + xxd(); return 0; } diff --git a/sys-utils/libcmt/tests/gio.c b/sys-utils/libcmt/tests/gio.c index abe1756b..dfc1269e 100644 --- a/sys-utils/libcmt/tests/gio.c +++ b/sys-utils/libcmt/tests/gio.c @@ -5,50 +5,16 @@ #include #include "rollup.h" #include "data.h" - -static int read_whole_file(const char *name, size_t max, void *data, size_t *length) { - int rc = 0; - - FILE *file = fopen(name, "rb"); - if (!file) { - return -errno; - } - - *length = fread(data, 1, max, file); - if (!feof(file)) { - rc = -ENOBUFS; - } - if (fclose(file) != 0) { - rc = -errno; - } - return rc; -} - -static int write_whole_file(const char *name, size_t length, const void *data) { - int rc = 0; - - FILE *file = fopen(name, "wb"); - if (!file) { - return -errno; - } - - if (fwrite(data, 1, length, file) != length) { - rc = -EIO; - } - if (fclose(file) != 0) { - rc = -errno; - } - return rc; -} +#include "util.h" int main(void) { uint8_t buffer[1024]; - size_t buffer_length; + size_t buffer_length = 0; cmt_rollup_t rollup; - assert(write_whole_file("build/gio.bin", sizeof valid_gio_reply_0, valid_gio_reply_0) == 0); - assert(setenv("CMT_INPUTS", "42:build/gio.bin", 1) == 0); + assert(cmt_util_write_whole_file("gio.bin", sizeof valid_gio_reply_0, valid_gio_reply_0) == 0); + assert(setenv("CMT_INPUTS", "42:gio.bin", 1) == 0); assert(cmt_rollup_init(&rollup) == 0); char request[] = "gio-request-0"; @@ -61,7 +27,7 @@ int main(void) }; assert(cmt_gio_request(&rollup, &req) == 0); - assert(read_whole_file("none.gio-0.bin", sizeof buffer, buffer, &buffer_length) == 0); + assert(cmt_util_read_whole_file("none.gio-0.bin", sizeof buffer, buffer, &buffer_length) == 0); assert(req.response_code == 42); assert(req.response_data_length == strlen(reply)); assert(memcmp(req.response_data, reply, req.response_data_length) == 0); diff --git a/sys-utils/libcmt/tests/io.c b/sys-utils/libcmt/tests/io.c new file mode 100644 index 00000000..1aea1987 --- /dev/null +++ b/sys-utils/libcmt/tests/io.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include "io.h" + +void invalid_parameters(void) +{ + assert(cmt_io_init(NULL) == -EINVAL); + cmt_io_fini(NULL); + + cmt_buf_t tx = cmt_io_get_tx(NULL); + assert(tx.begin == NULL && tx.end == NULL); + + cmt_buf_t rx = cmt_io_get_rx(NULL); + assert(rx.begin == NULL && rx.end == NULL); + + setenv("CMT_INPUTS", "invalid", 1); + cmt_io_driver_t io[1]; + assert(cmt_io_init(io) == 0); + + { // invalid cmd + reason + cmt_io_yield_t rr[1] = {{ + .cmd = HTIF_YIELD_CMD_AUTOMATIC, + .reason = UINT16_MAX, + }}; + assert(cmt_io_yield(io, rr) == -EINVAL); + } + + { // invalid cmd + cmt_io_yield_t rr[1] = {{ + .cmd = 0xff, + .reason = 0, + }}; + assert(cmt_io_yield(io, rr) == -EINVAL); + } + + { // invalid args + cmt_io_yield_t rr[1] = {{ + .reason = HTIF_YIELD_MANUAL_REASON_RX_ACCEPTED, + .cmd = HTIF_YIELD_CMD_MANUAL, + .data = 0, + }}; + assert(cmt_io_yield(io, NULL) == -EINVAL); + assert(cmt_io_yield(NULL, rr) == -EINVAL); + assert(cmt_io_yield(io, rr) == -ENODATA); + } +} + +int main(void) +{ + setenv("CMT_DEBUG", "yes", 1); + invalid_parameters(); + return 0; +} diff --git a/sys-utils/libcmt/tests/merkle.c b/sys-utils/libcmt/tests/merkle.c index 47d5f67d..5ce98f74 100644 --- a/sys-utils/libcmt/tests/merkle.c +++ b/sys-utils/libcmt/tests/merkle.c @@ -17,8 +17,10 @@ #include #include +#include #include #include +#include #if 0 // NOLINT static void print(int m, uint8_t md[CMT_KECCAK_LENGTH]) { @@ -124,9 +126,14 @@ void test_cmt_merkle_push_back_data(void) { } void test_cmt_merkle_save_load(void) { - const char *test_file = "/tmp/cmt_merkle_test.bin"; cmt_merkle_t merkle1; cmt_merkle_t merkle2; + char valid[] = "/tmp/tmp.XXXXXX"; + char invalid[] = "/tmp/tmp.XXXXXX/invalid.bin"; + + // create a unique file and an invalid file from it. + mkstemp(valid); + memcpy(invalid, valid, strlen(valid)); // Initialize merkle1 and add some data cmt_merkle_init(&merkle1); @@ -138,24 +145,52 @@ void test_cmt_merkle_save_load(void) { assert(cmt_merkle_push_back_data(&merkle1, CMT_KECCAK_LENGTH, data) == 0); } - assert(cmt_merkle_save(&merkle1, test_file) == 0); - assert(cmt_merkle_load(&merkle2, test_file) == 0); - assert(memcmp(&merkle1, &merkle2, sizeof(cmt_merkle_t)) == 0); + // succeed with normal usage + assert(cmt_merkle_save(&merkle1, valid) == 0); + assert(cmt_merkle_load(&merkle2, valid) == 0); + assert(memcmp(&merkle1, &merkle2, sizeof(merkle1)) == 0); + + // fail to load smaller file + (void)truncate(valid, sizeof(merkle1) - 1); + assert(cmt_merkle_load(&merkle2, valid) != 0); + (void)remove(valid); + + // fail to save/load invalid filepath + assert(cmt_merkle_save(&merkle1, invalid) != 0); + assert(cmt_merkle_load(&merkle2, invalid) != 0); + + // invalid state + assert(cmt_merkle_save(NULL, valid) == -EINVAL); + assert(cmt_merkle_load(NULL, valid) == -EINVAL); - // Cleanup - if (remove(test_file) != 0) { - (void) fprintf(stderr, "Error deleting file %s: %s\n", test_file, strerror(errno)); - } printf("test_cmt_merkle_save_load passed\n"); } +void test_cmt_merkle_full(void) { + const uint64_t max_count = + (CMT_MERKLE_TREE_HEIGHT < 8 * sizeof(uint64_t))? + (UINT64_C(1) << CMT_MERKLE_TREE_HEIGHT): + UINT64_MAX; + cmt_merkle_t merkle = { + .leaf_count = max_count - 1, + }; + assert(cmt_merkle_get_leaf_count(&merkle) == max_count - 1); + + uint8_t data[] = {0}; + assert(cmt_merkle_push_back_data(&merkle, sizeof(data), data) == 0); + assert(cmt_merkle_push_back_data(&merkle, sizeof(data), data) == -ENOBUFS); + assert(cmt_merkle_get_leaf_count(&merkle) == max_count); +} + int main(void) { + setenv("CMT_DEBUG", "yes", 1); test_merkle_init_and_reset(); test_merkle_push_back_and_get_root(); test_cmt_merkle_push_back_data_and_get_root(); test_cmt_merkle_push_back(); test_cmt_merkle_push_back_data(); test_cmt_merkle_save_load(); + test_cmt_merkle_full(); printf("All merkle tests passed!\n"); return 0; } diff --git a/sys-utils/libcmt/tests/rollup.c b/sys-utils/libcmt/tests/rollup.c index d2831c28..3e6fde56 100644 --- a/sys-utils/libcmt/tests/rollup.c +++ b/sys-utils/libcmt/tests/rollup.c @@ -13,49 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "rollup.h" -#include "data.h" #include #include #include #include #include #include +#include "rollup.h" +#include "util.h" +#include "data.h" -static int read_whole_file(const char *name, size_t max, void *data, size_t *length) { - int rc = 0; - - FILE *file = fopen(name, "rb"); - if (!file) { - return -errno; - } - - *length = fread(data, 1, max, file); - if (!feof(file)) { - rc = -ENOBUFS; - } - if (fclose(file) != 0) { - rc = -errno; - } - return rc; -} - -static int write_whole_file(const char *name, size_t length, const void *data) { - int rc = 0; - - FILE *file = fopen(name, "wb"); - if (!file) { - return -errno; - } - - if (fwrite(data, 1, length, file) != length) { - rc = -EIO; - } - if (fclose(file) != 0) { - rc = -errno; - } - return rc; -} void test_rollup_init_and_fini(void) { cmt_rollup_t rollup; @@ -127,11 +94,11 @@ void test_rollup_parse_inputs(void) { uint8_t data[] = {0}; // synthesize inputs and feed them to io-mock via CMT_INPUTS env. - assert(write_whole_file("build/0.bin", sizeof valid_advance_0, valid_advance_0) == 0); - assert(write_whole_file("build/1.bin", sizeof valid_inspect_0, valid_inspect_0) == 0); - assert(write_whole_file("build/2.bin", sizeof data, data) == 0); - assert(truncate("build/2.bin", 3 << 20) == 0); - assert(setenv("CMT_INPUTS", "0:build/0.bin,1:build/1.bin,0:build/2.bin", 1) == 0); + assert(cmt_util_write_whole_file("0.bin", sizeof valid_advance_0, valid_advance_0) == 0); + assert(cmt_util_write_whole_file("1.bin", sizeof valid_inspect_0, valid_inspect_0) == 0); + assert(cmt_util_write_whole_file("2.bin", sizeof data, data) == 0); + assert(truncate("2.bin", 3 << 20) == 0); + assert(setenv("CMT_INPUTS", "0:0.bin,1:1.bin,0:2.bin", 1) == 0); assert(cmt_rollup_init(&rollup) == 0); assert(cmt_rollup_finish(&rollup, &finish) == 0); @@ -142,6 +109,9 @@ void test_rollup_parse_inputs(void) { assert(cmt_rollup_finish(&rollup, &finish) == -ENODATA); + finish.accept_previous_request = false; + assert(cmt_rollup_finish(&rollup, &finish) == -ENOSYS); + cmt_rollup_fini(&rollup); printf("test_rollup_parse_inputs passed!\n"); } @@ -172,37 +142,63 @@ void test_rollup_outputs_reports_and_exceptions(void) { assert(cmt_rollup_emit_voucher(&rollup, sizeof address, address, sizeof value, value, strlen(voucher_data), voucher_data, &index) == 0); assert(index == 0); - assert(read_whole_file("none.output-0.bin", sizeof buffer, buffer, &read_size) == 0); + assert(cmt_util_read_whole_file("none.output-0.bin", sizeof buffer, buffer, &read_size) == 0); assert(sizeof valid_voucher_0 == read_size); assert(memcmp(valid_voucher_0, buffer, sizeof valid_voucher_0) == 0); + // voucher (invalid) + assert(cmt_rollup_emit_voucher(NULL, sizeof address, address, sizeof value, value, strlen(voucher_data), + voucher_data, &index) == -EINVAL); + assert(cmt_rollup_emit_voucher(&rollup, sizeof address - 1, address, sizeof value, value, strlen(voucher_data), + NULL, &index) == -EINVAL); + assert(cmt_rollup_emit_voucher(&rollup, sizeof address - 1, address, sizeof value, value, strlen(voucher_data), + voucher_data, &index) == -EINVAL); + assert(cmt_rollup_emit_voucher(&rollup, sizeof address, address, sizeof value, value, UINT32_MAX, + voucher_data, &index) == -ENOBUFS); + // notice char notice_data[] = "notice-0"; assert(cmt_rollup_emit_notice(&rollup, strlen(notice_data), notice_data, &index) == 0); - assert(read_whole_file("none.output-1.bin", sizeof buffer, buffer, &read_size) == 0); + assert(cmt_util_read_whole_file("none.output-1.bin", sizeof buffer, buffer, &read_size) == 0); assert(sizeof valid_notice_0 == read_size); assert(memcmp(valid_notice_0, buffer, sizeof valid_notice_0) == 0); assert(index == 1); + // notice (invalid) + assert(cmt_rollup_emit_notice(NULL, strlen(notice_data), notice_data, &index) == -EINVAL); + assert(cmt_rollup_emit_notice(&rollup, strlen(notice_data), NULL, &index) == -EINVAL); + assert(cmt_rollup_emit_notice(&rollup, UINT32_MAX, notice_data, &index) == -ENOBUFS); + // report char report_data[] = "report-0"; assert(cmt_rollup_emit_report(&rollup, strlen(report_data), report_data) == 0); - assert(read_whole_file("none.report-0.bin", sizeof buffer, buffer, &read_size) == 0); + assert(cmt_util_read_whole_file("none.report-0.bin", sizeof buffer, buffer, &read_size) == 0); assert(sizeof valid_report_0 == read_size); assert(memcmp(valid_report_0, buffer, sizeof valid_report_0) == 0); + // report (invalid) + assert(cmt_rollup_emit_report(NULL, strlen(report_data), report_data) == -EINVAL); + assert(cmt_rollup_emit_report(&rollup, strlen(report_data), NULL) == -EINVAL); + assert(cmt_rollup_emit_report(&rollup, UINT32_MAX, report_data) == -ENOBUFS); + // exception char exception_data[] = "exception-0"; assert(cmt_rollup_emit_exception(&rollup, strlen(exception_data), exception_data) == 0); - assert(read_whole_file("none.exception-0.bin", sizeof buffer, buffer, &read_size) == 0); + assert(cmt_util_read_whole_file("none.exception-0.bin", sizeof buffer, buffer, &read_size) == 0); assert(sizeof valid_exception_0 == read_size); assert(memcmp(valid_exception_0, buffer, sizeof valid_exception_0) == 0); + // exception (invalid) + assert(cmt_rollup_emit_exception(NULL, strlen(exception_data), exception_data) == -EINVAL); + assert(cmt_rollup_emit_exception(&rollup, strlen(exception_data), NULL) == -EINVAL); + assert(cmt_rollup_emit_exception(&rollup, UINT32_MAX, exception_data) == -ENOBUFS); + cmt_rollup_fini(&rollup); printf("test_rollup_outputs_reports_and_exceptions passed!\n"); } int main(void) { + setenv("CMT_DEBUG", "yes", 1); test_rollup_init_and_fini(); test_rollup_parse_inputs(); test_rollup_outputs_reports_and_exceptions();