#if ! defined(_GNU_SOURCE) #define _GNU_SOURCE #endif #ifdef _MSC_VER #include #endif #include "zeek/fuzzers/FuzzBuffer.h" #include namespace zeek::detail { bool 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 ( ExceedsChunkLimit(chunk_count_limit) ) return false; return true; } int FuzzBuffer::ChunkCount(int chunk_count_limit) const { auto pos = begin; int chunks = 0; while ( pos < end && (chunks < chunk_count_limit || chunk_count_limit == 0) ) { 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 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(rval.size); memcpy(rval.data.get(), chunk_begin, rval.size); return {std::move(rval)}; } return {}; } } // namespace zeek::detail