Buffer parser fuzzing (#2496)
* Buffer parser fuzzing * add clang-6 with libfuzzer base Dockerfile Co-authored-by: Russel Waters <vaelstrom@gmail.com>
This commit is contained in:
		
					parent
					
						
							
								a752debfc7
							
						
					
				
			
			
				commit
				
					
						d41d4c5633
					
				
			
		
					 6 changed files with 132 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -38,6 +38,7 @@ set (NANO_ROCKSDB OFF CACHE BOOL "")
 | 
			
		|||
set (NANO_POW_SERVER OFF CACHE BOOL "")
 | 
			
		||||
set (NANO_WARN_TO_ERR OFF CACHE BOOL "")
 | 
			
		||||
set (NANO_TIMED_LOCKS 0 CACHE STRING "")
 | 
			
		||||
set (NANO_FUZZER_TEST OFF CACHE BOOL "")
 | 
			
		||||
 | 
			
		||||
option (NANO_STACKTRACE_BACKTRACE "Use BOOST_STACKTRACE_USE_BACKTRACE in stacktraces, for POSIX" OFF)
 | 
			
		||||
if (NANO_STACKTRACE_BACKTRACE)
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +111,11 @@ else ()
 | 
			
		|||
		add_definitions(-DED25519_NO_INLINE_ASM)
 | 
			
		||||
	endif()
 | 
			
		||||
 | 
			
		||||
	if (NANO_FUZZER_TEST)
 | 
			
		||||
		add_compile_options (-fsanitize=fuzzer-no-link -fno-omit-frame-pointer)
 | 
			
		||||
		add_definitions (-DNANO_FUZZER_TEST)
 | 
			
		||||
	endif ()
 | 
			
		||||
 | 
			
		||||
	if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86(_64)?)$")
 | 
			
		||||
		if (NANO_SIMD_OPTIMIZATIONS OR RAIBLOCKS_SIMD_OPTIMIZATIONS OR ENABLE_AVX2)
 | 
			
		||||
			add_compile_options(-msse4)
 | 
			
		||||
| 
						 | 
				
			
			@ -175,6 +181,9 @@ else ()
 | 
			
		|||
			set (PLATFORM_LINK_FLAGS "${PLATFORM_LINK_FLAGS} -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/tsan_clang_blacklist")
 | 
			
		||||
		endif()
 | 
			
		||||
	endif()
 | 
			
		||||
	if (NANO_FUZZER_TEST)
 | 
			
		||||
		set (PLATFORM_LINK_FLAGS "${PLATFORM_LINK_FLAGS} -fsanitize=fuzzer-no-link")
 | 
			
		||||
	endif ()
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINK_FLAGS}" )
 | 
			
		||||
| 
						 | 
				
			
			@ -352,6 +361,14 @@ add_subdirectory(nano/nano_node)
 | 
			
		|||
add_subdirectory(nano/rpc)
 | 
			
		||||
add_subdirectory(nano/nano_rpc)
 | 
			
		||||
 | 
			
		||||
if (NANO_FUZZER_TEST)
 | 
			
		||||
	if (NOT WIN32)
 | 
			
		||||
		add_subdirectory (nano/fuzzer_test)
 | 
			
		||||
	else ()
 | 
			
		||||
		message (WARNING "Fuzzing is not supported on Windows")
 | 
			
		||||
	endif ()
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
if (NANO_TEST OR RAIBLOCKS_TEST)
 | 
			
		||||
	if(WIN32)
 | 
			
		||||
		if(MSVC_VERSION)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								docker/ci/Dockerfile-clang-6
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								docker/ci/Dockerfile-clang-6
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
FROM nanocurrency/nano-env:base
 | 
			
		||||
 | 
			
		||||
RUN apt-get update && apt-get install -yqq software-properties-common && \
 | 
			
		||||
    wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \
 | 
			
		||||
    apt-add-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-6.0 main" && \
 | 
			
		||||
    apt-get update -qq && apt-get install -yqq \
 | 
			
		||||
    clang-6.0 lldb-6.0 libfuzzer-6.0-dev git
 | 
			
		||||
 | 
			
		||||
ADD util/build_prep/fetch_rocksdb.sh fetch_rocksdb.sh
 | 
			
		||||
RUN ./fetch_rocksdb.sh
 | 
			
		||||
 | 
			
		||||
ENV CXX=/usr/bin/clang++
 | 
			
		||||
ENV CC=/usr/bin/clang
 | 
			
		||||
RUN ln -s /usr/bin/clang-6.0 /usr/bin/clang
 | 
			
		||||
RUN ln -s /usr/bin/clang++-6.0 /usr/bin/clang++
 | 
			
		||||
RUN update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
 | 
			
		||||
RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
 | 
			
		||||
