Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

afl persistent mode #2012

Closed
GrosQuildu opened this issue Mar 26, 2020 · 3 comments
Closed

afl persistent mode #2012

GrosQuildu opened this issue Mar 26, 2020 · 3 comments
Labels
kind: bug state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated

Comments

@GrosQuildu
Copy link

AFL's persistent mode (__AFL_LOOP(1000)) has very poor stability (around 5%).

Environment:

AFL is AFL++ from master.

json/(develop) » afl-clang-fast --version
afl-clang-fast++2.62d by <lszekeres@google.com>
clang version 10.0.0-++20200323042644+d32170dbd5b-1~exp1~20200323154014.129 
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm-10/bin

json/(develop) » CC=afl-clang-fast CXX=afl-clang-fast++ make fuzzers -Ctest
json/(develop) » mkdir input && echo x >input/x && afl-fuzz -i input -o output ./parse_afl_fuzzer

It may be due to the invalid usage of cin.get, but not sure about that. Replacing file with test/src/fuzzer-driver_afl.cpp:

/*
    __ _____ _____ _____
 __|  |   __|     |   | |  JSON for Modern C++ (fuzz test support)
|  |  |__   |  |  | | | |  version 3.7.3
|_____|_____|_____|_|___|  https://github.com/nlohmann/json

This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on
an implementation of the `LLVMFuzzerTestOneInput` function which processes a
passed byte array.

Licensed under the MIT License <http://opensource.org/licenses/MIT>.
*/

#include <vector>    // for vector
#include <cstdint>   // for uint8_t
#include <iostream>  // for cin
#include <cstring>   // for memcpy
#include <unistd.h>  // for read

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);

static const std::size_t MaxInputSize = 1048576;  // 1MiB
static uint8_t InputBuf[MaxInputSize];

int main() {
  /* AFL deferred fork */
  __AFL_INIT();

  /* AFL persistent loop */
  while(__AFL_LOOP(1000)) {
     /* read data*/
      ssize_t bytesReaded = read(0, InputBuf, MaxInputSize);
      if (bytesReaded > 0) {
        /* allocate memory, exactly bytesReaded to catch overflows */
        uint8_t *tmpBuf = (uint8_t*)malloc(bytesReaded);
        memcpy(tmpBuf, InputBuf, bytesReaded);

        /* run harness*/
        LLVMFuzzerTestOneInput(tmpBuf, bytesReaded);

        /* clear */
        free(tmpBuf);
      }
    }
  return 0;
}

yields 100% stability (performance is about the same).

nlohmann added a commit that referenced this issue Apr 11, 2020
@nlohmann
Copy link
Owner

@GrosQuildu Thanks for reporting.

I created a branch https://github.com/nlohmann/json/tree/feature/afl_persistent with your proposed change. I had to make some changes to make it compile via

make fuzz_testing

Then, I get the following warning on (odd, check syntax!):

image

Any ideas?

Sorry for the questions - since the project is fuzz tested by OSSFuzz, I have not executed AFL regularly.

@GrosQuildu
Copy link
Author

__AFL_HAVE_MANUAL_CONTROL is defined only with afl-clang-fast, not with afl-clang nor afl-gcc. Fix like:

#include <vector>    // for vector
#include <cstdint>   // for uint8_t
#include <iostream>  // for cin
#include <cstring>   // for memcpy
#include <unistd.h>  // for read

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);

static const std::size_t MaxInputSize = 1048576;  // 1MiB
static uint8_t InputBuf[MaxInputSize];

int main()
{
#ifdef __AFL_HAVE_MANUAL_CONTROL
    /* AFL deferred fork */
    __AFL_INIT();

    /* AFL persistent loop */
    while (__AFL_LOOP(1000))
    {
#endif

        /* read data*/
        ssize_t bytesReadedS = read(0, InputBuf, MaxInputSize);
        if (bytesReadedS > 0)
        {
            size_t bytesReaded = static_cast<size_t>(bytesReadedS);
            /* allocate memory, exactly bytesReaded to catch overflows */
            uint8_t* tmpBuf = static_cast<uint8_t*>(malloc(bytesReaded));
            memcpy(tmpBuf, InputBuf, bytesReaded);

            /* run harness*/
            LLVMFuzzerTestOneInput(tmpBuf, bytesReaded);

            /* clear */
            free(tmpBuf);
        }

#ifdef __AFL_HAVE_MANUAL_CONTROL
    }
#endif
    return 0;
}

nlohmann added a commit that referenced this issue May 10, 2020
@stale
Copy link

stale bot commented May 24, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label May 24, 2020
@stale stale bot closed this as completed May 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated
Projects
None yet
Development

No branches or pull requests

2 participants