/* * Memory-wrapper behaviour that is deterministic today. * * TODO.md section 1.1 also calls out malloc(0), malloc(SIZE_MAX), and * overlapping memcpy. Those are intentionally not pinned here yet: malloc(0) * is platform-dependent under the current wrapper, huge allocations need * sanitizer-safe handling, and overlapping memcpy is still an API-contract * decision. */ #include "aksl_capture.h" static int test_malloc_writes_nonnull_pointer(void) { void *ptr = NULL; AKSL_CHECK_OK(aksl_malloc(32, &ptr)); AKSL_CHECK(ptr != NULL); AKSL_CHECK_OK(aksl_free(ptr)); return 0; } static int test_malloc_rejects_null_destination(void) { AKSL_CHECK_STATUS_MSG_CONTAINS(aksl_malloc(32, NULL), AKERR_NULLPOINTER, "NULL"); return 0; } static int test_free_rejects_null_pointer(void) { AKSL_CHECK_STATUS_MSG_CONTAINS(aksl_free(NULL), AKERR_NULLPOINTER, "NULL"); return 0; } static int test_malloc_free_round_trip(void) { unsigned char *buf = NULL; size_t i = 0; AKSL_CHECK_OK(aksl_malloc(64, (void **)&buf)); AKSL_CHECK(buf != NULL); for ( i = 0; i < 64; i++ ) { buf[i] = (unsigned char)i; } for ( i = 0; i < 64; i++ ) { AKSL_CHECK(buf[i] == (unsigned char)i); } AKSL_CHECK_OK(aksl_free(buf)); return 0; } static int test_memset_fills_buffer(void) { unsigned char buf[8]; size_t i = 0; memset((void *)buf, 0x00, sizeof(buf)); AKSL_CHECK_OK(aksl_memset(buf, 0x5a, sizeof(buf))); for ( i = 0; i < sizeof(buf); i++ ) { AKSL_CHECK(buf[i] == 0x5a); } return 0; } static int test_memset_zero_length_is_noop(void) { unsigned char buf[4] = { 1, 2, 3, 4 }; AKSL_CHECK_OK(aksl_memset(buf, 0xff, 0)); AKSL_CHECK(buf[0] == 1); AKSL_CHECK(buf[1] == 2); AKSL_CHECK(buf[2] == 3); AKSL_CHECK(buf[3] == 4); return 0; } static int test_memset_rejects_null_buffer(void) { AKSL_CHECK_STATUS_MSG_CONTAINS(aksl_memset(NULL, 0x00, 4), AKERR_NULLPOINTER, "s="); return 0; } static int test_memcpy_copies_bytes(void) { unsigned char src[6] = { 0, 1, 2, 3, 4, 5 }; unsigned char dst[6] = { 9, 9, 9, 9, 9, 9 }; size_t i = 0; AKSL_CHECK_OK(aksl_memcpy(dst, src, sizeof(src))); for ( i = 0; i < sizeof(src); i++ ) { AKSL_CHECK(dst[i] == src[i]); } return 0; } static int test_memcpy_zero_length_is_noop(void) { unsigned char src[3] = { 1, 2, 3 }; unsigned char dst[3] = { 4, 5, 6 }; AKSL_CHECK_OK(aksl_memcpy(dst, src, 0)); AKSL_CHECK(dst[0] == 4); AKSL_CHECK(dst[1] == 5); AKSL_CHECK(dst[2] == 6); return 0; } static int test_memcpy_rejects_null_destination(void) { unsigned char src[1] = { 1 }; AKSL_CHECK_STATUS(aksl_memcpy(NULL, src, sizeof(src)), AKERR_NULLPOINTER); return 0; } static int test_memcpy_rejects_null_source(void) { unsigned char dst[1] = { 0 }; AKSL_CHECK_STATUS(aksl_memcpy(dst, NULL, sizeof(dst)), AKERR_NULLPOINTER); return 0; } int main(void) { int failures = 0; akerr_init(); AKSL_RUN(failures, test_malloc_writes_nonnull_pointer); AKSL_RUN(failures, test_malloc_rejects_null_destination); AKSL_RUN(failures, test_free_rejects_null_pointer); AKSL_RUN(failures, test_malloc_free_round_trip); AKSL_RUN(failures, test_memset_fills_buffer); AKSL_RUN(failures, test_memset_zero_length_is_noop); AKSL_RUN(failures, test_memset_rejects_null_buffer); AKSL_RUN(failures, test_memcpy_copies_bytes); AKSL_RUN(failures, test_memcpy_zero_length_is_noop); AKSL_RUN(failures, test_memcpy_rejects_null_destination); AKSL_RUN(failures, test_memcpy_rejects_null_source); AKSL_REPORT(failures); }