Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 4 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ jobs:
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get -o Dpkg::Use-Pty=0 update
sudo rm -f /var/lib/man-db/auto-update
sudo apt-get -o Dpkg::Use-Pty=0 install -y cmake clang ninja-build
sudo apt-get -o Dpkg::Use-Pty=0 install -y \
cmake clang ninja-build protobuf-compiler libprotobuf-dev

- name: Compile mainline
env:
Expand All @@ -54,7 +55,8 @@ jobs:
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get -o Dpkg::Use-Pty=0 update
sudo rm -f /var/lib/man-db/auto-update
sudo apt-get -o Dpkg::Use-Pty=0 install -y cmake clang ninja-build
sudo apt-get -o Dpkg::Use-Pty=0 install -y \
cmake clang ninja-build protobuf-compiler libprotobuf-dev

- name: Compile deps target
run: ./scripts/compile_target.sh deps
Expand Down
61 changes: 56 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,54 @@
cmake_minimum_required(VERSION 3.11)
project(curl_fuzzer_deps)

set(Protobuf_USE_STATIC_LIBS ON CACHE BOOL "Link against static protobuf" FORCE)

if(NOT "$ENV{MAKE}" STREQUAL "")
set(MAKE "$ENV{MAKE}")
else()
set(MAKE "make")
endif()

include(ExternalProject)
find_package(Protobuf REQUIRED)

set(CURL_FUZZER_PROTO ${CMAKE_CURRENT_SOURCE_DIR}/schemas/curl_fuzzer.proto)
protobuf_generate_cpp(CURL_FUZZER_PROTO_SRCS CURL_FUZZER_PROTO_HDRS
${CURL_FUZZER_PROTO})

add_library(curl_fuzzer_proto STATIC ${CURL_FUZZER_PROTO_SRCS})
target_include_directories(curl_fuzzer_proto PUBLIC
${CMAKE_CURRENT_BINARY_DIR}
${PROTOBUF_INCLUDE_DIRS})
target_link_libraries(curl_fuzzer_proto PUBLIC ${PROTOBUF_LIBRARIES})

# Install libprotobuf-mutator
#
# renovate: datasource=github-tags depName=google/libprotobuf-mutator
set(LIB_PROTO_MUTATOR_TAG v1.5)
set(LIB_PROTO_MUTATOR_INSTALL_DIR ${CMAKE_BINARY_DIR}/libprotobuf-mutator-install)
set(LIB_PROTO_MUTATOR_INCLUDE_DIR ${LIB_PROTO_MUTATOR_INSTALL_DIR}/include)
set(LIB_PROTO_MUTATOR_STATIC_LIB ${LIB_PROTO_MUTATOR_INSTALL_DIR}/lib/libprotobuf-mutator.a)
set(LIB_PROTO_MUTATOR_FUZZER_LIB ${LIB_PROTO_MUTATOR_INSTALL_DIR}/lib/libprotobuf-mutator-libfuzzer.a)

ExternalProject_Add(libprotobuf_mutator_external
GIT_REPOSITORY https://github.com/google/libprotobuf-mutator.git
GIT_TAG ${LIB_PROTO_MUTATOR_TAG}
PREFIX ${CMAKE_BINARY_DIR}/libprotobuf-mutator
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${LIB_PROTO_MUTATOR_INSTALL_DIR}
-DBUILD_SHARED_LIBS=OFF
-DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=OFF
-DLIB_PROTO_MUTATOR_WITH_LIBFUZZER=ON
-DLIB_PROTO_MUTATOR_EXAMPLES=OFF
-DLIB_PROTO_MUTATOR_TESTING=OFF
-DProtobuf_USE_STATIC_LIBS=ON
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
BUILD_BYPRODUCTS ${LIB_PROTO_MUTATOR_STATIC_LIB} ${LIB_PROTO_MUTATOR_FUZZER_LIB}
INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
DOWNLOAD_NO_PROGRESS 1
)

# Install zlib
#
Expand Down Expand Up @@ -223,7 +264,8 @@ add_custom_target(deps
zstd_external
libidn2_external
${GDB_DEP}
openldap_external
openldap_external
libprotobuf_mutator_external
)

