Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bufq fuzzing harness #98

Merged
merged 8 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
strategy:
matrix:
fuzzer:
- curl_fuzzer_bufq
- curl_fuzzer_dict
- curl_fuzzer_file
- curl_fuzzer_ftp
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ m4/
Makefile
Makefile.in
missing
/curl_fuzzer_bufq
/curl_fuzzer_bufq_seed_corpus.zip
/curl_fuzzer_dict
/curl_fuzzer_dict_seed_corpus.zip
/curl_fuzzer_file
Expand Down
8 changes: 7 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ LIBS = -lpthread -lm
LIB_FUZZING_ENGINE ?= libstandaloneengine.a

FUZZPROGS = curl_fuzzer \
curl_fuzzer_bufq \
curl_fuzzer_dict \
curl_fuzzer_file \
curl_fuzzer_ftp \
Expand All @@ -58,7 +59,7 @@ FUZZPROGS = curl_fuzzer \

FUZZLIBS = libstandaloneengine.a

COMMON_SOURCES = curl_fuzzer.cc curl_fuzzer_tlv.cc curl_fuzzer_callback.cc
COMMON_SOURCES = curl_fuzzer.cc curl_fuzzer_tlv_main.cc curl_fuzzer_tlv_common.cc curl_fuzzer_callback.cc
COMMON_FLAGS = $(AM_CXXFLAGS) $(CODE_COVERAGE_CXXFLAGS)
COMMON_LDADD = @INSTALLDIR@/lib/libcurl.la $(LIB_FUZZING_ENGINE) $(CODE_COVERAGE_LIBS)

Expand Down Expand Up @@ -135,6 +136,11 @@ curl_fuzzer_fnmatch_SOURCES = fuzz_fnmatch.cc
curl_fuzzer_fnmatch_CXXFLAGS = $(COMMON_FLAGS)
curl_fuzzer_fnmatch_LDADD = $(COMMON_LDADD)

# BUFQ fuzzer
curl_fuzzer_bufq_SOURCES = fuzz_bufq.cc curl_fuzzer_tlv_bufq.cc curl_fuzzer_tlv_common.cc
curl_fuzzer_bufq_CXXFLAGS = $(COMMON_FLAGS) -DTLV_ENUM_BUFQ
curl_fuzzer_bufq_LDADD = $(COMMON_LDADD)

# Create the seed corpora zip files.
zip:
BUILD_ROOT=$(PWD) scripts/create_zip.sh
Expand Down
Binary file added corpora/curl_fuzzer_bufq/maxchunks_5_chunksize_10
Binary file not shown.
Binary file not shown.
20 changes: 0 additions & 20 deletions curl_fuzzer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,26 +104,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
return 0;
}

/**
* Utility function to convert 4 bytes to a u32 predictably.
*/
uint32_t to_u32(const uint8_t b[4])
{
uint32_t u;
u = (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3];
return u;
}

/**
* Utility function to convert 2 bytes to a u16 predictably.
*/
uint16_t to_u16(const uint8_t b[2])
{
uint16_t u;
u = (b[0] << 8) + b[1];
return u;
}

/**
* Initialize the local fuzz data structure.
*/
Expand Down
103 changes: 45 additions & 58 deletions curl_fuzzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,61 +23,11 @@
#include <curl/curl.h>
#include "testinput.h"

