From 261da2a6685c0185283dbf72ce543e9fd81e9bd8 Mon Sep 17 00:00:00 2001 From: Max Dymond Date: Sat, 2 Sep 2017 22:40:01 +0100 Subject: ossfuzz: add some more handled CURL options Add support for HEADER, COOKIE, RANGE, CUSTOMREQUEST, MAIL_RECIPIENT, MAIL_FROM and uploading data. --- tests/fuzz/curl_fuzzer.cc | 106 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 20 deletions(-) (limited to 'tests/fuzz/curl_fuzzer.cc') diff --git a/tests/fuzz/curl_fuzzer.cc b/tests/fuzz/curl_fuzzer.cc index 92bedf92e..bbf91c222 100644 --- a/tests/fuzz/curl_fuzzer.cc +++ b/tests/fuzz/curl_fuzzer.cc @@ -63,6 +63,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) } /* 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); EXIT_LABEL: @@ -122,8 +130,14 @@ int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz, CURLOPT_SOCKOPTFUNCTION, fuzz_sockopt_callback)); - /* Can enable verbose mode */ - /* FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_VERBOSE, 1L)); */ + /* Set the standard read function callback. */ + 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 */ 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->password); 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) { curl_easy_cleanup(fuzz->easy); @@ -216,6 +244,31 @@ static int fuzz_sockopt_callback(void *ptr, 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. */ @@ -278,14 +331,9 @@ int fuzz_get_tlv_comn(FUZZ_DATA *fuzz, int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv) { int rc; + char *tmp; 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: /* 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. */ @@ -293,24 +341,42 @@ int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv) fuzz->rsp1_data_len = tlv->length; break; - case TLV_TYPE_USERNAME: - FCHECK(fuzz->username == NULL); - fuzz->username = fuzz_tlv_to_string(tlv); - FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_USERNAME, fuzz->username)); + case TLV_TYPE_UPLOAD1: + /* 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. */ + 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; - case TLV_TYPE_PASSWORD: - FCHECK(fuzz->password == NULL); - fuzz->password = fuzz_tlv_to_string(tlv); - FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_PASSWORD, fuzz->password)); + case TLV_TYPE_HEADER: + tmp = fuzz_tlv_to_string(tlv); + fuzz->header_list = curl_slist_append(fuzz->header_list, tmp); + fuzz_free((void **)&tmp); break; - case TLV_TYPE_POSTFIELDS: - FCHECK(fuzz->postfields == NULL); - fuzz->postfields = fuzz_tlv_to_string(tlv); - FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_POSTFIELDS, fuzz->postfields)); + case TLV_TYPE_MAIL_RECIPIENT: + tmp = fuzz_tlv_to_string(tlv); + fuzz->mail_recipients_list = + curl_slist_append(fuzz->mail_recipients_list, tmp); + fuzz_free((void **)&tmp); 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: /* The fuzzer generates lots of unknown TLVs, so don't do anything if the TLV isn't known. */ -- cgit v1.2.3