mirror of
https://git.wownero.com/wownero/wownero.git
synced 2024-08-15 01:03:23 +00:00
Merge pull request #2905
bd1f6029
http_client: rewrite header parsing manually for speed (moneromooo-monero)ec724eb6
tests: add levin fuzz test (moneromooo-monero)f1bdc9a4
tests: add http client fuzz test (moneromooo-monero)0272df9e
add parse_url fuzz test (moneromooo-monero)261b0dd0
tests: add base58 fuzz test (moneromooo-monero)fd052087
fuzz_testing: allow automatically resuming an interrupted job (moneromooo-monero)c80bb0eb
tests: don't init stuff we don't need in fuzz tests - faster (moneromooo-monero)53b83a83
tests: better load-from-binary fuzz test data file (moneromooo-monero)1a379ef6
fuzz_testing: build with ASAN (assumed to be available) (moneromooo-monero)4cd4a431
fuzz_testing: create out directory if needed, and fix filename passing (moneromooo-monero)c27d9092
Makefile: build fuzz tests statically, starts faster (moneromooo-monero)95aa0bf7
add load_from_binary/load_from_json fuzzers (moneromooo-monero)
This commit is contained in:
commit
9d1c4408ad
20 changed files with 967 additions and 116 deletions
|
@ -238,6 +238,16 @@ if(STATIC)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZMQ_STATIC")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZMQ_STATIC")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(SANITIZE)
|
||||||
|
if (MSVC)
|
||||||
|
message(FATAL_ERROR "Cannot sanitize with MSVC")
|
||||||
|
else()
|
||||||
|
message(STATUS "Using ASAN")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Set default blockchain storage location:
|
# Set default blockchain storage location:
|
||||||
# memory was the default in Cryptonote before Monero implimented LMDB, it still works but is unneccessary.
|
# memory was the default in Cryptonote before Monero implimented LMDB, it still works but is unneccessary.
|
||||||
# set(DATABASE memory)
|
# set(DATABASE memory)
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -114,7 +114,7 @@ release-static-win32:
|
||||||
|
|
||||||
fuzz:
|
fuzz:
|
||||||
mkdir -p build/fuzz
|
mkdir -p build/fuzz
|
||||||
cd build/fuzz && cmake -D BUILD_TESTS=ON -D USE_LTO=OFF -D CMAKE_C_COMPILER=afl-gcc -D CMAKE_CXX_COMPILER=afl-g++ -D ARCH="x86-64" -D CMAKE_BUILD_TYPE=fuzz -D BUILD_TAG="linux-x64" ../.. && $(MAKE)
|
cd build/fuzz && cmake -D STATIC=ON -D SANITIZE=ON -D BUILD_TESTS=ON -D USE_LTO=OFF -D CMAKE_C_COMPILER=afl-gcc -D CMAKE_CXX_COMPILER=afl-g++ -D ARCH="x86-64" -D CMAKE_BUILD_TYPE=fuzz -D BUILD_TAG="linux-x64" ../.. && $(MAKE)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "WARNING: Back-up your wallet if it exists within ./build!" ; \
|
@echo "WARNING: Back-up your wallet if it exists within ./build!" ; \
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <ctype.h>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
@ -236,7 +237,8 @@ namespace net_utils
|
||||||
namespace http
|
namespace http
|
||||||
{
|
{
|
||||||
|
|
||||||
class http_simple_client: public i_target_handler
|
template<typename net_client_type>
|
||||||
|
class http_simple_client_template: public i_target_handler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
enum reciev_machine_state
|
enum reciev_machine_state
|
||||||
|
@ -259,7 +261,7 @@ namespace net_utils
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
blocked_mode_client m_net_client;
|
net_client_type m_net_client;
|
||||||
std::string m_host_buff;
|
std::string m_host_buff;
|
||||||
std::string m_port;
|
std::string m_port;
|
||||||
http_client_auth m_auth;
|
http_client_auth m_auth;
|
||||||
|
@ -276,7 +278,7 @@ namespace net_utils
|
||||||
bool m_ssl;
|
bool m_ssl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit http_simple_client()
|
explicit http_simple_client_template()
|
||||||
: i_target_handler()
|
: i_target_handler()
|
||||||
, m_net_client()
|
, m_net_client()
|
||||||
, m_host_buff()
|
, m_host_buff()
|
||||||
|
@ -428,6 +430,15 @@ namespace net_utils
|
||||||
CRITICAL_REGION_LOCAL(m_lock);
|
CRITICAL_REGION_LOCAL(m_lock);
|
||||||
return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params);
|
return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params);
|
||||||
}
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
bool test(const std::string &s, std::chrono::milliseconds timeout) // TEST FUNC ONLY
|
||||||
|
{
|
||||||
|
CRITICAL_REGION_LOCAL(m_lock);
|
||||||
|
m_net_client.set_test_data(s);
|
||||||
|
m_state = reciev_machine_state_header;
|
||||||
|
return handle_reciev(timeout);
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
inline bool handle_reciev(std::chrono::milliseconds timeout)
|
inline bool handle_reciev(std::chrono::milliseconds timeout)
|
||||||
|
@ -742,87 +753,107 @@ namespace net_utils
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
inline
|
inline bool parse_header(http_header_info& body_info, const std::string& m_cache_to_process)
|
||||||
bool parse_header(http_header_info& body_info, const std::string& m_cache_to_process)
|
|
||||||
{
|
{
|
||||||
MTRACE("http_stream_filter::parse_cached_header(*)");
|
MTRACE("http_stream_filter::parse_cached_header(*)");
|
||||||
|
|
||||||
STATIC_REGEXP_EXPR_1(rexp_mach_field,
|
const char *ptr = m_cache_to_process.c_str();
|
||||||
"\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)|(Origin)"
|
while (ptr[0] != '\r' || ptr[1] != '\n')
|
||||||
// 12 3 4 5 6 7 8 9 10 11
|
|
||||||
"|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
|
|
||||||
//12 13 14 15
|
|
||||||
boost::regex::icase | boost::regex::normal);
|
|
||||||
|
|
||||||
boost::smatch result;
|
|
||||||
std::string::const_iterator it_current_bound = m_cache_to_process.begin();
|
|
||||||
std::string::const_iterator it_end_bound = m_cache_to_process.end();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//lookup all fields and fill well-known fields
|
|
||||||
while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched)
|
|
||||||
{
|
{
|
||||||
const size_t field_val = 14;
|
// optional \n
|
||||||
//const size_t field_etc_name = 11;
|
if (*ptr == '\n')
|
||||||
|
++ptr;
|
||||||
|
// an identifier composed of letters or -
|
||||||
|
const char *key_pos = ptr;
|
||||||
|
while (isalnum(*ptr) || *ptr == '_' || *ptr == '-')
|
||||||
|
++ptr;
|
||||||
|
const char *key_end = ptr;
|
||||||
|
// optional space (not in RFC, but in previous code)
|
||||||
|
if (*ptr == ' ')
|
||||||
|
++ptr;
|
||||||
|
CHECK_AND_ASSERT_MES(*ptr == ':', true, "http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process);
|
||||||
|
++ptr;
|
||||||
|
// optional whitespace, but not newlines - line folding is obsolete, let's ignore it
|
||||||
|
while (isblank(*ptr))
|
||||||
|
++ptr;
|
||||||
|
const char *value_pos = ptr;
|
||||||
|
while (*ptr != '\r' && *ptr != '\n')
|
||||||
|
++ptr;
|
||||||
|
const char *value_end = ptr;
|
||||||
|
// optional trailing whitespace
|
||||||
|
while (value_end > value_pos && isblank(*(value_end-1)))
|
||||||
|
--value_end;
|
||||||
|
if (*ptr == '\r')
|
||||||
|
++ptr;
|
||||||
|
CHECK_AND_ASSERT_MES(*ptr == '\n', true, "http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process);
|
||||||
|
++ptr;
|
||||||
|
|
||||||
int i = 2; //start position = 2
|
const std::string key = std::string(key_pos, key_end - key_pos);
|
||||||
if(result[i++].matched)//"Connection"
|
const std::string value = std::string(value_pos, value_end - value_pos);
|
||||||
body_info.m_connection = result[field_val];
|
if (!key.empty())
|
||||||
else if(result[i++].matched)//"Referrer"
|
{
|
||||||
body_info.m_referer = result[field_val];
|
if (!string_tools::compare_no_case(key, "Connection"))
|
||||||
else if(result[i++].matched)//"Content-Length"
|
body_info.m_connection = value;
|
||||||
body_info.m_content_length = result[field_val];
|
else if(!string_tools::compare_no_case(key, "Referrer"))
|
||||||
else if(result[i++].matched)//"Content-Type"
|
body_info.m_referer = value;
|
||||||
body_info.m_content_type = result[field_val];
|
else if(!string_tools::compare_no_case(key, "Content-Length"))
|
||||||
else if(result[i++].matched)//"Transfer-Encoding"
|
body_info.m_content_length = value;
|
||||||
body_info.m_transfer_encoding = result[field_val];
|
else if(!string_tools::compare_no_case(key, "Content-Type"))
|
||||||
else if(result[i++].matched)//"Content-Encoding"
|
body_info.m_content_type = value;
|
||||||
body_info.m_content_encoding = result[field_val];
|
else if(!string_tools::compare_no_case(key, "Transfer-Encoding"))
|
||||||
else if(result[i++].matched)//"Host"
|
body_info.m_transfer_encoding = value;
|
||||||
{ body_info.m_host = result[field_val];
|
else if(!string_tools::compare_no_case(key, "Content-Encoding"))
|
||||||
string_tools::trim(body_info.m_host);
|
body_info.m_content_encoding = value;
|
||||||
}
|
else if(!string_tools::compare_no_case(key, "Host"))
|
||||||
else if(result[i++].matched)//"Cookie"
|
body_info.m_host = value;
|
||||||
body_info.m_cookie = result[field_val];
|
else if(!string_tools::compare_no_case(key, "Cookie"))
|
||||||
else if(result[i++].matched)//"User-Agent"
|
body_info.m_cookie = value;
|
||||||
body_info.m_user_agent = result[field_val];
|
else if(!string_tools::compare_no_case(key, "User-Agent"))
|
||||||
else if(result[i++].matched)//"Origin"
|
body_info.m_user_agent = value;
|
||||||
body_info.m_origin = result[field_val];
|
else if(!string_tools::compare_no_case(key, "Origin"))
|
||||||
else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
|
body_info.m_origin = value;
|
||||||
body_info.m_etc_fields.emplace_back(result[12], result[field_val]);
|
|
||||||
else
|
else
|
||||||
{CHECK_AND_ASSERT_MES(false, false, "http_stream_filter::parse_cached_header() not matched last entry in:"<<m_cache_to_process);}
|
body_info.m_etc_fields.emplace_back(key, value);
|
||||||
|
}
|
||||||
it_current_bound = result[(int)result.size()-1]. first;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
inline
|
//---------------------------------------------------------------------------
|
||||||
bool analize_first_response_line()
|
inline bool analize_first_response_line()
|
||||||
{
|
{
|
||||||
|
|
||||||
//First line response, look like this: "HTTP/1.1 200 OK"
|
//First line response, look like this: "HTTP/1.1 200 OK"
|
||||||
STATIC_REGEXP_EXPR_1(rexp_match_first_response_line, "^HTTP/(\\d+).(\\d+) ((\\d)\\d{2})( [^\n]*)?\r?\n", boost::regex::icase | boost::regex::normal);
|
const char *ptr = m_header_cache.c_str();
|
||||||
// 1 2 34 5
|
CHECK_AND_ASSERT_MES(!memcmp(ptr, "HTTP/", 5), false, "Invalid first response line: " + m_header_cache);
|
||||||
//size_t match_len = 0;
|
ptr += 5;
|
||||||
boost::smatch result;
|
CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache);
|
||||||
if(boost::regex_search( m_header_cache, result, rexp_match_first_response_line, boost::match_default) && result[0].matched)
|
unsigned long ul;
|
||||||
{
|
char *end;
|
||||||
CHECK_AND_ASSERT_MES(result[1].matched&&result[2].matched, false, "http_stream_filter::handle_invoke_reply_line() assert failed...");
|
ul = strtoul(ptr, &end, 10);
|
||||||
m_response_info.m_http_ver_hi = boost::lexical_cast<int>(result[1]);
|
CHECK_AND_ASSERT_MES(ul <= INT_MAX && *end =='.', false, "Invalid first response line: " + m_header_cache);
|
||||||
m_response_info.m_http_ver_lo = boost::lexical_cast<int>(result[2]);
|
m_response_info.m_http_ver_hi = ul;
|
||||||
m_response_info.m_response_code = boost::lexical_cast<int>(result[3]);
|
ptr = end + 1;
|
||||||
|
CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr);
|
||||||
|
ul = strtoul(ptr, &end, 10);
|
||||||
|
CHECK_AND_ASSERT_MES(ul <= INT_MAX && isblank(*end), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr);
|
||||||
|
m_response_info.m_http_ver_lo = ul;
|
||||||
|
ptr = end + 1;
|
||||||
|
while (isblank(*ptr))
|
||||||
|
++ptr;
|
||||||
|
CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache);
|
||||||
|
ul = strtoul(ptr, &end, 10);
|
||||||
|
CHECK_AND_ASSERT_MES(ul >= 100 && ul <= 999 && isspace(*end), false, "Invalid first response line: " + m_header_cache);
|
||||||
|
m_response_info.m_response_code = ul;
|
||||||
|
ptr = end;
|
||||||
|
// ignore the optional text, till the end
|
||||||
|
while (*ptr != '\r' && *ptr != '\n')
|
||||||
|
++ptr;
|
||||||
|
if (*ptr == '\r')
|
||||||
|
++ptr;
|
||||||
|
CHECK_AND_ASSERT_MES(*ptr == '\n', false, "Invalid first response line: " << m_header_cache);
|
||||||
|
++ptr;
|
||||||
|
|
||||||
m_header_cache.erase(to_nonsonst_iterator(m_header_cache, result[0].first), to_nonsonst_iterator(m_header_cache, result[0].second));
|
m_header_cache.erase(0, ptr - m_header_cache.c_str());
|
||||||
return true;
|
return true;
|
||||||
}else
|
|
||||||
{
|
|
||||||
LOG_ERROR("http_stream_filter::handle_invoke_reply_line(): Failed to match first response line:" << m_header_cache);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
inline
|
inline
|
||||||
bool set_reply_content_encoder()
|
bool set_reply_content_encoder()
|
||||||
|
@ -957,6 +988,7 @@ namespace net_utils
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
typedef http_simple_client_template<blocked_mode_client> http_simple_client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,20 @@ fi
|
||||||
type="$1"
|
type="$1"
|
||||||
if test -z "$type"
|
if test -z "$type"
|
||||||
then
|
then
|
||||||
echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction"
|
echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
case "$type" in
|
case "$type" in
|
||||||
block|transaction|signature|cold-outputs|cold-transaction) ;;
|
block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin) ;;
|
||||||
*) echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction"; exit 1 ;;
|
*) echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin"; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
afl-fuzz -i tests/data/fuzz/$type -m 150 -t 250 -o fuzz-out/$type build/fuzz/tests/fuzz/${type}_fuzz_tests
|
if test -d "fuzz-out/$type"
|
||||||
|
then
|
||||||
|
dir="-"
|
||||||
|
else
|
||||||
|
dir="tests/data/fuzz/$type"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p fuzz-out
|
||||||
|
afl-fuzz -i "$dir" -m none -t 250 -o fuzz-out/$type build/fuzz/tests/fuzz/${type}_fuzz_tests @@
|
||||||
|
|
0
tests/data/fuzz/base58/ENC1
Normal file
0
tests/data/fuzz/base58/ENC1
Normal file
1
tests/data/fuzz/base58/ENC2
Normal file
1
tests/data/fuzz/base58/ENC2
Normal file
|
@ -0,0 +1 @@
|
||||||
|
9zZBkWRgMNPEnVofRFqWK9MKBwgXNyKELBJSttxb1t2UhDM114URntt5iYcXzXusoHZygfSojsbviXZhnP9pJ4p2SDcv81L
|
8
tests/data/fuzz/http-client/RESP1
Normal file
8
tests/data/fuzz/http-client/RESP1
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
HTTP/1.1 200 Ok
|
||||||
|
Server: Epee-based
|
||||||
|
Content-Length: 5
|
||||||
|
Content-Type: text/plain
|
||||||
|
Last-Modified: Mon, 11 Dec 2017 09:03:03 GMT
|
||||||
|
Accept-Ranges: bytes
|
||||||
|
|
||||||
|
foo
|
BIN
tests/data/fuzz/levin/LEVIN1
Normal file
BIN
tests/data/fuzz/levin/LEVIN1
Normal file
Binary file not shown.
BIN
tests/data/fuzz/load-from-binary/BINARY1
Normal file
BIN
tests/data/fuzz/load-from-binary/BINARY1
Normal file
Binary file not shown.
1
tests/data/fuzz/load-from-json/JSON1
Normal file
1
tests/data/fuzz/load-from-json/JSON1
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
1
tests/data/fuzz/parse-url/URL1
Normal file
1
tests/data/fuzz/parse-url/URL1
Normal file
|
@ -0,0 +1 @@
|
||||||
|
127.0.0.1
|
1
tests/data/fuzz/parse-url/URL2
Normal file
1
tests/data/fuzz/parse-url/URL2
Normal file
|
@ -0,0 +1 @@
|
||||||
|
iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash=
|
|
@ -89,3 +89,80 @@ set_property(TARGET cold-transaction_fuzz_tests
|
||||||
PROPERTY
|
PROPERTY
|
||||||
FOLDER "tests")
|
FOLDER "tests")
|
||||||
|
|
||||||
|
add_executable(load-from-binary_fuzz_tests load_from_binary.cpp fuzzer.cpp)
|
||||||
|
target_link_libraries(load-from-binary_fuzz_tests
|
||||||
|
PRIVATE
|
||||||
|
common
|
||||||
|
epee
|
||||||
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${EXTRA_LIBRARIES})
|
||||||
|
set_property(TARGET load-from-binary_fuzz_tests
|
||||||
|
PROPERTY
|
||||||
|
FOLDER "tests")
|
||||||
|
|
||||||
|
add_executable(load-from-json_fuzz_tests load_from_json.cpp fuzzer.cpp)
|
||||||
|
target_link_libraries(load-from-json_fuzz_tests
|
||||||
|
PRIVATE
|
||||||
|
common
|
||||||
|
epee
|
||||||
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${EXTRA_LIBRARIES})
|
||||||
|
set_property(TARGET load-from-json_fuzz_tests
|
||||||
|
PROPERTY
|
||||||
|
FOLDER "tests")
|
||||||
|
|
||||||
|
add_executable(base58_fuzz_tests base58.cpp fuzzer.cpp)
|
||||||
|
target_link_libraries(base58_fuzz_tests
|
||||||
|
PRIVATE
|
||||||
|
common
|
||||||
|
epee
|
||||||
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${EXTRA_LIBRARIES})
|
||||||
|
set_property(TARGET base58_fuzz_tests
|
||||||
|
PROPERTY
|
||||||
|
FOLDER "tests")
|
||||||
|
|
||||||
|
add_executable(parse-url_fuzz_tests parse_url.cpp fuzzer.cpp)
|
||||||
|
target_link_libraries(parse-url_fuzz_tests
|
||||||
|
PRIVATE
|
||||||
|
epee
|
||||||
|
${Boost_REGEX_LIBRARY}
|
||||||
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${Boost_SYSTEM_LIBRARY}
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${EXTRA_LIBRARIES})
|
||||||
|
set_property(TARGET parse-url_fuzz_tests
|
||||||
|
PROPERTY
|
||||||
|
FOLDER "tests")
|
||||||
|
|
||||||
|
add_executable(http-client_fuzz_tests http-client.cpp fuzzer.cpp)
|
||||||
|
target_link_libraries(http-client_fuzz_tests
|
||||||
|
PRIVATE
|
||||||
|
epee
|
||||||
|
${Boost_THREAD_LIBRARY}
|
||||||
|
${Boost_REGEX_LIBRARY}
|
||||||
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${Boost_SYSTEM_LIBRARY}
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${EXTRA_LIBRARIES})
|
||||||
|
set_property(TARGET http-client_fuzz_tests
|
||||||
|
PROPERTY
|
||||||
|
FOLDER "tests")
|
||||||
|
|
||||||
|
add_executable(levin_fuzz_tests levin.cpp fuzzer.cpp)
|
||||||
|
target_link_libraries(levin_fuzz_tests
|
||||||
|
PRIVATE
|
||||||
|
common
|
||||||
|
epee
|
||||||
|
${Boost_THREAD_LIBRARY}
|
||||||
|
${Boost_REGEX_LIBRARY}
|
||||||
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${EXTRA_LIBRARIES})
|
||||||
|
set_property(TARGET levin_fuzz_tests
|
||||||
|
PROPERTY
|
||||||
|
FOLDER "tests")
|
||||||
|
|
||||||
|
|
74
tests/fuzz/base58.cpp
Normal file
74
tests/fuzz/base58.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright (c) 2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "include_base_utils.h"
|
||||||
|
#include "file_io_utils.h"
|
||||||
|
#include "common/base58.h"
|
||||||
|
#include "fuzzer.h"
|
||||||
|
|
||||||
|
class Base58Fuzzer: public Fuzzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Base58Fuzzer() {}
|
||||||
|
virtual int init();
|
||||||
|
virtual int run(const std::string &filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
int Base58Fuzzer::init()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Base58Fuzzer::run(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
if (!epee::file_io_utils::load_file_to_string(filename, s))
|
||||||
|
{
|
||||||
|
std::cout << "Error: failed to load file " << filename << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::string data;
|
||||||
|
tools::base58::decode(s, data);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to load from binary: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
Base58Fuzzer fuzzer;
|
||||||
|
return run_fuzzer(argc, argv, fuzzer);
|
||||||
|
}
|
||||||
|
|
|
@ -44,41 +44,11 @@ static int __AFL_LOOP(int)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace epee;
|
|
||||||
using namespace boost::program_options;
|
|
||||||
|
|
||||||
int run_fuzzer(int argc, const char **argv, Fuzzer &fuzzer)
|
int run_fuzzer(int argc, const char **argv, Fuzzer &fuzzer)
|
||||||
{
|
{
|
||||||
TRY_ENTRY();
|
|
||||||
tools::on_startup();
|
|
||||||
string_tools::set_module_name_and_folder(argv[0]);
|
|
||||||
|
|
||||||
//set up logging options
|
|
||||||
mlog_configure(mlog_get_default_log_path("fuzztests.log"), true);
|
|
||||||
mlog_set_log("*:FATAL,logging:none");
|
|
||||||
|
|
||||||
options_description desc_options("Allowed options");
|
|
||||||
command_line::add_arg(desc_options, command_line::arg_help);
|
|
||||||
|
|
||||||
variables_map vm;
|
|
||||||
bool r = command_line::handle_error_helper(desc_options, [&]()
|
|
||||||
{
|
|
||||||
store(parse_command_line(argc, argv, desc_options), vm);
|
|
||||||
notify(vm);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
if (!r)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (command_line::get_arg(vm, command_line::arg_help))
|
|
||||||
{
|
|
||||||
std::cout << desc_options << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
std::cout << desc_options << std::endl;
|
std::cout << "usage: " << argv[0] << " " << "<filename>" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +64,5 @@ int run_fuzzer(int argc, const char **argv, Fuzzer &fuzzer)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CATCH_ENTRY_L0("fuzzer_main", 1);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
98
tests/fuzz/http-client.cpp
Normal file
98
tests/fuzz/http-client.cpp
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
// Copyright (c) 2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "include_base_utils.h"
|
||||||
|
#include "file_io_utils.h"
|
||||||
|
#include "net/http_client.h"
|
||||||
|
#include "fuzzer.h"
|
||||||
|
|
||||||
|
class dummy_client
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool connect(const std::string& addr, int port, std::chrono::milliseconds timeout, bool ssl = false, const std::string& bind_ip = "0.0.0.0") { return true; }
|
||||||
|
bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout, bool ssl = false, const std::string& bind_ip = "0.0.0.0") { return true; }
|
||||||
|
bool disconnect() { return true; }
|
||||||
|
bool send(const std::string& buff, std::chrono::milliseconds timeout) { return true; }
|
||||||
|
bool send(const void* data, size_t sz) { return true; }
|
||||||
|
bool is_connected() { return true; }
|
||||||
|
bool recv(std::string& buff, std::chrono::milliseconds timeout)
|
||||||
|
{
|
||||||
|
buff = data;
|
||||||
|
data.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_test_data(const std::string &s) { data = s; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HTTPClientFuzzer: public Fuzzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HTTPClientFuzzer() {}
|
||||||
|
virtual int init();
|
||||||
|
virtual int run(const std::string &filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
epee::net_utils::http::http_simple_client_template<dummy_client> client;
|
||||||
|
};
|
||||||
|
|
||||||
|
int HTTPClientFuzzer::init()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HTTPClientFuzzer::run(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
if (!epee::file_io_utils::load_file_to_string(filename, s))
|
||||||
|
{
|
||||||
|
std::cout << "Error: failed to load file " << filename << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.test(s, std::chrono::milliseconds(1000));
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to test http client: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
HTTPClientFuzzer fuzzer;
|
||||||
|
return run_fuzzer(argc, argv, fuzzer);
|
||||||
|
}
|
||||||
|
|
345
tests/fuzz/levin.cpp
Normal file
345
tests/fuzz/levin.cpp
Normal file
|
@ -0,0 +1,345 @@
|
||||||
|
// Copyright (c) 2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "include_base_utils.h"
|
||||||
|
#include "file_io_utils.h"
|
||||||
|
#include "net/net_utils_base.h"
|
||||||
|
#include "net/abstract_tcp_server2.h"
|
||||||
|
#include "storages/levin_abstract_invoke2.h"
|
||||||
|
#include "net/levin_protocol_handler_async.h"
|
||||||
|
#include "fuzzer.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class call_counter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
call_counter() : m_counter(0) { }
|
||||||
|
|
||||||
|
// memory_order_relaxed is enough for call counter
|
||||||
|
void inc() volatile { m_counter.fetch_add(1, std::memory_order_relaxed); }
|
||||||
|
size_t get() volatile const { return m_counter.load(std::memory_order_relaxed); }
|
||||||
|
void reset() volatile { m_counter.store(0, std::memory_order_relaxed); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::atomic<size_t> m_counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_levin_connection_context : public epee::net_utils::connection_context_base
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef epee::levin::async_protocol_handler_config<test_levin_connection_context> test_levin_protocol_handler_config;
|
||||||
|
typedef epee::levin::async_protocol_handler<test_levin_connection_context> test_levin_protocol_handler;
|
||||||
|
|
||||||
|
struct test_levin_commands_handler : public epee::levin::levin_commands_handler<test_levin_connection_context>
|
||||||
|
{
|
||||||
|
test_levin_commands_handler()
|
||||||
|
: m_return_code(LEVIN_OK)
|
||||||
|
, m_last_command(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int invoke(int command, const std::string& in_buff, std::string& buff_out, test_levin_connection_context& context)
|
||||||
|
{
|
||||||
|
m_invoke_counter.inc();
|
||||||
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
|
m_last_command = command;
|
||||||
|
m_last_in_buf = in_buff;
|
||||||
|
buff_out = m_invoke_out_buf;
|
||||||
|
return m_return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int notify(int command, const std::string& in_buff, test_levin_connection_context& context)
|
||||||
|
{
|
||||||
|
m_notify_counter.inc();
|
||||||
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
|
m_last_command = command;
|
||||||
|
m_last_in_buf = in_buff;
|
||||||
|
return m_return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void callback(test_levin_connection_context& context)
|
||||||
|
{
|
||||||
|
m_callback_counter.inc();
|
||||||
|
//std::cout << "test_levin_commands_handler::callback()" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void on_connection_new(test_levin_connection_context& context)
|
||||||
|
{
|
||||||
|
m_new_connection_counter.inc();
|
||||||
|
//std::cout << "test_levin_commands_handler::on_connection_new()" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void on_connection_close(test_levin_connection_context& context)
|
||||||
|
{
|
||||||
|
m_close_connection_counter.inc();
|
||||||
|
//std::cout << "test_levin_commands_handler::on_connection_close()" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t invoke_counter() const { return m_invoke_counter.get(); }
|
||||||
|
size_t notify_counter() const { return m_notify_counter.get(); }
|
||||||
|
size_t callback_counter() const { return m_callback_counter.get(); }
|
||||||
|
size_t new_connection_counter() const { return m_new_connection_counter.get(); }
|
||||||
|
size_t close_connection_counter() const { return m_close_connection_counter.get(); }
|
||||||
|
|
||||||
|
int return_code() const { return m_return_code; }
|
||||||
|
void return_code(int v) { m_return_code = v; }
|
||||||
|
|
||||||
|
const std::string& invoke_out_buf() const { return m_invoke_out_buf; }
|
||||||
|
void invoke_out_buf(const std::string& v) { m_invoke_out_buf = v; }
|
||||||
|
|
||||||
|
int last_command() const { return m_last_command; }
|
||||||
|
const std::string& last_in_buf() const { return m_last_in_buf; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
call_counter m_invoke_counter;
|
||||||
|
call_counter m_notify_counter;
|
||||||
|
call_counter m_callback_counter;
|
||||||
|
call_counter m_new_connection_counter;
|
||||||
|
call_counter m_close_connection_counter;
|
||||||
|
|
||||||
|
boost::mutex m_mutex;
|
||||||
|
|
||||||
|
int m_return_code;
|
||||||
|
std::string m_invoke_out_buf;
|
||||||
|
|
||||||
|
int m_last_command;
|
||||||
|
std::string m_last_in_buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
class test_connection : public epee::net_utils::i_service_endpoint
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
test_connection(boost::asio::io_service& io_service, test_levin_protocol_handler_config& protocol_config)
|
||||||
|
: m_io_service(io_service)
|
||||||
|
, m_protocol_handler(this, protocol_config, m_context)
|
||||||
|
, m_send_return(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
m_protocol_handler.after_init_connection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement epee::net_utils::i_service_endpoint interface
|
||||||
|
virtual bool do_send(const void* ptr, size_t cb)
|
||||||
|
{
|
||||||
|
m_send_counter.inc();
|
||||||
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
|
m_last_send_data.append(reinterpret_cast<const char*>(ptr), cb);
|
||||||
|
return m_send_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool close() { return true; }
|
||||||
|
virtual bool call_run_once_service_io() { return true; }
|
||||||
|
virtual bool request_callback() { return true; }
|
||||||
|
virtual boost::asio::io_service& get_io_service() { return m_io_service; }
|
||||||
|
virtual bool add_ref() { return true; }
|
||||||
|
virtual bool release() { return true; }
|
||||||
|
|
||||||
|
size_t send_counter() const { return m_send_counter.get(); }
|
||||||
|
|
||||||
|
const std::string& last_send_data() const { return m_last_send_data; }
|
||||||
|
void reset_last_send_data() { boost::unique_lock<boost::mutex> lock(m_mutex); m_last_send_data.clear(); }
|
||||||
|
|
||||||
|
bool send_return() const { return m_send_return; }
|
||||||
|
void send_return(bool v) { m_send_return = v; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
test_levin_connection_context m_context;
|
||||||
|
test_levin_protocol_handler m_protocol_handler;
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::asio::io_service& m_io_service;
|
||||||
|
|
||||||
|
call_counter m_send_counter;
|
||||||
|
boost::mutex m_mutex;
|
||||||
|
|
||||||
|
std::string m_last_send_data;
|
||||||
|
|
||||||
|
bool m_send_return;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
class async_protocol_handler_test : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static uint64_t invoke_timeout = 5 * 1000;
|
||||||
|
const static size_t max_packet_size = 10 * 1024 * 1024;
|
||||||
|
|
||||||
|
typedef std::unique_ptr<test_connection> test_connection_ptr;
|
||||||
|
|
||||||
|
async_protocol_handler_test():
|
||||||
|
m_pcommands_handler(new test_levin_commands_handler()),
|
||||||
|
m_commands_handler(*m_pcommands_handler)
|
||||||
|
{
|
||||||
|
m_handler_config.set_handler(m_pcommands_handler, [](epee::levin::levin_commands_handler<test_levin_connection_context> *handler) { delete handler; });
|
||||||
|
m_handler_config.m_invoke_timeout = invoke_timeout;
|
||||||
|
m_handler_config.m_max_packet_size = max_packet_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetUp()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
test_connection_ptr create_connection(bool start = true)
|
||||||
|
{
|
||||||
|
test_connection_ptr conn(new test_connection(m_io_service, m_handler_config));
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
conn->start();
|
||||||
|
}
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
boost::asio::io_service m_io_service;
|
||||||
|
test_levin_protocol_handler_config m_handler_config;
|
||||||
|
test_levin_commands_handler *m_pcommands_handler, &m_commands_handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
class positive_test_connection_to_levin_protocol_handler_calls : public async_protocol_handler_test
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
class test_levin_protocol_handler__hanle_recv_with_invalid_data : public async_protocol_handler_test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const int expected_command = 5615871;
|
||||||
|
static const int expected_return_code = 782546;
|
||||||
|
|
||||||
|
test_levin_protocol_handler__hanle_recv_with_invalid_data()
|
||||||
|
: m_expected_invoke_out_buf(512, 'y')
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetUp()
|
||||||
|
{
|
||||||
|
async_protocol_handler_test::SetUp();
|
||||||
|
|
||||||
|
m_conn = create_connection();
|
||||||
|
|
||||||
|
m_in_data.assign(256, 't');
|
||||||
|
|
||||||
|
m_req_head.m_signature = LEVIN_SIGNATURE;
|
||||||
|
m_req_head.m_cb = m_in_data.size();
|
||||||
|
m_req_head.m_have_to_return_data = true;
|
||||||
|
m_req_head.m_command = expected_command;
|
||||||
|
m_req_head.m_return_code = LEVIN_OK;
|
||||||
|
m_req_head.m_flags = LEVIN_PACKET_REQUEST;
|
||||||
|
m_req_head.m_protocol_version = LEVIN_PROTOCOL_VER_1;
|
||||||
|
|
||||||
|
m_commands_handler.return_code(expected_return_code);
|
||||||
|
m_commands_handler.invoke_out_buf(m_expected_invoke_out_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void prepare_buf()
|
||||||
|
{
|
||||||
|
m_buf.assign(reinterpret_cast<const char*>(&m_req_head), sizeof(m_req_head));
|
||||||
|
m_buf += m_in_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
test_connection_ptr m_conn;
|
||||||
|
epee::levin::bucket_head2 m_req_head;
|
||||||
|
std::string m_in_data;
|
||||||
|
std::string m_buf;
|
||||||
|
std::string m_expected_invoke_out_buf;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
class LevinFuzzer: public Fuzzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LevinFuzzer() {} //: handler(endpoint, config, context) {}
|
||||||
|
virtual int init();
|
||||||
|
virtual int run(const std::string &filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//epee::net_utils::connection_context_base context;
|
||||||
|
//epee::levin::async_protocol_handler<> handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
int LevinFuzzer::init()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LevinFuzzer::run(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
//
|
||||||
|
epee::levin::bucket_head2 req_head;
|
||||||
|
req_head.m_signature = LEVIN_SIGNATURE;
|
||||||
|
req_head.m_cb = 0;
|
||||||
|
req_head.m_have_to_return_data = true;
|
||||||
|
req_head.m_command = 2000;
|
||||||
|
req_head.m_flags = LEVIN_PACKET_REQUEST;
|
||||||
|
req_head.m_protocol_version = LEVIN_PROTOCOL_VER_1;
|
||||||
|
FILE *f=fopen("/tmp/out.levin", "w");
|
||||||
|
fwrite(&req_head,sizeof(req_head),1, f);
|
||||||
|
fclose(f);
|
||||||
|
//
|
||||||
|
if (!epee::file_io_utils::load_file_to_string(filename, s))
|
||||||
|
{
|
||||||
|
std::cout << "Error: failed to load file " << filename << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//std::unique_ptr<test_connection> conn = new test();
|
||||||
|
boost::asio::io_service io_service;
|
||||||
|
test_levin_protocol_handler_config m_handler_config;
|
||||||
|
test_levin_commands_handler *m_pcommands_handler = new test_levin_commands_handler();
|
||||||
|
m_handler_config.set_handler(m_pcommands_handler, [](epee::levin::levin_commands_handler<test_levin_connection_context> *handler) { delete handler; });
|
||||||
|
std::unique_ptr<test_connection> conn(new test_connection(io_service, m_handler_config));
|
||||||
|
conn->start();
|
||||||
|
//m_commands_handler.invoke_out_buf(expected_out_data);
|
||||||
|
//m_commands_handler.return_code(expected_return_code);
|
||||||
|
conn->m_protocol_handler.handle_recv(s.data(), s.size());
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to test http client: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
LevinFuzzer fuzzer;
|
||||||
|
return run_fuzzer(argc, argv, fuzzer);
|
||||||
|
}
|
||||||
|
|
76
tests/fuzz/load_from_binary.cpp
Normal file
76
tests/fuzz/load_from_binary.cpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// Copyright (c) 2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "include_base_utils.h"
|
||||||
|
#include "file_io_utils.h"
|
||||||
|
#include "serialization/keyvalue_serialization.h"
|
||||||
|
#include "storages/portable_storage_template_helper.h"
|
||||||
|
#include "storages/portable_storage_base.h"
|
||||||
|
#include "fuzzer.h"
|
||||||
|
|
||||||
|
class PortableStorageFuzzer: public Fuzzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PortableStorageFuzzer() {}
|
||||||
|
virtual int init();
|
||||||
|
virtual int run(const std::string &filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
int PortableStorageFuzzer::init()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PortableStorageFuzzer::run(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
if (!epee::file_io_utils::load_file_to_string(filename, s))
|
||||||
|
{
|
||||||
|
std::cout << "Error: failed to load file " << filename << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
epee::serialization::portable_storage ps;
|
||||||
|
ps.load_from_binary(s);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to load from binary: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
PortableStorageFuzzer fuzzer;
|
||||||
|
return run_fuzzer(argc, argv, fuzzer);
|
||||||
|
}
|
||||||
|
|
76
tests/fuzz/load_from_json.cpp
Normal file
76
tests/fuzz/load_from_json.cpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// Copyright (c) 2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "include_base_utils.h"
|
||||||
|
#include "file_io_utils.h"
|
||||||
|
#include "serialization/keyvalue_serialization.h"
|
||||||
|
#include "storages/portable_storage_template_helper.h"
|
||||||
|
#include "storages/portable_storage_base.h"
|
||||||
|
#include "fuzzer.h"
|
||||||
|
|
||||||
|
class PortableStorageFuzzer: public Fuzzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PortableStorageFuzzer() {}
|
||||||
|
virtual int init();
|
||||||
|
virtual int run(const std::string &filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
int PortableStorageFuzzer::init()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PortableStorageFuzzer::run(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
if (!epee::file_io_utils::load_file_to_string(filename, s))
|
||||||
|
{
|
||||||
|
std::cout << "Error: failed to load file " << filename << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
epee::serialization::portable_storage ps;
|
||||||
|
ps.load_from_json(s);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to load from binary: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
PortableStorageFuzzer fuzzer;
|
||||||
|
return run_fuzzer(argc, argv, fuzzer);
|
||||||
|
}
|
||||||
|
|
74
tests/fuzz/parse_url.cpp
Normal file
74
tests/fuzz/parse_url.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright (c) 2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "include_base_utils.h"
|
||||||
|
#include "file_io_utils.h"
|
||||||
|
#include "net/net_parse_helpers.h"
|
||||||
|
#include "fuzzer.h"
|
||||||
|
|
||||||
|
class ParseURLFuzzer: public Fuzzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ParseURLFuzzer() {}
|
||||||
|
virtual int init();
|
||||||
|
virtual int run(const std::string &filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
int ParseURLFuzzer::init()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseURLFuzzer::run(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
if (!epee::file_io_utils::load_file_to_string(filename, s))
|
||||||
|
{
|
||||||
|
std::cout << "Error: failed to load file " << filename << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
epee::net_utils::http::url_content url;
|
||||||
|
epee::net_utils::parse_url(s, url);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to load from binary: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
ParseURLFuzzer fuzzer;
|
||||||
|
return run_fuzzer(argc, argv, fuzzer);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue