libisoalloc-sys 0.3.0

Security oriented allocator
Documentation
/* iso_alloc alloc_fuzz.c
 * Copyright 2023 - chris.rohlf@gmail.com */

/* This test is not meant to be run as a part of the IsoAlloc
 * test suite. It should be run stand alone during development
 * work to catch any bugs you introduce */

#include "iso_alloc.h"
#include "iso_alloc_internal.h"
#include <time.h>

static const uint32_t allocation_sizes[] = {ZONE_16, ZONE_32, ZONE_64, ZONE_128,
                                            ZONE_256, ZONE_512, ZONE_1024,
                                            ZONE_2048, ZONE_4096, ZONE_8192,
                                            SMALL_SIZE_MAX};

static const uint32_t array_sizes[] = {16, 32, 64, 128, 256};

static __thread iso_alloc_zone_handle *private_zone;

#define MAYBE_VALIDATE_ZONES() \
    if((rand() % 10) == 1) {   \
        iso_verify_zones();    \
    }

int64_t reallocate(size_t array_size, size_t allocation_size) {
    uint64_t allocs = 0;
    void *p[array_size];
    memset(p, 0x0, array_size);

    for(int i = 0; i < array_size; i++) {
        if(allocation_size == 0) {
            allocation_size = allocation_sizes[(rand() % sizeof(allocation_sizes) / sizeof(uint32_t))] + (rand() % 32);
        }

        void *d = iso_alloc(allocation_size / 2);
        allocs++;
        memset(d, 0x0, allocation_size / 2);
        p[i] = iso_realloc(d, allocation_size);
        allocs++;

        if(p[i] == NULL) {
            LOG_AND_ABORT("Failed to allocate %ld bytes", allocation_size);
        }

        /* Free every other allocation */
        if(i % 2) {
            iso_free(p[i]);
            p[i] = NULL;
        }
    }

    MAYBE_VALIDATE_ZONES();

    /* Free the remaining allocations */
    for(int i = 0; i < array_size; i++) {
        iso_free(p[i]);
    }

    return allocs;
}

int64_t callocate(size_t array_size, size_t allocation_size) {
    uint64_t allocs = 0;
    void *p[array_size];
    memset(p, 0x0, array_size);

    for(int i = 0; i < array_size; i++) {
        if(allocation_size == 0) {
            allocation_size = allocation_sizes[(rand() % sizeof(allocation_sizes) / sizeof(uint32_t))] + (rand() % 32);
        }

        p[i] = iso_calloc(1, allocation_size);
        allocs++;

        if(p[i] == NULL) {
            LOG_AND_ABORT("Failed to allocate %ld bytes", allocation_size);
        }

        /* Free every other allocation */
        if(i % 2) {
            iso_free(p[i]);
            p[i] = NULL;
        }
    }

    MAYBE_VALIDATE_ZONES();

    /* Free the remaining allocations */
    for(int i = 0; i < array_size; i++) {
        iso_free(p[i]);
    }

    return allocs;
}

int64_t allocate(size_t array_size, size_t allocation_size) {
    uint64_t allocs = 0;
    void *p[array_size];
    memset(p, 0x0, array_size);

    if(rand() % 100 == 1) {
        if(private_zone != NULL) {
            iso_alloc_destroy_zone(private_zone);

            private_zone = NULL;
        }

        if(allocation_size <= SMALL_SIZE_MAX) {
            private_zone = iso_alloc_new_zone(allocation_size);

            if(private_zone == NULL) {
                LOG_AND_ABORT("Could not allocate private zone!");
            }
        }
    }

    for(int i = 0; i < array_size; i++) {
        if(allocation_size == 0) {
            allocation_size = allocation_sizes[(rand() % sizeof(allocation_sizes) / sizeof(uint32_t))] + (rand() % 32);
        }

        if(rand() % 100 == 1 && private_zone != NULL && allocation_size < SMALL_SIZE_MAX) {
            p[i] = iso_alloc_from_zone(private_zone);
            allocs++;
        } else {
            p[i] = iso_alloc(allocation_size);
            allocs++;
        }

        if(p[i] == NULL) {
            LOG_AND_ABORT("Failed to allocate %ld bytes", allocation_size);
        }

        /* Free every other allocation */
        if(i % 2) {
            iso_free(p[i]);
            p[i] = NULL;
        }
    }

    MAYBE_VALIDATE_ZONES();

    /* Free the remaining allocations */
    for(int i = 0; i < array_size; i++) {
        /* Occasionally leak chunks */
        if((rand() % 100) == 1) {
            iso_free(p[i]);
        }
    }

    if(rand() % 10 == 1) {
        iso_alloc_destroy_zone(private_zone);
        private_zone = NULL;
    }

    return allocs;
}

void *start(void *p) {
    uint64_t total_allocations = 0;
    uint64_t loop = 1;
    srand(time(NULL));

    while(1) {
        for(int i = 0; i < sizeof(array_sizes) / sizeof(uint32_t); i++) {
            for(int z = 0; z < sizeof(allocation_sizes) / sizeof(uint32_t); z++) {
                total_allocations += allocate(array_sizes[i], allocation_sizes[z]);
            }
        }

        for(int i = 0; i < sizeof(array_sizes) / sizeof(uint32_t); i++) {
            total_allocations += allocate(array_sizes[i], 0);
        }

        for(int i = 0; i < sizeof(array_sizes) / sizeof(uint32_t); i++) {
            for(int z = 0; z < sizeof(allocation_sizes) / sizeof(uint32_t); z++) {
                total_allocations += callocate(array_sizes[i], allocation_sizes[z]);
            }
        }

        for(int i = 0; i < sizeof(array_sizes) / sizeof(uint32_t); i++) {
            total_allocations += callocate(array_sizes[i], 0);
        }

        for(int i = 0; i < sizeof(array_sizes) / sizeof(uint32_t); i++) {
            for(int z = 0; z < sizeof(allocation_sizes) / sizeof(uint32_t); z++) {
                total_allocations += reallocate(array_sizes[i], allocation_sizes[z]);
            }
        }

        for(int i = 0; i < sizeof(array_sizes) / sizeof(uint32_t); i++) {
            total_allocations += reallocate(array_sizes[i], 0);
        }

        LOG("Thread ID (%d) looped %d times. Total allocations: %ld", pthread_self(), loop++, total_allocations);
    }
}

int main(int argc, char *argv[]) {
    private_zone = NULL;

    pthread_t t;
    pthread_t tt;
    pthread_t ttt;
    pthread_t tttt;
    pthread_create(&t, NULL, start, NULL);
    pthread_create(&tt, NULL, start, NULL);
    pthread_create(&ttt, NULL, start, NULL);
    pthread_create(&tttt, NULL, start, NULL);

    pthread_join(t, NULL);
    pthread_join(tt, NULL);
    pthread_join(ttt, NULL);
    pthread_join(tttt, NULL);
    pthread_exit(NULL);

    return 0;
}