# Now for the main dependencies!
Expand Down Expand Up @@ -336,7 +378,11 @@ else()
endif()

# Common sources and flags
set(COMMON_SOURCES curl_fuzzer.cc curl_fuzzer_tlv.cc curl_fuzzer_callback.cc)
set(COMMON_SOURCES
curl_fuzzer.cc
curl_fuzzer_tlv.cc
curl_fuzzer_callback.cc
curl_fuzzer_scenario.cc)
set(COMMON_FLAGS -g -DCURL_DISABLE_DEPRECATION)
set(COMMON_LINK_LIBS
${CURL_LIB_DIR}/libcurl.a
Expand All @@ -348,19 +394,24 @@ set(COMMON_LINK_LIBS
${OPENLDAP_STATIC_LIB_LDAP}
${OPENLDAP_STATIC_LIB_LBER}
${LIB_FUZZING_ENGINE}
${LIB_PROTO_MUTATOR_FUZZER_LIB}
${LIB_PROTO_MUTATOR_STATIC_LIB}
curl_fuzzer_proto
pthread
m
)
list(APPEND COMMON_LINK_LIBS ${PROTOBUF_LIBRARIES})
set(COMMON_LINK_OPTIONS ${LIB_FUZZING_ENGINE_FLAG})
list(APPEND COMMON_LINK_OPTIONS -static-libstdc++ -static-libgcc)

# Ensure that curl and its dependencies are built before the fuzzers
set(FUZZ_DEPS curl_external ${CURL_DEPS} ${LIB_FUZZING_ENGINE_DEP})
set(FUZZ_DEPS curl_external ${CURL_DEPS} ${LIB_FUZZING_ENGINE_DEP} curl_fuzzer_proto libprotobuf_mutator_external)

# Helper macro to define a fuzzer target
macro(curl_add_fuzzer _name _proto)
add_executable(${_name} ${COMMON_SOURCES})
target_compile_options(${_name} PRIVATE ${COMMON_FLAGS} -DFUZZ_PROTOCOLS_${_proto})
target_include_directories(${_name} PRIVATE ${CURL_INCLUDE_DIRS})
target_include_directories(${_name} PRIVATE ${CURL_INCLUDE_DIRS} ${LIB_PROTO_MUTATOR_INCLUDE_DIR} ${LIB_PROTO_MUTATOR_INCLUDE_DIR}/libprotobuf-mutator)
target_link_libraries(${_name} PRIVATE ${COMMON_LINK_LIBS})
target_link_options(${_name} PRIVATE ${COMMON_LINK_OPTIONS})
add_dependencies(${_name} ${FUZZ_DEPS})
Expand All @@ -387,7 +438,7 @@ curl_add_fuzzer(curl_fuzzer_ws WS)
# BUFQ fuzzer
add_executable(curl_fuzzer_bufq fuzz_bufq.cc)
target_compile_options(curl_fuzzer_bufq PRIVATE ${COMMON_FLAGS})
target_include_directories(curl_fuzzer_bufq PRIVATE ${CURL_INCLUDE_DIRS})
target_include_directories(curl_fuzzer_bufq PRIVATE ${CURL_INCLUDE_DIRS} ${LIB_PROTO_MUTATOR_INCLUDE_DIR} ${LIB_PROTO_MUTATOR_INCLUDE_DIR}/libprotobuf-mutator)
target_link_libraries(curl_fuzzer_bufq PRIVATE ${COMMON_LINK_LIBS})
target_link_options(curl_fuzzer_bufq PRIVATE ${COMMON_LINK_OPTIONS})
add_dependencies(curl_fuzzer_bufq ${FUZZ_DEPS})
Expand Down
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ temporary directory instead.

`./mainline.sh` is run regressibly by Github Actions.

## Structure-aware fuzzing with libprotobuf-mutator

Every `curl_fuzzer*` binary now links
[libprotobuf-mutator](https://github.com/google/libprotobuf-mutator) directly.
Build the usual targets and you automatically get structured `Scenario`
generation:

```shell
cmake -S . -B build
cmake --build build --target curl_fuzzer
```

The shared engine still understands legacy TLV corpora, but the libFuzzer
entry-point feeds decoded `Scenario` protos into the same execution path, so
crash reports remain comparable to the classic workflow.

## I want more information when running a testcase or multiple testcases

Setting the `FUZZ_VERBOSE` environment variable turns on curl verbose logging.
Expand Down Expand Up @@ -80,6 +96,22 @@ read_corpus <path/to/file>
```
This will print out a list of contents inside the file.

## I want to convert TLV corpora into structured scenarios

Install the tooling (see above), then run the converter to mirror TLV corpus
entries into Scenario `.textproto` files:

```shell
corpora_to_textproto --output scenarios/
```

By default the tool walks the `corpora/` tree and writes `*.textproto` files to
`scenarios/`, preserving the directory structure. You can point `--output` to a
different directory or pass one or more explicit corpus paths when you only
want to convert selected inputs. The converter automatically skips corpora for
the `curl_fuzzer_fnmatch`, `curl_fuzzer_bufq`, and `fuzz_url` harnesses because
they do not use the structured Scenario pipeline.

## I want an HTML decoder for corpus files

Generate a standalone HTML page that can inspect TLV corpora directly in your browser:
Expand Down
20 changes: 20 additions & 0 deletions corpora/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Ignore all the scenario corpora
curl_fuzzer/
curl_fuzzer_dict/
curl_fuzzer_file/
curl_fuzzer_ftp/
curl_fuzzer_gopher/
curl_fuzzer_http/
curl_fuzzer_https/
curl_fuzzer_imap/
curl_fuzzer_ldap/
curl_fuzzer_mqtt/
curl_fuzzer_pop3/
curl_fuzzer_rtmp/
curl_fuzzer_rtsp/
curl_fuzzer_scp/
curl_fuzzer_sftp/
curl_fuzzer_smb/
curl_fuzzer_smtp/
curl_fuzzer_tftp/
curl_fuzzer_ws/
Binary file removed corpora/curl_fuzzer/oss-fuzz-3327
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test1
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test10
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test100
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test100_2
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test100_3
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test1011
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test12
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test1201
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test13
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test1326
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test1450
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test2
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test271
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test3
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test39
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test4
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test5
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test567
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test6
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test64
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test800
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test800_2
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test850
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test900
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test900_2
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test_accept_encoding
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test_file_nobody
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test_ftp_list
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test_ftp_wildcard
Binary file not shown.
Binary file removed corpora/curl_fuzzer/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer/timeout-4625841444093952
Binary file not shown.
Binary file removed corpora/curl_fuzzer_dict/test1450
Binary file not shown.
Binary file removed corpora/curl_fuzzer_dict/test_url_dict
Binary file not shown.
Binary file removed corpora/curl_fuzzer_dict/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_file/test_file_nobody
Binary file not shown.
Binary file removed corpora/curl_fuzzer_file/test_url_file
Binary file not shown.
Binary file removed corpora/curl_fuzzer_file/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ftp/test_ftp_list
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ftp/test_ftp_wildcard
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ftp/test_url_ftp
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ftp/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_gopher/test1201
Binary file not shown.
Binary file removed corpora/curl_fuzzer_gopher/test_url_gopher
Binary file not shown.
Binary file removed corpora/curl_fuzzer_gopher/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test1
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test10
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test100
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test100_2
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test100_3
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test1011
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test12
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test1201
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test13
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test1326
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test1450
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test2
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test271
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test3
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test39
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test4
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test5
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test567
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test6
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test64
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test800
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test800_2
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test850
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test900
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test900_2
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_accept_encoding
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_alt_svc
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_alt_svc_with_ma
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_basic_http2
Binary file not shown.
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_http_upgrade_to_ws
Binary file not shown.
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_http_with_hsts
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_http_with_hsts_tlv
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_invalid_prior_http2
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_ipv6
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_ntlm
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_ntlm_wb
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_url_http
Binary file not shown.
Binary file removed corpora/curl_fuzzer_http/test_wrongproto
Binary file not shown.
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_alt_svc_with_ma
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_altsvc_with_cache
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_hsts_response
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_hsts_response_to_ipv6
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_http_version_2
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_https_ntlm
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_ipv6
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_post_0byte
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_simple_httppost
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_url
Binary file not shown.
Binary file removed corpora/curl_fuzzer_https/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_imap/test800
Binary file not shown.
Binary file removed corpora/curl_fuzzer_imap/test800_2
Binary file not shown.
Binary file removed corpora/curl_fuzzer_imap/test_oauthed_imap
Binary file not shown.
Binary file removed corpora/curl_fuzzer_imap/test_url_imap
Binary file not shown.
Binary file removed corpora/curl_fuzzer_imap/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ldap/test_url_fullldap
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ldap/test_url_ldap
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ldap/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_mqtt/test_dummy
Binary file not shown.
Binary file removed corpora/curl_fuzzer_pop3/test850
Binary file not shown.
Binary file removed corpora/curl_fuzzer_pop3/test_oauthed_pop3
Binary file not shown.
Binary file removed corpora/curl_fuzzer_pop3/test_url_pop3
Binary file not shown.
Binary file removed corpora/curl_fuzzer_pop3/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtmp/test_url_rtmp
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtmp/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/oss-fuzz-issue-6937
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/test567
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/test_rtsp_client_cseq
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/test_rtsp_request
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/test_rtsp_request2
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/test_rtsp_session_id
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/test_rtsp_stream_uri
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/test_rtsp_transport
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/test_url_rtsp
Binary file not shown.
Binary file removed corpora/curl_fuzzer_rtsp/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_scp/test_url_scp
Binary file not shown.
Binary file removed corpora/curl_fuzzer_scp/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_sftp/test_url_sftp
Binary file not shown.
Binary file removed corpora/curl_fuzzer_sftp/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_smb/test_url_smb
Binary file not shown.
Binary file removed corpora/curl_fuzzer_smb/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_smtp/test900
Binary file not shown.
Binary file removed corpora/curl_fuzzer_smtp/test900_2
Binary file not shown.
Binary file removed corpora/curl_fuzzer_smtp/test_mail_auth
Binary file not shown.
Binary file removed corpora/curl_fuzzer_smtp/test_smtps_with_oauth
Binary file not shown.
Binary file removed corpora/curl_fuzzer_smtp/test_url_smtp
Binary file not shown.
Binary file removed corpora/curl_fuzzer_smtp/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_tftp/test_url_tftp
Binary file not shown.
Binary file removed corpora/curl_fuzzer_tftp/test_wrongproto
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ws/basictest
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ws/test_http_upgrade_to_ws
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ws/ws_with_raw_mode_connect_test
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ws/ws_with_raw_mode_test
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ws/wss_test
Binary file not shown.
Binary file removed corpora/curl_fuzzer_ws/wss_with_basic_auth_test
Binary file not shown.
89 changes: 54 additions & 35 deletions curl_fuzzer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,56 +26,66 @@
#include <unistd.h>
#include <curl/curl.h>
#include "curl_fuzzer.h"
#include "curl_fuzzer_scenario.h"

/**
* Fuzzing entry point. This function is passed a buffer containing a test
* case. This test case should drive the CURL API into making a request.
*/
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
#include <libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h>

namespace {

bool FuzzOptionIsSet(const FUZZ_DATA *fuzz, CURLoption opt)
{
size_t idx = static_cast<size_t>(opt % 1000);
if(idx >= FUZZ_CURLOPT_TRACKER_SPACE) {
return false;
}
return fuzz->options[idx] != 0;
}

} // namespace

DEFINE_BINARY_PROTO_FUZZER(const curl::fuzzer::proto::Scenario &scenario)
{
CurlFuzzerRunScenario(scenario);
}

int CurlFuzzerRunScenario(const curl::fuzzer::proto::Scenario &scenario)
{
int rc = 0;
int tlv_rc;
FUZZ_DATA fuzz;
TLV tlv;

/* Ignore SIGPIPE errors. We'll handle the errors ourselves. */
signal(SIGPIPE, SIG_IGN);

/* Have to set all fields to zero before getting to the terminate function */
memset(&fuzz, 0, sizeof(FUZZ_DATA));

if(size < sizeof(TLV_RAW)) {
/* Not enough data for a single TLV - don't continue */
goto EXIT_LABEL;
}

/* Try to initialize the fuzz data */
FTRY(fuzz_initialize_fuzz_data(&fuzz, data, size));

for(tlv_rc = fuzz_get_first_tlv(&fuzz, &tlv);
tlv_rc == 0;
tlv_rc = fuzz_get_next_tlv(&fuzz, &tlv)) {

/* Have the TLV in hand. Parse the TLV. */
rc = fuzz_parse_tlv(&fuzz, &tlv);
FTRY(fuzz_initialize_fuzz_data(&fuzz));

if(rc != 0) {
/* Failed to parse the TLV. Can't continue. */
goto EXIT_LABEL;
}
rc = curl_fuzzer::ApplyScenario(scenario, &fuzz);
if(rc != 0) {
FV_PRINTF(&fuzz, "SCENARIO: ApplyScenario failed with rc=%d\n", rc);
goto EXIT_LABEL;
}

if(tlv_rc != TLV_RC_NO_MORE_TLVS) {
/* A TLV call failed. Can't continue. */
if(!FuzzOptionIsSet(&fuzz, CURLOPT_URL)) {
FV_PRINTF(&fuzz, "SCENARIO: skipping transfer due to missing CURLOPT_URL\n");
goto EXIT_LABEL;
}

FV_PRINTF(&fuzz,
"SCENARIO: successfully applied scenario, starting transfer\n");

/* Set up the standard easy options. */
FTRY(fuzz_set_easy_options(&fuzz));
rc = fuzz_set_easy_options(&fuzz);
if(rc != 0) {
FV_PRINTF(&fuzz, "SCENARIO: fuzz_set_easy_options failed with rc=%d\n", rc);
goto EXIT_LABEL;
}

/**
* Add in more curl options that have been accumulated over possibly
* multiple TLVs.
* Add in more curl options that have been accumulated over the scenario
* execution.
*/
if(fuzz.header_list != NULL) {
curl_easy_setopt(fuzz.easy, CURLOPT_HTTPHEADER, fuzz.header_list);
Expand Down Expand Up @@ -104,6 +114,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
return 0;
}


/**
* Utility function to convert 4 bytes to a u32 predictably.
*/
Expand All @@ -127,24 +138,25 @@ uint16_t to_u16(const uint8_t b[2])
/**
* Initialize the local fuzz data structure.
*/
int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz,
const uint8_t *data,
size_t data_len)
int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz)
{
int rc = 0;
int ii;

/* Initialize the fuzz data. */
memset(fuzz, 0, sizeof(FUZZ_DATA));
fuzz->scenario_state = NULL;
fuzz->scenario_state_destructor = NULL;

/* Create an easy handle. This will have all of the settings configured on
it. */
fuzz->easy = curl_easy_init();
FCHECK(fuzz->easy != NULL);

/* Set up the state parser */
fuzz->state.data = data;
fuzz->state.data_len = data_len;
fuzz->state.data = NULL;
fuzz->state.data_len = 0;
fuzz->state.data_pos = 0;

/* Set up the state of the server sockets. */
for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) {
Expand Down Expand Up @@ -275,6 +287,12 @@ void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz)
fuzz->easy = NULL;
}

if(fuzz->scenario_state_destructor != NULL && fuzz->scenario_state != NULL) {
fuzz->scenario_state_destructor(fuzz->scenario_state);
fuzz->scenario_state = NULL;
fuzz->scenario_state_destructor = NULL;
}

/* When you have passed the struct curl_httppost pointer to curl_easy_setopt
* (using the CURLOPT_HTTPPOST option), you must not free the list until after
* you have called curl_easy_cleanup for the curl handle.
Expand All @@ -283,6 +301,7 @@ void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz)
curl_formfree(fuzz->httppost);
fuzz->httppost = NULL;
}
fuzz->last_post_part = NULL;

// free after httppost and last_post_part.
if (fuzz->post_body != NULL) {
Expand Down Expand Up @@ -575,7 +594,7 @@ int fuzz_set_allowed_protocols(FUZZ_DATA *fuzz)
allowed_protocols = "http,ws,wss";
FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_CONNECT_ONLY, 2L));
#endif

FV_PRINTF(fuzz, "allowed_protocols=%s\n", allowed_protocols);
FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_PROTOCOLS_STR, allowed_protocols));

EXIT_LABEL:
Expand Down
Loading
Loading