axl_memchr
This commit is contained in:
parent
7b20fdb03e
commit
774d0096d8
3 changed files with 120 additions and 35 deletions
16
axl_memory.c
16
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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,10 +6,6 @@
|
|||
#include "axl_koan.h"
|
||||
#include <string.h>
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 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();
|
||||
|
|
|
|||
Loading…
Reference in a new issue