mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
ossfuzz: add some more handled CURL options
Add support for HEADER, COOKIE, RANGE, CUSTOMREQUEST, MAIL_RECIPIENT, MAIL_FROM and uploading data.
This commit is contained in:
parent
1ae2704d6e
commit
261da2a668
@ -50,7 +50,7 @@ LDADD = $(top_builddir)/lib/libcurl.la \
|
|||||||
include Makefile.inc
|
include Makefile.inc
|
||||||
|
|
||||||
checksrc:
|
checksrc:
|
||||||
@PERL@ $(top_srcdir)/lib/checksrc.pl $(srcdir)/*.c
|
@PERL@ $(top_srcdir)/lib/checksrc.pl $(srcdir)/*.cc
|
||||||
|
|
||||||
noinst_PROGRAMS = $(FUZZPROGS)
|
noinst_PROGRAMS = $(FUZZPROGS)
|
||||||
noinst_LIBRARIES = $(FUZZLIBS)
|
noinst_LIBRARIES = $(FUZZLIBS)
|
||||||
|
BIN
tests/fuzz/curl_fuzz_data/test10
Normal file
BIN
tests/fuzz/curl_fuzz_data/test10
Normal file
Binary file not shown.
BIN
tests/fuzz/curl_fuzz_data/test12
Normal file
BIN
tests/fuzz/curl_fuzz_data/test12
Normal file
Binary file not shown.
BIN
tests/fuzz/curl_fuzz_data/test13
Normal file
BIN
tests/fuzz/curl_fuzz_data/test13
Normal file
Binary file not shown.
BIN
tests/fuzz/curl_fuzz_data/test4
Normal file
BIN
tests/fuzz/curl_fuzz_data/test4
Normal file
Binary file not shown.
BIN
tests/fuzz/curl_fuzz_data/test5
Normal file
BIN
tests/fuzz/curl_fuzz_data/test5
Normal file
Binary file not shown.
BIN
tests/fuzz/curl_fuzz_data/test6
Normal file
BIN
tests/fuzz/curl_fuzz_data/test6
Normal file
Binary file not shown.
BIN
tests/fuzz/curl_fuzz_data/test900
Normal file
BIN
tests/fuzz/curl_fuzz_data/test900
Normal file
Binary file not shown.
@ -63,6 +63,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do the CURL stuff! */
|
/* Do the CURL stuff! */
|
||||||
|
if(fuzz.header_list != NULL) {
|
||||||
|
curl_easy_setopt(fuzz.easy, CURLOPT_HTTPHEADER, fuzz.header_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fuzz.mail_recipients_list != NULL) {
|
||||||
|
curl_easy_setopt(fuzz.easy, CURLOPT_MAIL_RCPT, fuzz.mail_recipients_list);
|
||||||
|
}
|
||||||
|
|
||||||
curl_easy_perform(fuzz.easy);
|
curl_easy_perform(fuzz.easy);
|
||||||
|
|
||||||
EXIT_LABEL:
|
EXIT_LABEL:
|
||||||
@ -122,8 +130,14 @@ int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz,
|
|||||||
CURLOPT_SOCKOPTFUNCTION,
|
CURLOPT_SOCKOPTFUNCTION,
|
||||||
fuzz_sockopt_callback));
|
fuzz_sockopt_callback));
|
||||||
|
|
||||||
/* Can enable verbose mode */
|
/* Set the standard read function callback. */
|
||||||
/* FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_VERBOSE, 1L)); */
|
FTRY(curl_easy_setopt(fuzz->easy,
|
||||||
|
CURLOPT_READFUNCTION,
|
||||||
|
fuzz_read_callback));
|
||||||
|
FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_READDATA, fuzz));
|
||||||
|
|
||||||
|
/* Can enable verbose mode by changing 0L to 1L */
|
||||||
|
FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_VERBOSE, 0L));
|
||||||
|
|
||||||
/* Set up the state parser */
|
/* Set up the state parser */
|
||||||
fuzz->state.data = data;
|
fuzz->state.data = data;
|
||||||
@ -143,6 +157,20 @@ void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz)
|
|||||||
fuzz_free((void **)&fuzz->username);
|
fuzz_free((void **)&fuzz->username);
|
||||||
fuzz_free((void **)&fuzz->password);
|
fuzz_free((void **)&fuzz->password);
|
||||||
fuzz_free((void **)&fuzz->postfields);
|
fuzz_free((void **)&fuzz->postfields);
|
||||||
|
fuzz_free((void **)&fuzz->cookie);
|
||||||
|
fuzz_free((void **)&fuzz->range);
|
||||||
|
fuzz_free((void **)&fuzz->customrequest);
|
||||||
|
fuzz_free((void **)&fuzz->mail_from);
|
||||||
|
|
||||||
|
if(fuzz->header_list != NULL) {
|
||||||
|
curl_slist_free_all(fuzz->header_list);
|
||||||
|
fuzz->header_list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fuzz->mail_recipients_list != NULL) {
|
||||||
|
curl_slist_free_all(fuzz->mail_recipients_list);
|
||||||
|
fuzz->mail_recipients_list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if(fuzz->easy != NULL) {
|
if(fuzz->easy != NULL) {
|
||||||
curl_easy_cleanup(fuzz->easy);
|
curl_easy_cleanup(fuzz->easy);
|
||||||
@ -216,6 +244,31 @@ static int fuzz_sockopt_callback(void *ptr,
|
|||||||
return CURL_SOCKOPT_ALREADY_CONNECTED;
|
return CURL_SOCKOPT_ALREADY_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function for doing data uploads.
|
||||||
|
*/
|
||||||
|
static size_t fuzz_read_callback(char *buffer,
|
||||||
|
size_t size,
|
||||||
|
size_t nitems,
|
||||||
|
void *ptr)
|
||||||
|
{
|
||||||
|
FUZZ_DATA *fuzz = (FUZZ_DATA *)ptr;
|
||||||
|
curl_off_t nread;
|
||||||
|
|
||||||
|
/* If no upload data has been specified, then return an error code. */
|
||||||
|
if(fuzz->upload1_data_len == 0) {
|
||||||
|
/* No data to upload */
|
||||||
|
return CURL_READFUNC_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the upload data. */
|
||||||
|
memcpy(buffer,
|
||||||
|
fuzz->upload1_data,
|
||||||
|
fuzz->upload1_data_len);
|
||||||
|
|
||||||
|
return fuzz->upload1_data_len;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLV access function - gets the first TLV from a data stream.
|
* TLV access function - gets the first TLV from a data stream.
|
||||||
*/
|
*/
|
||||||
@ -278,14 +331,9 @@ int fuzz_get_tlv_comn(FUZZ_DATA *fuzz,
|
|||||||
int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv)
|
int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
switch(tlv->type) {
|
switch(tlv->type) {
|
||||||
case TLV_TYPE_URL:
|
|
||||||
FCHECK(fuzz->url == NULL);
|
|
||||||
fuzz->url = fuzz_tlv_to_string(tlv);
|
|
||||||
FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_URL, fuzz->url));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TLV_TYPE_RESPONSE1:
|
case TLV_TYPE_RESPONSE1:
|
||||||
/* The pointers in the TLV will always be valid as long as the fuzz data
|
/* The pointers in the TLV will always be valid as long as the fuzz data
|
||||||
is in scope, which is the entirety of this file. */
|
is in scope, which is the entirety of this file. */
|
||||||
@ -293,24 +341,42 @@ int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv)
|
|||||||
fuzz->rsp1_data_len = tlv->length;
|
fuzz->rsp1_data_len = tlv->length;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TLV_TYPE_USERNAME:
|
case TLV_TYPE_UPLOAD1:
|
||||||
FCHECK(fuzz->username == NULL);
|
/* The pointers in the TLV will always be valid as long as the fuzz data
|
||||||
fuzz->username = fuzz_tlv_to_string(tlv);
|
is in scope, which is the entirety of this file. */
|
||||||
FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_USERNAME, fuzz->username));
|
fuzz->upload1_data = tlv->value;
|
||||||
|
fuzz->upload1_data_len = tlv->length;
|
||||||
|
|
||||||
|
curl_easy_setopt(fuzz->easy, CURLOPT_UPLOAD, 1L);
|
||||||
|
curl_easy_setopt(fuzz->easy,
|
||||||
|
CURLOPT_INFILESIZE_LARGE,
|
||||||
|
(curl_off_t)fuzz->upload1_data_len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TLV_TYPE_PASSWORD:
|
case TLV_TYPE_HEADER:
|
||||||
FCHECK(fuzz->password == NULL);
|
tmp = fuzz_tlv_to_string(tlv);
|
||||||
fuzz->password = fuzz_tlv_to_string(tlv);
|
fuzz->header_list = curl_slist_append(fuzz->header_list, tmp);
|
||||||
FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_PASSWORD, fuzz->password));
|
fuzz_free((void **)&tmp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TLV_TYPE_POSTFIELDS:
|
case TLV_TYPE_MAIL_RECIPIENT:
|
||||||
FCHECK(fuzz->postfields == NULL);
|
tmp = fuzz_tlv_to_string(tlv);
|
||||||
fuzz->postfields = fuzz_tlv_to_string(tlv);
|
fuzz->mail_recipients_list =
|
||||||
FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_POSTFIELDS, fuzz->postfields));
|
curl_slist_append(fuzz->mail_recipients_list, tmp);
|
||||||
|
fuzz_free((void **)&tmp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Define a set of singleton TLVs - they can only have their value set once
|
||||||
|
and all follow the same pattern. */
|
||||||
|
FSINGLETONTLV(TLV_TYPE_URL, url, CURLOPT_URL);
|
||||||
|
FSINGLETONTLV(TLV_TYPE_USERNAME, username, CURLOPT_USERNAME);
|
||||||
|
FSINGLETONTLV(TLV_TYPE_PASSWORD, password, CURLOPT_PASSWORD);
|
||||||
|
FSINGLETONTLV(TLV_TYPE_POSTFIELDS, postfields, CURLOPT_POSTFIELDS);
|
||||||
|
FSINGLETONTLV(TLV_TYPE_COOKIE, cookie, CURLOPT_COOKIE);
|
||||||
|
FSINGLETONTLV(TLV_TYPE_RANGE, range, CURLOPT_RANGE);
|
||||||
|
FSINGLETONTLV(TLV_TYPE_CUSTOMREQUEST, customrequest, CURLOPT_CUSTOMREQUEST);
|
||||||
|
FSINGLETONTLV(TLV_TYPE_MAIL_FROM, mail_from, CURLOPT_MAIL_FROM);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* The fuzzer generates lots of unknown TLVs, so don't do anything if
|
/* The fuzzer generates lots of unknown TLVs, so don't do anything if
|
||||||
the TLV isn't known. */
|
the TLV isn't known. */
|
||||||
|
@ -31,6 +31,13 @@
|
|||||||
#define TLV_TYPE_USERNAME 3
|
#define TLV_TYPE_USERNAME 3
|
||||||
#define TLV_TYPE_PASSWORD 4
|
#define TLV_TYPE_PASSWORD 4
|
||||||
#define TLV_TYPE_POSTFIELDS 5
|
#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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLV function return codes.
|
* TLV function return codes.
|
||||||
@ -91,19 +98,29 @@ typedef struct fuzz_data
|
|||||||
/* Parser state */
|
/* Parser state */
|
||||||
FUZZ_PARSE_STATE state;
|
FUZZ_PARSE_STATE state;
|
||||||
|
|
||||||
/* Current URL. */
|
|
||||||
char *url;
|
|
||||||
|
|
||||||
/* Response data and length */
|
/* Response data and length */
|
||||||
const uint8_t *rsp1_data;
|
const uint8_t *rsp1_data;
|
||||||
size_t rsp1_data_len;
|
size_t rsp1_data_len;
|
||||||
|
|
||||||
/* Username and password */
|
/* Upload data and length; */
|
||||||
|
const uint8_t *upload1_data;
|
||||||
|
size_t upload1_data_len;
|
||||||
|
|
||||||
|
/* Singleton string fields. */
|
||||||
|
char *url;
|
||||||
char *username;
|
char *username;
|
||||||
char *password;
|
char *password;
|
||||||
|
|
||||||
/* Postfields */
|
|
||||||
char *postfields;
|
char *postfields;
|
||||||
|
char *cookie;
|
||||||
|
char *range;
|
||||||
|
char *customrequest;
|
||||||
|
char *mail_from;
|
||||||
|
|
||||||
|
/* List of headers */
|
||||||
|
struct curl_slist *header_list;
|
||||||
|
|
||||||
|
/* List of mail recipients */
|
||||||
|
struct curl_slist *mail_recipients_list;
|
||||||
|
|
||||||
} FUZZ_DATA;
|
} FUZZ_DATA;
|
||||||
|
|
||||||
@ -121,6 +138,10 @@ static curl_socket_t fuzz_open_socket(void *ptr,
|
|||||||
static int fuzz_sockopt_callback(void *ptr,
|
static int fuzz_sockopt_callback(void *ptr,
|
||||||
curl_socket_t curlfd,
|
curl_socket_t curlfd,
|
||||||
curlsocktype purpose);
|
curlsocktype purpose);
|
||||||
|
static size_t fuzz_read_callback(char *buffer,
|
||||||
|
size_t size,
|
||||||
|
size_t nitems,
|
||||||
|
void *ptr);
|
||||||
int fuzz_get_first_tlv(FUZZ_DATA *fuzz, TLV *tlv);
|
int fuzz_get_first_tlv(FUZZ_DATA *fuzz, TLV *tlv);
|
||||||
int fuzz_get_next_tlv(FUZZ_DATA *fuzz, TLV *tlv);
|
int fuzz_get_next_tlv(FUZZ_DATA *fuzz, TLV *tlv);
|
||||||
int fuzz_get_tlv_comn(FUZZ_DATA *fuzz, TLV *tlv);
|
int fuzz_get_tlv_comn(FUZZ_DATA *fuzz, TLV *tlv);
|
||||||
@ -146,3 +167,10 @@ char *fuzz_tlv_to_string(TLV *tlv);
|
|||||||
goto EXIT_LABEL; \
|
goto EXIT_LABEL; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FSINGLETONTLV(TLVNAME, FIELDNAME, OPTNAME) \
|
||||||
|
case TLVNAME: \
|
||||||
|
FCHECK(fuzz->FIELDNAME == NULL); \
|
||||||
|
fuzz->FIELDNAME = fuzz_tlv_to_string(tlv); \
|
||||||
|
FTRY(curl_easy_setopt(fuzz->easy, OPTNAME, fuzz->FIELDNAME)); \
|
||||||
|
break
|
@ -36,6 +36,27 @@ def generate_corpus(options):
|
|||||||
enc.maybe_write_string(enc.TYPE_USERNAME, options.username)
|
enc.maybe_write_string(enc.TYPE_USERNAME, options.username)
|
||||||
enc.maybe_write_string(enc.TYPE_PASSWORD, options.password)
|
enc.maybe_write_string(enc.TYPE_PASSWORD, options.password)
|
||||||
enc.maybe_write_string(enc.TYPE_POSTFIELDS, options.postfields)
|
enc.maybe_write_string(enc.TYPE_POSTFIELDS, options.postfields)
|
||||||
|
enc.maybe_write_string(enc.TYPE_COOKIE, options.cookie)
|
||||||
|
enc.maybe_write_string(enc.TYPE_RANGE, options.range)
|
||||||
|
enc.maybe_write_string(enc.TYPE_CUSTOMREQUEST, options.customrequest)
|
||||||
|
enc.maybe_write_string(enc.TYPE_MAIL_FROM, options.mailfrom)
|
||||||
|
|
||||||
|
# Write the first upload to the file.
|
||||||
|
if options.upload1:
|
||||||
|
enc.write_bytes(enc.TYPE_UPLOAD1, options.upload1.encode("utf-8"))
|
||||||
|
elif options.upload1file:
|
||||||
|
with open(options.upload1file, "rb") as g:
|
||||||
|
enc.write_bytes(enc.TYPE_UPLOAD1, g.read())
|
||||||
|
|
||||||
|
# Write an array of headers to the file.
|
||||||
|
if options.header:
|
||||||
|
for header in options.header:
|
||||||
|
enc.write_string(enc.TYPE_HEADER, header)
|
||||||
|
|
||||||
|
# Write an array of headers to the file.
|
||||||
|
if options.mailrecipient:
|
||||||
|
for mailrecipient in options.mailrecipient:
|
||||||
|
enc.write_string(enc.TYPE_MAIL_RECIPIENT, mailrecipient)
|
||||||
|
|
||||||
return ScriptRC.SUCCESS
|
return ScriptRC.SUCCESS
|
||||||
|
|
||||||
@ -46,6 +67,13 @@ class TLVEncoder(object):
|
|||||||
TYPE_USERNAME = 3
|
TYPE_USERNAME = 3
|
||||||
TYPE_PASSWORD = 4
|
TYPE_PASSWORD = 4
|
||||||
TYPE_POSTFIELDS = 5
|
TYPE_POSTFIELDS = 5
|
||||||
|
TYPE_HEADER = 6
|
||||||
|
TYPE_COOKIE = 7
|
||||||
|
TYPE_UPLOAD1 = 8
|
||||||
|
TYPE_RANGE = 9
|
||||||
|
TYPE_CUSTOMREQUEST = 10
|
||||||
|
TYPE_MAIL_RECIPIENT = 11
|
||||||
|
TYPE_MAIL_FROM = 12
|
||||||
|
|
||||||
def __init__(self, output):
|
def __init__(self, output):
|
||||||
self.output = output
|
self.output = output
|
||||||
@ -58,7 +86,7 @@ class TLVEncoder(object):
|
|||||||
self.write_tlv(tlv_type, len(bytedata), bytedata)
|
self.write_tlv(tlv_type, len(bytedata), bytedata)
|
||||||
|
|
||||||
def maybe_write_string(self, tlv_type, wstring):
|
def maybe_write_string(self, tlv_type, wstring):
|
||||||
if wstring:
|
if wstring is not None:
|
||||||
self.write_string(tlv_type, wstring)
|
self.write_string(tlv_type, wstring)
|
||||||
|
|
||||||
def write_tlv(self, tlv_type, tlv_length, tlv_data=None):
|
def write_tlv(self, tlv_type, tlv_length, tlv_data=None):
|
||||||
@ -84,12 +112,22 @@ def get_options():
|
|||||||
parser.add_argument("--username")
|
parser.add_argument("--username")
|
||||||
parser.add_argument("--password")
|
parser.add_argument("--password")
|
||||||
parser.add_argument("--postfields")
|
parser.add_argument("--postfields")
|
||||||
|
parser.add_argument("--header", action="append")
|
||||||
|
parser.add_argument("--cookie")
|
||||||
|
parser.add_argument("--range")
|
||||||
|
parser.add_argument("--customrequest")
|
||||||
|
parser.add_argument("--mailfrom")
|
||||||
|
parser.add_argument("--mailrecipient", action="append")
|
||||||
|
|
||||||
rsp1 = parser.add_mutually_exclusive_group(required=True)
|
rsp1 = parser.add_mutually_exclusive_group(required=True)
|
||||||
rsp1.add_argument("--rsp1")
|
rsp1.add_argument("--rsp1")
|
||||||
rsp1.add_argument("--rsp1file")
|
rsp1.add_argument("--rsp1file")
|
||||||
rsp1.add_argument("--rsp1test", type=int)
|
rsp1.add_argument("--rsp1test", type=int)
|
||||||
|
|
||||||
|
upload1 = parser.add_mutually_exclusive_group()
|
||||||
|
upload1.add_argument("--upload1")
|
||||||
|
upload1.add_argument("--upload1file")
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user