/**
* TLV types.
*/
#define TLV_TYPE_URL 1
#define TLV_TYPE_RESPONSE0 2
#define TLV_TYPE_USERNAME 3
#define TLV_TYPE_PASSWORD 4
#define TLV_TYPE_POSTFIELDS 5
#define TLV_TYPE_HEADER 6
#define TLV_TYPE_COOKIE 7
#define TLV_TYPE_UPLOAD1 8
#define TLV_TYPE_RANGE 9
#define TLV_TYPE_CUSTOMREQUEST 10
#define TLV_TYPE_MAIL_RECIPIENT 11
#define TLV_TYPE_MAIL_FROM 12
#define TLV_TYPE_MIME_PART 13
#define TLV_TYPE_MIME_PART_NAME 14
#define TLV_TYPE_MIME_PART_DATA 15
#define TLV_TYPE_HTTPAUTH 16
#define TLV_TYPE_RESPONSE1 17
#define TLV_TYPE_RESPONSE2 18
#define TLV_TYPE_RESPONSE3 19
#define TLV_TYPE_RESPONSE4 20
#define TLV_TYPE_RESPONSE5 21
#define TLV_TYPE_RESPONSE6 22
#define TLV_TYPE_RESPONSE7 23
#define TLV_TYPE_RESPONSE8 24
#define TLV_TYPE_RESPONSE9 25
#define TLV_TYPE_RESPONSE10 26
#define TLV_TYPE_OPTHEADER 27
#define TLV_TYPE_NOBODY 28
#define TLV_TYPE_FOLLOWLOCATION 29
#define TLV_TYPE_ACCEPTENCODING 30
#define TLV_TYPE_SECOND_RESPONSE0 31
#define TLV_TYPE_SECOND_RESPONSE1 32
#define TLV_TYPE_WILDCARDMATCH 33
#define TLV_TYPE_RTSP_REQUEST 34
#define TLV_TYPE_RTSP_SESSION_ID 35
#define TLV_TYPE_RTSP_STREAM_URI 36
#define TLV_TYPE_RTSP_TRANSPORT 37
#define TLV_TYPE_RTSP_CLIENT_CSEQ 38
#define TLV_TYPE_MAIL_AUTH 39
#define TLV_TYPE_HTTP_VERSION 40
#define TLV_TYPE_DOH_URL 41
#define TLV_TYPE_LOGIN_OPTIONS 42
#define TLV_TYPE_XOAUTH2_BEARER 43
#define TLV_TYPE_USERPWD 44
#define TLV_TYPE_USERAGENT 45
#define TLV_TYPE_NETRC 46
#define TLV_TYPE_SSH_HOST_PUBLIC_KEY_SHA256 47
#define TLV_TYPE_POST 48
#define TLV_TYPE_WS_OPTIONS 49
#define TLV_TYPE_CONNECT_ONLY 50
#define TLV_TYPE_HSTS 51
#define TLV_TYPE_HTTPPOSTBODY 52
#ifdef TLV_ENUM_BUFQ
cmeister2 marked this conversation as resolved.
Show resolved Hide resolved
#include "curl_fuzzer_tlv_bufq.h"
#else
#include "curl_fuzzer_tlv_main.h"
#endif

/**
* TLV function return codes.
Expand Down Expand Up @@ -199,9 +149,9 @@ typedef struct fuzz_socket_manager
} FUZZ_SOCKET_MANAGER;

/**
* Data local to a fuzzing run.
* Data local to a fuzzing run on the main fuzzer
*/
typedef struct fuzz_data
struct fuzz_data_main
{
/* CURL easy object */
CURL *easy;
Expand Down Expand Up @@ -252,7 +202,43 @@ typedef struct fuzz_data
/* Verbose mode. */
int verbose;

} FUZZ_DATA;
};

/**
* Data local to a fuzzing run on the BUFQ fuzzer
*/
struct fuzz_data_bufq
{
/* Parser state */
FUZZ_PARSE_STATE state;

/* Verbose mode. */
int verbose;

/* BUFQ max_chunks parameter */
int max_chunks;

/* BUFQ chunk_size parameter */
int chunk_size;

/* Should the run use a pool? */
int use_pool;

/* BUFQ max_spare parameter */
int max_spare;

/* Should spares be enabled? */
int no_spare;

/* How many operations to execute */
int operation_count;

/* List of operations */
struct fuzz_bufq_operation *operation_list;

/* Template buffer for writes / read checks */
unsigned char *template_buf;
};

