AFLplusplus: COMPCOV float bug?

It seems like there is a bug in the float splitting of compcov that was found in oss-fuzz in a bitcoin_core harness.

fuzzing harness:

#include <memusage.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <util/serfloat.h>
#include <version.h>

#include <cassert>
#include <cmath>
#include <limits>

FUZZ_TARGET(float)
{
    FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());

    {
        const double d{[&] {
            double tmp;
            CallOneOf(
                fuzzed_data_provider,
                // an actual number
                [&] { tmp = fuzzed_data_provider.ConsumeFloatingPoint<double>(); },
                // special numbers and NANs
                [&] { tmp = fuzzed_data_provider.PickValueInArray({
                          std::numeric_limits<double>::infinity(),
                          -std::numeric_limits<double>::infinity(),
                          std::numeric_limits<double>::min(),
                          -std::numeric_limits<double>::min(),
                          std::numeric_limits<double>::max(),
                          -std::numeric_limits<double>::max(),
                          std::numeric_limits<double>::lowest(),
                          -std::numeric_limits<double>::lowest(),
                          std::numeric_limits<double>::quiet_NaN(),
                          -std::numeric_limits<double>::quiet_NaN(),
                          std::numeric_limits<double>::signaling_NaN(),
                          -std::numeric_limits<double>::signaling_NaN(),
                          std::numeric_limits<double>::denorm_min(),
                          -std::numeric_limits<double>::denorm_min(),
                      }); },
                // Anything from raw memory (also checks that DecodeDouble doesn't crash on any input)
                [&] { tmp = DecodeDouble(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); });
            return tmp;
        }()};
        (void)memusage::DynamicUsage(d);

        uint64_t encoded = EncodeDouble(d);
        if constexpr (std::numeric_limits<double>::is_iec559) {
            if (!std::isnan(d)) {
                uint64_t encoded_in_memory;
                std::copy((const unsigned char*)&d, (const unsigned char*)(&d + 1), (unsigned char*)&encoded_in_memory);
                assert(encoded_in_memory == encoded);
            }
        }
        double d_deserialized = DecodeDouble(encoded);
        assert(std::isnan(d) == std::isnan(d_deserialized));
        assert(std::isnan(d) || d == d_deserialized);
    }
}

testcase that results in an assert failure:

00000000:  0000 0000 0000 0000 0000 0000 0000 0000    [ ................ ]
00000010:  0000 0000 0000 0000 0000 0000 0000 0000    [ ................ ]
00000020:  0000 0000 0000 0000 0080 0000 0000 8000    [ ................ ]
00000030:  00ff ffff ff00 0000 0000 0000 0000 8041    [ ...............A ]

obtain testcase: wget 'https://oss-fuzz.com/download?testcase_id=6121564358180864'

to run:

./float testcase.bin
Running LLVMFuzzerInitialize ...
continue...
Reading 64 bytes from testcase.bin
float: test/fuzz/float.cpp:55: void float_fuzz_target(FuzzBufferType): Assertion `encoded_in_memory == encoded' failed.
Aborted

Download compiled harness and testcase: https://we.tl/t-KZiOA4NXOd

to build:

git clone --depth=1 https://github.com/google/oss-fuzz
cd oss-fuzz
echo N|python infra/helper.py build_image base-builder
echo N|python infra/helper.py build_image bitcoin_core
python infra/helper.py shell --sanitizer address --engine afl --architecture x86_64 bitcoin_core
# then in the shell:
  vi /usr/local/bin/compile_afl
  # change lines to
    export AFL_ENABLE_CMPLOG=0
    export AFL_LAF_CHANCE=100
  # save and exit
  # to update afl++:
  pushd /src/aflplusplus/
  git checkout dev
  git pull
  bash # <- important!
  unset CFLAGS
  unset CXXFLAGS
  make install
  exit # <- important
  popd
  compile  # <- this builds the target
  exit # exit docker shell
# compiled harness is in build/out/bitcoin-core outside of the docker container

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 18 (18 by maintainers)

Commits related to this issue

Most upvoted comments

ah typo. python infra/helper.py build_image bitcoin-core dash not underscore 😦