diff --git a/axl_memory.c b/axl_memory.c index 71b3a17..b73a9e3 100644 --- a/axl_memory.c +++ b/axl_memory.c @@ -238,6 +238,22 @@ i32 axl_memcmp(const void* s1, const void* s2, u32 n) return 0; } +void* axl_memchr(const void* ptr, u8 value, u32 n) +{ + if(ptr) + { + for(u32 i = 0; i < n; i++) + { + if(*((u8*)ptr + i) == value) + { + return (u8*)ptr + i; + } + } + } + + return NULL; +} + void axl_free(void* ptr) { if(!ptr) diff --git a/axl_memory.h b/axl_memory.h index b551fbb..2ca24b4 100644 --- a/axl_memory.h +++ b/axl_memory.h @@ -13,6 +13,7 @@ void* axl_realloc(void* ptr, u32 size); void* axl_memset(void* ptr, i8 c, u32 n); void* axl_memcpy(void* dst, const void* src, u32 count); i32 axl_memcmp(const void* s1, const void* s2, u32 n); +void* axl_memchr(const void* ptr, u8 value, u32 n); void axl_free(void* ptr); #endif diff --git a/axl_memory_test.c b/axl_memory_test.c index f83eaa0..27369ab 100644 --- a/axl_memory_test.c +++ b/axl_memory_test.c @@ -6,10 +6,6 @@ #include "axl_koan.h" #include -/* ------------------------------------------------------------------ */ -/* Basic allocation & initialization */ -/* ------------------------------------------------------------------ */ - KOAN(init_called) { void* p = axl_malloc(1); @@ -30,14 +26,10 @@ KOAN(malloc_returns_different_pointers) KOAN(malloc_exhaustion_returns_null) { - void* p = axl_malloc(AXL_HEAP_SIZE + 4096); /* definitely too big */ + void* p = axl_malloc(AXL_HEAP_SIZE + 4096); ASSERT_NULL(p); } -/* ------------------------------------------------------------------ */ -/* Realloc behavior (strictly per C standard) */ -/* ------------------------------------------------------------------ */ - KOAN(realloc_null_acts_like_malloc) { void* p = axl_realloc(NULL, 64); @@ -52,7 +44,7 @@ KOAN(realloc_zero_size_frees_and_returns_null_or_valid) ASSERT_NOT_NULL(p); void* q = axl_realloc(p, 0); if (q != NULL) axl_free(q); - /* Original p is freed regardless */ + } KOAN(realloc_enlarge_preserves_content) @@ -83,14 +75,10 @@ KOAN(realloc_same_size_returns_same_or_equivalent) p = axl_realloc(p, 100); ASSERT_NOT_NULL(p); - /* May return same or different pointer */ + axl_free(p); } -/* ------------------------------------------------------------------ */ -/* Memory operations */ -/* ------------------------------------------------------------------ */ - KOAN(memset_fills_correctly) { void* p = axl_malloc(64); @@ -104,7 +92,7 @@ KOAN(memset_zero_bytes_is_nop) { void* p = axl_malloc(16); axl_memset(p, 0xFF, 16); - axl_memset(p, 0x00, 0); /* should not change anything */ + axl_memset(p, 0x00, 0); for (int i = 0; i < 16; i++) ASSERT_INT_EQ(0xFF, ((u8*)p)[i]); axl_free(p); @@ -125,7 +113,7 @@ KOAN(memcpy_zero_bytes_is_nop) u8 data[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; void* p = axl_malloc(16); axl_memcpy(p, data, 16); - axl_memcpy(p, "junk", 0); /* must not modify */ + axl_memcpy(p, "junk", 0); ASSERT_INT_EQ(0, memcmp(p, data, 16)); axl_free(p); } @@ -152,27 +140,115 @@ KOAN(memcmp_zero_length_returns_zero) ASSERT_INT_EQ(0, axl_memcmp(&x, &y, 0)); } -/* ------------------------------------------------------------------ */ -/* Double-free and use-after-free detection (indirect) */ -/* ------------------------------------------------------------------ */ +KOAN(memchr_finds_character_in_buffer) +{ + u8 buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + void* result = axl_memchr(buffer, 0x03, sizeof(buffer)); + ASSERT_NOT_NULL(result); + ASSERT_TRUE(result == &buffer[3]); +} + +KOAN(memchr_returns_null_when_not_found) +{ + u8 buffer[] = {0x10, 0x20, 0x30, 0x40, 0x50}; + void* result = axl_memchr(buffer, 0x99, sizeof(buffer)); + ASSERT_NULL(result); +} + +KOAN(memchr_finds_first_occurrence) +{ + u8 buffer[] = {0xAA, 0xBB, 0xCC, 0xBB, 0xDD}; + void* result = axl_memchr(buffer, 0xBB, sizeof(buffer)); + ASSERT_NOT_NULL(result); + ASSERT_TRUE(result == &buffer[1]); +} + +KOAN(memchr_finds_at_beginning) +{ + u8 buffer[] = {0xFF, 0xFE, 0xFD, 0xFC}; + void* result = axl_memchr(buffer, 0xFF, sizeof(buffer)); + ASSERT_NOT_NULL(result); + ASSERT_TRUE(result == &buffer[0]); +} + +KOAN(memchr_finds_at_end) +{ + u8 buffer[] = {0x11, 0x22, 0x33, 0x44, 0x55}; + void* result = axl_memchr(buffer, 0x55, sizeof(buffer)); + ASSERT_NOT_NULL(result); + ASSERT_TRUE(result == &buffer[4]); +} + +KOAN(memchr_zero_length_returns_null) +{ + u8 buffer[] = {0x01, 0x02, 0x03}; + void* result = axl_memchr(buffer, 0x01, 0); + ASSERT_NULL(result); +} + +KOAN(memchr_stops_at_specified_length) +{ + u8 buffer[] = {0x10, 0x20, 0x30, 0x40, 0x50}; + + void* result = axl_memchr(buffer, 0x40, 3); + ASSERT_NULL(result); + + + result = axl_memchr(buffer, 0x40, 4); + ASSERT_NOT_NULL(result); + ASSERT_TRUE(result == &buffer[3]); +} + +KOAN(memchr_handles_all_byte_values) +{ + u8 buffer[256]; + for (int i = 0; i < 256; i++) { + buffer[i] = (u8)i; + } + + + for (int i = 0; i < 256; i++) { + void* result = axl_memchr(buffer, (u8)i, sizeof(buffer)); + ASSERT_NOT_NULL(result); + ASSERT_TRUE(result == &buffer[i]); + } +} + +KOAN(memchr_matches_standard_memchr) +{ + u8 buffer[100]; + for (int i = 0; i < 100; i++) { + buffer[i] = (u8)(i * 3); + } + + + for (int val = 0; val < 256; val += 17) { + void* axl_result = axl_memchr(buffer, (u8)val, sizeof(buffer)); + void* std_result = memchr(buffer, (u8)val, sizeof(buffer)); + + + if (std_result == NULL) { + ASSERT_NULL(axl_result); + } else { + ASSERT_NOT_NULL(axl_result); + ASSERT_TRUE(axl_result == std_result); + } + } +} KOAN(double_free_does_not_crash) { void* p = axl_malloc(64); ASSERT_NOT_NULL(p); axl_free(p); - axl_free(p); /* should be ignored or handled safely */ + axl_free(p); } -/* ------------------------------------------------------------------ */ -/* Large and boundary allocations */ -/* ------------------------------------------------------------------ */ - KOAN(large_allocation_near_heap_limit) { - /* Allocate almost entire heap */ + void* p = axl_malloc(AXL_HEAP_SIZE - 1024); - ASSERT_NOT_NULL(p); /* may pass if overhead is small */ + ASSERT_NOT_NULL(p); if (p) axl_free(p); } @@ -182,10 +258,6 @@ KOAN(allocation_of_max_size_fails) ASSERT_NULL(p); } -/* ------------------------------------------------------------------ */ -/* Stress: many small allocations */ -/* ------------------------------------------------------------------ */ - KOAN(many_small_allocations) { #define N 1000 @@ -201,10 +273,6 @@ KOAN(many_small_allocations) } } -/* ------------------------------------------------------------------ */ -/* Main */ -/* ------------------------------------------------------------------ */ - int main(void) { axl_init();