ENV BOOST_ROOT=/tmp/boost
 | 
			
		||||
 | 
			
		||||
ADD util/build_prep/bootstrap_boost.sh bootstrap_boost.sh
 | 
			
		||||
 | 
			
		||||
RUN ./bootstrap_boost.sh -m -c -B 1.70
 | 
			
		||||
							
								
								
									
										3
									
								
								nano/fuzzer_test/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								nano/fuzzer_test/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
add_executable(fuzz_buffer fuzz_buffer.cpp)
 | 
			
		||||
target_compile_options(fuzz_buffer PUBLIC -fsanitize=fuzzer)
 | 
			
		||||
target_link_libraries(fuzz_buffer PRIVATE -fsanitize=fuzzer node)
 | 
			
		||||
							
								
								
									
										75
									
								
								nano/fuzzer_test/fuzz_buffer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								nano/fuzzer_test/fuzz_buffer.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
#include <nano/core_test/testutil.hpp>
 | 
			
		||||
#include <nano/node/common.hpp>
 | 
			
		||||
#include <nano/node/testing.hpp>
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
namespace nano
 | 
			
		||||
{
 | 
			
		||||
void force_nano_test_network ();
 | 
			
		||||
}
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
std::shared_ptr<nano::system> system0;
 | 
			
		||||
std::shared_ptr<nano::node> node0;
 | 
			
		||||
 | 
			
		||||
class fuzz_visitor : public nano::message_visitor
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual void keepalive (nano::keepalive const &) override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	virtual void publish (nano::publish const &) override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	virtual void confirm_req (nano::confirm_req const &) override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	virtual void confirm_ack (nano::confirm_ack const &) override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	virtual void bulk_pull (nano::bulk_pull const &) override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	virtual void bulk_pull_account (nano::bulk_pull_account const &) override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	virtual void bulk_push (nano::bulk_push const &) override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	virtual void frontier_req (nano::frontier_req const &) override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	virtual void node_id_handshake (nano::node_id_handshake const &) override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Fuzz live message parsing. This covers parsing and block/vote uniquing. */
 | 
			
		||||
void fuzz_message_parser (const uint8_t * Data, size_t Size)
 | 
			
		||||
{
 | 
			
		||||
	static bool initialized = false;
 | 
			
		||||
	if (!initialized)
 | 
			
		||||
	{
 | 
			
		||||
		nano::force_nano_test_network ();
 | 
			
		||||
		initialized = true;
 | 
			
		||||
		system0 = std::make_shared<nano::system> (1);
 | 
			
		||||
		node0 = system0->nodes[0];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fuzz_visitor visitor;
 | 
			
		||||
	nano::message_parser parser (node0->block_uniquer, node0->vote_uniquer, visitor, node0->work);
 | 
			
		||||
	parser.deserialize_buffer (Data, Size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Fuzzer entry point */
 | 
			
		||||
extern "C" int LLVMFuzzerTestOneInput (const uint8_t * Data, size_t Size)
 | 
			
		||||
{
 | 
			
		||||
	fuzz_message_parser (Data, Size);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1313,7 +1313,9 @@ std::shared_ptr<nano::block> nano::deserialize_block (nano::stream & stream_a, n
 | 
			
		|||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		default:
 | 
			
		||||
#ifndef NANO_FUZZER_TEST
 | 
			
		||||
			assert (false);
 | 
			
		||||
#endif
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	if (uniquer_a != nullptr)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ bool nano::work_validate (nano::block const & block_a, uint64_t * difficulty_a)
 | 
			
		|||
	return work_validate (block_a.root (), block_a.block_work (), difficulty_a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef NANO_FUZZER_TEST
 | 
			
		||||
uint64_t nano::work_value (nano::root const & root_a, uint64_t work_a)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t result;
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +33,18 @@ uint64_t nano::work_value (nano::root const & root_a, uint64_t work_a)
 | 
			
		|||
	blake2b_final (&hash, reinterpret_cast<uint8_t *> (&result), sizeof (result));
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
uint64_t nano::work_value (nano::root const & root_a, uint64_t work_a)
 | 
			
		||||
{
 | 
			
		||||
	static nano::network_constants network_constants;
 | 
			
		||||
	if (!network_constants.is_test_network ())
 | 
			
		||||
	{
 | 
			
		||||
		assert (false);
 | 
			
		||||
		std::exit (1);
 | 
			
		||||
	}
 | 
			
		||||
	return network_constants.publish_threshold + 1;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
nano::work_pool::work_pool (unsigned max_threads_a, std::chrono::nanoseconds pow_rate_limiter_a, std::function<boost::optional<uint64_t> (nano::root const &, uint64_t, std::atomic<int> &)> opencl_a) :
 | 
			
		||||
ticket (0),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue