view dbmalloc.c @ 1375:d8215479a58a fuzz

fuzzing has a constant time
author Matt Johnston <matt@ucc.asn.au>
date Thu, 25 May 2017 22:20:10 +0800
parents 9aa6cd66b51d
children 7209a6e30932
line wrap: on
line source

#include "dbmalloc.h"
#include "dbutil.h"

#define LIST_SIZE 1000

struct dbmalloc_header {
    unsigned int index;
    unsigned int epoch;
};

static struct dbmalloc_header* dbmalloc_list[LIST_SIZE];

unsigned int current_epoch = 0;

void m_malloc_set_epoch(unsigned int epoch) {
    current_epoch = epoch;
}

void m_malloc_free_epoch(unsigned int epoch) {
    unsigned int i;
    unsigned int freed = 0;
    for (i = 0; i < LIST_SIZE; i++) {
        if (dbmalloc_list[i] != NULL) {
            assert(dbmalloc_list[i]->index == i);
            if (dbmalloc_list[i]->epoch == epoch) {
                free(dbmalloc_list[i]);
                dbmalloc_list[i] = NULL;
                freed++;
            }
        }
    }
    TRACE(("free_epoch freed %d", freed))
}

static void put_alloc(struct dbmalloc_header *header) {
    unsigned int i;
    for (i = 0; i < LIST_SIZE; i++) {
        if (dbmalloc_list[i] == NULL) {
            dbmalloc_list[i] = header;
            header->index = i;
            return;
        }
    }
    dropbear_exit("ran out of dbmalloc entries");
}

static void remove_alloc(struct dbmalloc_header *header) {
    assert(header->index < LIST_SIZE);
    assert(dbmalloc_list[header->index] == header);
    assert(header->epoch == current_epoch);
    dbmalloc_list[header->index] = NULL;
}

static struct dbmalloc_header* get_header(void* ptr) {
    char* bptr = ptr;
    return (struct dbmalloc_header*)&bptr[-sizeof(struct dbmalloc_header)];
}

void * m_malloc(size_t size) {
    char* mem = NULL;
    struct dbmalloc_header* header = NULL;

    if (size == 0 || size > 1e9) {
        dropbear_exit("m_malloc failed");
    }

    size = size + sizeof(struct dbmalloc_header);

    mem = calloc(1, size);
    if (mem == NULL) {
        dropbear_exit("m_malloc failed");
    }
    header = (struct dbmalloc_header*)mem;
    put_alloc(header);
    header->epoch = current_epoch;
    return &mem[sizeof(struct dbmalloc_header)];
}

void * m_calloc(size_t nmemb, size_t size) {
    if (SIZE_T_MAX / nmemb < size) {
        dropbear_exit("m_calloc failed");
    }
    return m_malloc(nmemb*size);
}

void * m_realloc(void* ptr, size_t size) {
    char* mem = NULL;
    struct dbmalloc_header* header = NULL;
    if (size == 0 || size > 1e9) {
        dropbear_exit("m_realloc failed");
    }

    header = get_header(ptr);
    remove_alloc(header);

    size = size + sizeof(struct dbmalloc_header);
    mem = realloc(header, size);
    if (mem == NULL) {
        dropbear_exit("m_realloc failed");
    }

    header = (struct dbmalloc_header*)mem;
    put_alloc(header);
    return &mem[sizeof(struct dbmalloc_header)];
}

void m_free_direct(void* ptr) {
    struct dbmalloc_header* header = NULL;
    if (!ptr) {
        return;
    }
    header = get_header(ptr);
    remove_alloc(header);
    free(header);
}

void * m_strdup(const char * str) {
    char* ret;
    unsigned int len;
    len = strlen(str);

    ret = m_malloc(len+1);
    if (ret == NULL) {
        dropbear_exit("m_strdup failed");
    }
    memcpy(ret, str, len+1);
    return ret;
}