Randomized allocation failures

Notwithstanding systems with memory overcommit, in which an allocation failure would trigger a kill from the kernel, memory faults may happen and must be handled properly.

In order to validate your code you can use the following wrapper.

/*
 * posix_memalign wrapper with random failures
 *
 * Copyright (c) 2013, Derek Buitenhuis
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#define _GNU_SOURCE

#include <dlfcn.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define LOADSYM(symbol)                                                \
    do {                                                               \
        system_##symbol = dlsym(RTLD_NEXT, #symbol);                   \
        if ((err = dlerror())) {                                       \
            fprintf(stdout, "Can't load "#symbol" symbol: %s\n", err); \
            _exit(1);                                                  \
        }                                                              \
    } while(0)

int posix_memalign(void **memptr, size_t alignment, size_t size)
{
    static time_t seed        = 0;
    static int prob           = 0;
    static uint64_t iteration = 0;

    static int   (* system_posix_memalign)(void **memptr, size_t alignment, size_t size) = NULL;
    static void  (* system_srand)         (unsigned int seed)                            = NULL;
    static int   (* system_rand)          (void)                                         = NULL;
    static char *(* system_getenv)        (const char *name)                             = NULL;
    static int   (* system_atoi)          (const char *str)                              = NULL;

    int ret;

    if (!system_posix_memalign) {
        char *err;

        dlerror();

        LOADSYM(posix_memalign);
        LOADSYM(srand);
        LOADSYM(rand);
        LOADSYM(getenv);
        LOADSYM(atoi);
    }

    if (!seed) {
        char *usertime = system_getenv("MALLOC_SEED");

        if (!usertime)
            seed = time(NULL);
        else
            seed = system_atoi(usertime);

        system_srand(seed);
    }

    if (!prob) {
        char *userprob = system_getenv("MALLOC_FAILPROB");

        if (!userprob)
            prob = 10000;
        else
            prob = system_atoi(userprob);
    }

    if (!(system_rand() % prob)) {
        fprintf(stdout,
                "FAILED. Iteration = %"PRId64", Seed = %lld.\n",
                iteration, (long long) seed);
        ret = 0;
    } else {
        ret = system_posix_memalign(memptr, alignment, size);
    }

    iteration++;

    return ret;
}


CategoryWIP CategorySecurity