/* Function prototypes */
uint32_t to_u32(const uint8_t b[4]);
Expand Down Expand Up @@ -286,6 +272,7 @@ void fuzz_setup_http_post(FUZZ_DATA *fuzz, TLV *tlv);
int fuzz_add_mime_part(TLV *src_tlv, curl_mimepart *part);
int fuzz_parse_mime_tlv(curl_mimepart *part, TLV *tlv);
int fuzz_handle_transfer(FUZZ_DATA *fuzz);
int fuzz_handle_bufq(FUZZ_DATA *fuzz);
int fuzz_send_next_response(FUZZ_DATA *fuzz, FUZZ_SOCKET_MANAGER *sockman);
int fuzz_select(int nfds,
fd_set *readfds,
Expand Down
141 changes: 141 additions & 0 deletions curl_fuzzer_tlv_bufq.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2017, Max Dymond, <[email protected]>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "curl_fuzzer.h"

/**
* Do different actions on the CURL handle for different received TLVs.
*/
int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv)
{
int rc;
OPERATION *tmp_op;
uint32_t tmp_op_type;
uint32_t tmp_u32;

switch(tlv->type) {
case TLV_TYPE_MAX_CHUNKS:
FCHECK(tlv->length == 4);
FCHECK(fuzz->max_chunks == 0);
tmp_u32 = to_u32(tlv->value);
FCHECK(tmp_u32 > 0 && tmp_u32 < TLV_MAX_CHUNKS_QTY);
fuzz->max_chunks = tmp_u32;
break;

case TLV_TYPE_CHUNK_SIZE:
FCHECK(tlv->length == 4);
FCHECK(fuzz->chunk_size == 0);
tmp_u32 = to_u32(tlv->value);
FCHECK(tmp_u32 > 0 && tmp_u32 < TLV_MAX_CHUNK_SIZE);
fuzz->chunk_size = tmp_u32;
break;

case TLV_TYPE_MAX_SPARE:
FCHECK(tlv->length == 4);
FCHECK(fuzz->max_spare == 0);
tmp_u32 = to_u32(tlv->value);
FCHECK(tmp_u32 > 0 && tmp_u32 < TLV_MAX_MAX_SPARE);
fuzz->max_spare = tmp_u32;
break;

case TLV_TYPE_USE_POOL:
FCHECK(tlv->length == 0);
FCHECK(fuzz->use_pool == 0);
fuzz->use_pool = 1;
break;

case TLV_TYPE_NO_SPARE:
FCHECK(tlv->length == 0);
FCHECK(fuzz->no_spare == 0);
fuzz->no_spare = 1;
break;

case TLV_TYPE_RESET:
tmp_op_type = OP_TYPE_RESET;
goto ADD_OP_UNSIZED;
cmeister2 marked this conversation as resolved.
Show resolved Hide resolved

case TLV_TYPE_PEEK:
tmp_op_type = OP_TYPE_PEEK;
goto ADD_OP_UNSIZED;

case TLV_TYPE_READ_SIZE:
tmp_op_type = OP_TYPE_READ;
goto ADD_OP;

case TLV_TYPE_PEEK_AT:
tmp_op_type = OP_TYPE_PEEK_AT;
goto ADD_OP;

case TLV_TYPE_SLURP:
tmp_op_type = OP_TYPE_SLURP;
goto ADD_OP;

case TLV_TYPE_SIPN:
tmp_op_type = OP_TYPE_SIPN;
goto ADD_OP;

case TLV_TYPE_PASS:
tmp_op_type = OP_TYPE_PASS;
goto ADD_OP;

case TLV_TYPE_SKIP_SIZE:
tmp_op_type = OP_TYPE_SKIP;
goto ADD_OP;

case TLV_TYPE_WRITE_SIZE:
tmp_op_type = OP_TYPE_WRITE;
ADD_OP:
FCHECK(tlv->length == 4);
tmp_u32 = to_u32(tlv->value);
FCHECK(tmp_u32 <= TLV_MAX_RW_SIZE);
goto ADD_OP_COMMON;
ADD_OP_UNSIZED:
FCHECK(tlv->length == 0);
ADD_OP_COMMON:
tmp_op = (OPERATION*) malloc(sizeof(*tmp_op));
if (tmp_op == NULL) {
// keep on despite allocation failure
break;
}
tmp_op->type = tmp_op_type;
tmp_op->size = tmp_u32;
tmp_op->next = fuzz->operation_list;
fuzz->operation_list = tmp_op;
fuzz->operation_count++;
break;

default:
/* The fuzzer generates lots of unknown TLVs - we don't want these in the
corpus so we reject any unknown TLVs. */
FV_PRINTF(fuzz, "Unknown TLV!\n");
rc = 127;
goto EXIT_LABEL;
break;
}

rc = 0;

EXIT_LABEL:
return rc;
}
Loading