zeek/src/fuzzers/FuzzBuffer.cc
Justin Azoff 6aa6eea7bc Speed up ChunkCount validity check
When counting chunks for the purpose of a Valid check, only count up to
chunk_count_limit + 1 chunks.  This speeds up the skipping of the 70,000
chunk test file considerably.

Before:
    Processed 1 inputs in 0.025517s

After:
    Processed 1 inputs in 0.000620s
2020-05-21 12:55:00 -04:00

88 lines
1.9 KiB
C++

#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#include <string.h>
#include "FuzzBuffer.h"
bool zeek::detail::FuzzBuffer::Valid(int chunk_count_limit) const
{
if ( end - begin < PKT_MAGIC_LEN + 2 )
return false;
if ( memcmp(begin, PKT_MAGIC, PKT_MAGIC_LEN) != 0)
return false;
if ( ChunkCount(chunk_count_limit + 1) > chunk_count_limit )
return false;
return true;
}
int zeek::detail::FuzzBuffer::ChunkCount(int chunk_count_limit) const
{
auto pos = begin;
int chunks = 0;
while ( pos < end && (chunk_count_limit == 0 || chunks < chunk_count_limit) )
{
pos = (const unsigned char*)memmem(pos, end - pos,
PKT_MAGIC, PKT_MAGIC_LEN);
if ( ! pos )
break;
pos += PKT_MAGIC_LEN + 1;
chunks++;
}
return chunks;
}
std::optional<zeek::detail::FuzzBuffer::Chunk> zeek::detail::FuzzBuffer::Next()
{
if ( begin == end )
return {};
auto pos = (const unsigned char*)memmem(begin, end - begin,
PKT_MAGIC, PKT_MAGIC_LEN);
if ( ! pos )
return {};
begin += PKT_MAGIC_LEN;
auto remaining = end - begin;
if ( remaining < 2 )
return {};
Chunk rval;
rval.is_orig = begin[0] & 0x01;
begin += 1;
auto chunk_begin = begin;
auto next = (const unsigned char*)memmem(begin, end - begin,
PKT_MAGIC, PKT_MAGIC_LEN);
if ( next )
begin = next;
else
begin = end;
rval.size = begin - chunk_begin;
if ( rval.size )
{
// The point of allocating a new buffer here is to better detect
// analyzers that may over-read within a chunk -- ASan wouldn't
// complain if that happens to land within the full input buffer
// provided by the fuzzing engine, but will if we allocate a new buffer
// for each chunk.
rval.data = std::make_unique<unsigned char[]>(rval.size);
memcpy(rval.data.get(), chunk_begin, rval.size);
return {std::move(rval)};
}
return {};
}