Skip to content

Commit

Permalink
cmake: Add libfuzzer harness and target
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Oct 26, 2024
1 parent c2329a7 commit c2bc81e
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ if(BUILD_LTO)
endif()
endif()

option(BUILD_FUZZER "Build instrumented binary for fuzzing with libfuzzer, requires clang")
if(BUILD_FUZZER)
# Override CFLAGS early for instrumentation. Disable shared libs for instrumentation.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,fuzzer-no-link")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,fuzzer-no-link")
set(BUILD_SHARED_LIBS OFF)
endif()

include(GNUInstallDirs)

#--------------------------------------------------
Expand Down
10 changes: 10 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
add_executable(chdr-benchmark benchmark.c)
target_link_libraries(chdr-benchmark PRIVATE chdr-static)

# fuzzing
if(BUILD_FUZZER)
add_executable(chdr-fuzz fuzz.c)
target_link_options(chdr-fuzz PRIVATE "-fsanitize=address,fuzzer")
target_link_libraries(chdr-fuzz PRIVATE chdr-static)
add_custom_target(fuzz
COMMAND "$<TARGET_FILE:chdr-fuzz>" "-max_len=131072"
DEPENDS chdr-fuzz)
endif()
80 changes: 80 additions & 0 deletions tests/fuzz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include <libchdr/chd.h>
#include <libchdr/coretypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
const uint8_t *buffer;
size_t buffer_size;
size_t buffer_pos;
} membuf;

static uint64_t membuf_fsize(struct chd_core_file *cf) {
return ((membuf *)cf->argp)->buffer_size;
}

static size_t membuf_fread(void *buf, size_t size, size_t count,
struct chd_core_file *cf) {
membuf *mb = (membuf *)cf->argp;
if ((UINT32_MAX / size) < count)
return 0;
size_t copy = size * count;
size_t remain = mb->buffer_size - mb->buffer_pos;
if (remain < copy)
copy = remain;
memcpy(buf, &mb->buffer[mb->buffer_pos], copy);
mb->buffer_pos += copy;
return copy;
}

static int membuf_fclose(struct chd_core_file *cf) { return 0; }

static int membuf_fseek(struct chd_core_file *cf, int64_t pos, int origin) {
membuf *mb = (membuf *)cf->argp;
if (origin == SEEK_SET) {
if (pos < 0 || (size_t)pos > mb->buffer_size)
return -1;
mb->buffer_pos = (size_t)pos;
return 0;
} else if (origin == SEEK_CUR) {
if (pos < 0 && (size_t)-pos > mb->buffer_pos)
return -1;
else if ((mb->buffer_pos + (size_t)pos) > mb->buffer_size)
return -1;
mb->buffer_pos =
(pos < 0) ? (mb->buffer_pos - (size_t)-pos) : (mb->buffer_pos + pos);
return 0;
} else if (origin == SEEK_END) {
mb->buffer_pos = mb->buffer_size;
return 0;
} else {
return -1;
}
}

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
unsigned int i;
unsigned int totalbytes;
void *buffer;
membuf mb = {data, size, 0u};
struct chd_core_file cf = {&mb, membuf_fsize, membuf_fread, membuf_fclose,
membuf_fseek};
chd_file *file;
const chd_header *header;
chd_error err = chd_open_core_file(&cf, CHD_OPEN_READ, NULL, &file);
if (err != CHDERR_NONE)
return 0;

header = chd_get_header(file);
totalbytes = header->hunkbytes * header->totalhunks;
buffer = malloc(header->hunkbytes);
for (i = 0; i < header->totalhunks; i++) {
err = chd_read(file, i, buffer);
if (err != CHDERR_NONE)
continue;
}
free(buffer);
chd_close(file);
return 0;
}

0 comments on commit c2bc81e

Please sign in to comment.