Code Monkey home page Code Monkey logo

mallocfail's Introduction

Malloc Fail

This is a shared library that aims to help you test memory allocation failures in a fairly deterministic manner. It was inspired by a stackoverflow answer:

https://stackoverflow.com/questions/1711170/unit-testing-for-failed-malloc

I saw a cool solution to this problem which was presented to me by S.
Paavolainen. The idea is to override the standard malloc(), which you can do
just in the linker, by a custom allocator which

 1. reads the current execution stack of the thread calling malloc()
 2. checks if the stack exists in a database that is stored on hard disk
    1. if the stack does not exist, adds the stack to the database and returns NULL
    2. if the stack did exist already, allocates memory normally and returns

Then you just run your unit test many times---this system automatically
enumerates through different control paths to malloc() failure and is much more
efficient and reliable than e.g. random testing.

mallocfail.so implements this behaviour for you. It overrides malloc, calloc, and realloc with custom versions. Each time a custom allocator runs, the function uses libbacktrace to generate a text representation of the current call stack, and then generates a sha256 hash of that text. It then checks to see if the new hash has already been seen. If it has never been seen before, then the memory allocation fails and the hash is stored in memory and written to disk. If the hash (i.e. the particular call stack) has been seen before, then the normal libc version of the allocator is called as normal. Each time the program starts, the hashes that have already been seen are loaded in from disk.

The magic of the mallocfail library is that it does not require your program to be modified, as long as debug symbols are available (i.e. no stripped executables). You simply use the LD_PRELOAD linker environment variable to tell the linker to use the malloc etc. implementations in mallocfail instead of the libc versions.

Simple Usage

The easiest way to use mallocfail is with the provded mallocfail wrapper script:

mallocfail <your executable>

If you want more control, then to use mallocfail with your executable you need to set the LD_PRELOAD environment variable.

LD_PRELOAD=/usr/local/lib/mallocfail.so <your executable>

Note that the location of mallocfail.so may be different on your system, substitute the path in that you have instead. If you have compiled yourself and are still in the mallocfail directory, then use

LD_PRELOAD=./mallocfail.so <your executable>

It is not recommended to set LD_PRELOAD by using export before running your executable, because any subsequent command will be affected.

export LD_PRELOAD=/usr/local/lib/mallocfail.so
my_executable_test
ssh myhost # this will certainly fail

Keep running your program until no more entries are being added to the hashes file. It may take a lot of testing to achieve this.

You may find that your program crashes, or produces unexpected behaviour at some point. If you want to repeat your test, remove the last line or last few lines from the hashes file and repeat your program. It may be helpful to set the MALLOCFAIL_DEBUG environment variable to give you more information on what is happening.

LD_PRELOAD=/usr/local/lib/mallocfail.so MALLOCFAIL_DEBUG=1 <your executable>

Using the debug option in this manner rather than setting it outright means you are not bombarded with information on failures that are handled correctly. See the Environment Variables section below for more information on MALLOCFAIL_DEBUG.

Usage in GDB

Start gdb as normal:

 gdb <your executable>

or

 gdb --args <your executable> <your executable arguments>

Then configure LD_PRELOAD in the gdb command window:

 set environment LD_PRELOAD /usr/local/lib/mallocfail.so

Then run your program

 run

You can then run multiple times to test all outcomes, debug any crashes and so on.

Environment Variables

You can control the behaviour of mallocfail with some environment variables.

MALLOCFAIL_FILE determines the file that hashes will be written to. Defaults to mallocfail_hashes if not set.

MALLOCFAIL_DEBUG - set to 1 to enable debugging information. This has the effect of printing to stdout the stack traces of any allocations that are forced to fail. Enabling this option means the stack trace is generated twice per failed memory allocation, which may have a small effect on performance - worth noting if this is critical to you.

MALLOCFAIL_FAIL_COUNT - set to an integer > 0 to limit the number of failures that can occur in a run. Setting to 1 will ensure that only a single failure will happen per run.

Performance Impact

Allocated memory overhead associated with mallocfail is approximately a constant 2kB on the stack plus 128 bytes on the heap per stored call stack on a 64-bit machine.

Limitations

The current implementation will probably fail badly on threaded programs.

Dependencies

Troy D. Hanson's uthash (included in repository) https://troydhanson.github.io/uthash/

Andrey Jivsov sha3 implementation (included in repository) https://github.com/brainhub/SHA3IUF

Ian Taylor's libbacktrace https://github.com/ianlancetaylor/libbacktrace

mallocfail's People

Contributors

ralight avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

mallocfail's Issues

libFuzzer + random malloc failures

Any idea how to combine mallocfail with libFuzzer ?

Background: I used __malloc_hook etc, but the libFuzzer seems to have it's own malloc hooks or implementation (well, at least it makes sense). So my fuzzer runs as usual. But later when I used the corpora (generated test data files) without libFuzzer, I get SIGSEGV (some code doesn't handle malloc failures gracefully). (Interestingly this is within dependency libraries (libunistring + iconv functionality).)

Direct linking

Is there an description to directly link to mallocfail instead of the preload hook?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.