mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-03 22:19:32 +03:00
Merge f40cd9cd60
into fae61ed946
This commit is contained in:
commit
2fc00e6b57
2 changed files with 180 additions and 0 deletions
|
@ -759,3 +759,25 @@ if (MI_OVERRIDE)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Build fuzz tests
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
if(DEFINED ENV{LIB_FUZZING_ENGINE})
|
||||||
|
set(FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE})
|
||||||
|
set(FUZZING_COMPILE_FLAGS "")
|
||||||
|
set(FUZZING_LINK_FLAGS "${FUZZING_ENGINE}")
|
||||||
|
else()
|
||||||
|
set(FUZZING_COMPILE_FLAGS "-fsanitize=fuzzer,address")
|
||||||
|
set(FUZZING_LINK_FLAGS "-fsanitize=fuzzer,address")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(('${CMAKE_CXX_COMPILER_ID}' STREQUAL 'Clang') AND NOT MI_DEBUG_TSAN)
|
||||||
|
## fuzz testing
|
||||||
|
add_executable(mimalloc-test-fuzz test/test-fuzz.c)
|
||||||
|
target_compile_definitions(mimalloc-test-fuzz PRIVATE ${mi_defines})
|
||||||
|
target_compile_options(mimalloc-test-fuzz PRIVATE ${mi_cflags} "${FUZZING_COMPILE_FLAGS}")
|
||||||
|
target_include_directories(mimalloc-test-fuzz PRIVATE include)
|
||||||
|
target_link_libraries(mimalloc-test-fuzz PRIVATE mimalloc ${mi_libraries} "${FUZZING_LINK_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
158
test/fuzz-random-alloc.c
Normal file
158
test/fuzz-random-alloc.c
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
#include <mimalloc.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define MAX_ALLOC (1024 * 512)
|
||||||
|
#define MAX_COUNT 32
|
||||||
|
#define ALLOCATION_POINTERS 1024
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
#define debug_print(fmt, ...) \
|
||||||
|
do { if (DEBUG) fprintf(stderr, fmt, __VA_ARGS__); } while (0)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CALLOC = 0,
|
||||||
|
FREE,
|
||||||
|
MALLOC,
|
||||||
|
MALLOCN,
|
||||||
|
REALLOC,
|
||||||
|
REALLOCF,
|
||||||
|
REALLOCN,
|
||||||
|
ZALLOC,
|
||||||
|
LAST_NOP,
|
||||||
|
} allocation_op_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t count;
|
||||||
|
uint32_t size;
|
||||||
|
} arg_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// The index of the pointer to apply this operation too.
|
||||||
|
uint32_t index;
|
||||||
|
// The arguments to use in the operation.
|
||||||
|
arg_t any_arg;
|
||||||
|
// The type of operation to apply.
|
||||||
|
allocation_op_t type;
|
||||||
|
} fuzzing_operation_t;
|
||||||
|
|
||||||
|
void debug_print_operation(fuzzing_operation_t *operation) {
|
||||||
|
const char *names[] = {"CALLOC", "FREE", "MALLOC", "MALLOCN", "REALLOC", "REALLOCF", "REALLOCN", "ZALLOC", "LAST_NOP"};
|
||||||
|
debug_print("index: %d, arg.count: %d, arg.size: %d, type: %s\n", operation->index, operation->any_arg.count, operation->any_arg.size, names[operation->type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FUZZING_OPERATION_DATA_SIZE sizeof(fuzzing_operation_t)
|
||||||
|
|
||||||
|
int init_fuzzing_operation(fuzzing_operation_t* out, const uint8_t* fuzzed_data, size_t len) {
|
||||||
|
fuzzing_operation_t result = {0, {0,0},FREE};
|
||||||
|
|
||||||
|
// Return a free operation if we don't have enough data to construct
|
||||||
|
// a full operation.
|
||||||
|
if(sizeof(fuzzing_operation_t) > len) {
|
||||||
|
*out = result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomly populate operation using fuzzed data.
|
||||||
|
memcpy(&result, fuzzed_data, sizeof(fuzzing_operation_t));
|
||||||
|
|
||||||
|
// Fix up bounds for args and indicies. Randomly copying fuzzed data may result
|
||||||
|
// in out of bounds indicies or the fuzzer trying to allocate way too much data.
|
||||||
|
result.index %= ALLOCATION_POINTERS;
|
||||||
|
result.any_arg.count %= MAX_COUNT;
|
||||||
|
result.any_arg.size %= MAX_ALLOC;
|
||||||
|
result.type = (uint8_t)result.type % (uint8_t)LAST_NOP;
|
||||||
|
*out = result;
|
||||||
|
|
||||||
|
return sizeof(fuzzing_operation_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||||
|
mi_heap_t * heap = mi_heap_new();
|
||||||
|
void* allocation_ptrs[ALLOCATION_POINTERS] = {NULL};
|
||||||
|
|
||||||
|
for(size_t i = 0; i < size; i = i + FUZZING_OPERATION_DATA_SIZE) {
|
||||||
|
fuzzing_operation_t operation = {0, {0,0}, FREE};
|
||||||
|
init_fuzzing_operation(&operation, data + i, size - i);
|
||||||
|
|
||||||
|
debug_print_operation(&operation);
|
||||||
|
|
||||||
|
switch(operation.type) {
|
||||||
|
case CALLOC:
|
||||||
|
if(allocation_ptrs[operation.index] == NULL) {
|
||||||
|
debug_print("%s\n","CALLOC");
|
||||||
|
allocation_ptrs[operation.index] = mi_heap_calloc(heap, operation.any_arg.count, operation.any_arg.size);
|
||||||
|
} else {
|
||||||
|
debug_print("%s\n","CALLOC conditions not met");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FREE:
|
||||||
|
// Can be ptr or be NULL so we don't need to check first.
|
||||||
|
mi_free(allocation_ptrs[operation.index]);
|
||||||
|
allocation_ptrs[operation.index] = NULL;
|
||||||
|
break;
|
||||||
|
case MALLOC:
|
||||||
|
if(allocation_ptrs[operation.index] == NULL){
|
||||||
|
debug_print("%s\n","MALLOC");
|
||||||
|
allocation_ptrs[operation.index] = mi_heap_malloc(heap, operation.any_arg.size);
|
||||||
|
} else {
|
||||||
|
debug_print("%s\n","MALLOC conditions not met");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MALLOCN:
|
||||||
|
if(allocation_ptrs[operation.index] == NULL){
|
||||||
|
debug_print("%s\n","MALLOCN");
|
||||||
|
allocation_ptrs[operation.index] = mi_heap_mallocn(heap, operation.any_arg.count, operation.any_arg.size);
|
||||||
|
} else {
|
||||||
|
debug_print("%s\n","MALLOCN conditions not met");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REALLOC:
|
||||||
|
if(allocation_ptrs[operation.index] != NULL){
|
||||||
|
debug_print("%s\n","REALLOC");
|
||||||
|
allocation_ptrs[operation.index] = mi_heap_realloc(heap, allocation_ptrs[operation.index], operation.any_arg.size);
|
||||||
|
} else {
|
||||||
|
debug_print("%s\n","REALLOC conditions not met");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REALLOCN:
|
||||||
|
if(allocation_ptrs[operation.index] != NULL){
|
||||||
|
debug_print("%s\n","REALLOCN");
|
||||||
|
allocation_ptrs[operation.index] = mi_heap_reallocn(heap, allocation_ptrs[operation.index], operation.any_arg.count, operation.any_arg.size);
|
||||||
|
} else {
|
||||||
|
debug_print("%s\n","REALLOCN conditions not met");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REALLOCF:
|
||||||
|
if(allocation_ptrs[operation.index] != NULL){
|
||||||
|
debug_print("%s\n","REALLOCF");
|
||||||
|
allocation_ptrs[operation.index] = mi_heap_reallocf(heap, allocation_ptrs[operation.index], operation.any_arg.size);
|
||||||
|
} else {
|
||||||
|
debug_print("%s\n","REALLOCF conditions not met");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZALLOC:
|
||||||
|
if(allocation_ptrs[operation.index] == NULL){
|
||||||
|
debug_print("%s\n","ZALLOC");
|
||||||
|
allocation_ptrs[operation.index] = mi_heap_zalloc(heap, operation.any_arg.size);
|
||||||
|
} else {
|
||||||
|
debug_print("%s\n","ZALLOC conditions not met");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LAST_NOP:
|
||||||
|
// No-op
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mi_heap_destroy(heap);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mi_heap_destroy(heap);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue