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

Added undefined behavior sanitizer and fuzzers. #1949

Open
wants to merge 7 commits into
base: openssl
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
63 changes: 59 additions & 4 deletions build/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ option(WITH_UPNP "Include support for UPnP client" OFF)
option(WITH_GIT_VERSION "Use git commit info as version" OFF)
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
option(WITH_UNDEFSANITIZER "Build with undefined sanitizer (unix only)" OFF)
option(BUILD_FUZZING "Build fuzzers (Clang only)" OFF)
option(BUILD_TESTING "Build tests" OFF)

IF(BUILD_TESTING)
Expand Down Expand Up @@ -209,17 +211,64 @@ if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386")
add_definitions(-D__AES__)
endif()


set(_SANITIZE_FLAGS "")

if(WITH_ADDRSANITIZER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
list(APPEND _SANITIZE_FLAGS -fsanitize=address)
endif()

if(WITH_THREADSANITIZER)
if(WITH_ADDRSANITIZER)
message(FATAL_ERROR "thread sanitizer option cannot be combined with address sanitizer")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread")
list(APPEND _SANITIZE_FLAGS -fsanitize=thread)
endif()
endif()

if(WITH_UNDEFSANITIZER)
list(APPEND _SANITIZE_FLAGS -fsanitize=undefined)
list(APPEND _SANITIZE_FLAGS -fno-sanitize=vptr)
list(APPEND _SANITIZE_FLAGS -fno-sanitize=enum)
endif()

if(BUILD_FUZZING)
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
list(APPEND _SANITIZE_FLAGS -fsanitize=fuzzer-no-link)
else()
message(FATAL_ERROR "Fuzzing not supported by your compiler")
endif()
endif()

if(NOT "${_SANITIZE_FLAGS}" STREQUAL "")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer")

list(JOIN _SANITIZE_FLAGS " " _X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_X}")

# Is this really needed? Compiler (and CXX flags) used to link
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_X}")
endif()

# Check for incompatible VERIFY_ALWAYS_SUCCEEDS combinations
if(VERIFY_ALWAYS_SUCCEEDS)
if(NOT BUILD_FUZZING)
message(FATAL_ERROR "VERIFY_ALWAYS_SUCCEEDS enabled without BUILD_FUZZING")
endif()

if(BUILD_TESTING)
# Tests may be invalidated
message(FATAL_ERROR "VERIFY_ALWAYS_SUCCEEDS enabled with BUILD_TESTING")
endif()

if(WITH_LIBRARY)
# Such libraries are unsafe, except for fuzzing
message(FATAL_ERROR "VERIFY_ALWAYS_SUCCEEDS enabled with WITH_LIBRARY")
endif()

if(WITH_BINARY)
# Such binaries are unsafe
message(FATAL_ERROR "VERIFY_ALWAYS_SUCCEEDS enabled with WITH_BINARY")
endif()
endif()

Expand Down Expand Up @@ -337,6 +386,8 @@ message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}")
endif()
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS " UNDEFSANITIZER : ${WITH_UNDEFSANITIZER}")
message(STATUS " FUZZING : ${BUILD_FUZZING}")
message(STATUS "---------------------------------------")

if(WITH_BINARY)
Expand Down Expand Up @@ -391,3 +442,7 @@ endif()
if(BUILD_TESTING)
add_subdirectory(${CMAKE_SOURCE_DIR}/tests ${CMAKE_CURRENT_BINARY_DIR}/tests)
endif()

if(BUILD_FUZZING)
add_subdirectory(${CMAKE_SOURCE_DIR}/fuzzing ${CMAKE_CURRENT_BINARY_DIR}/fuzzing)
endif()
55 changes: 55 additions & 0 deletions fuzzing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

include_directories(
../libi2pd
${Boost_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
)


set(LIBS
libi2pd
${Boost_LIBRARIES}
OpenSSL::SSL
OpenSSL::Crypto
ZLIB::ZLIB
Threads::Threads
${CMAKE_REQUIRED_LIBRARIES}
)

add_library(fuzzing OBJECT
fuzzing_impl.cc
fuzzing_throttle.cc
fuzzing.h)

link_libraries(fuzzing)

set(FUZZERS
Base32ToByteStream
Base64ToByteStream
BlindedPublicKey
ByteStreamToBase32
ByteStreamToBase64
HandleI2NPMessage
IdentityEx
LeaseSet
LeaseSet2
NetDb-AddRouterInfo
NetDb-HandleDatabaseSearchReplyMsg
NetDb-HandleDatabaseStoreMsg
NetDb-HandleDatabaseLookupMsg
NetDb-HandleNTCP2RouterInfoMsg
NetDb-PostI2NPMsg
RouterContext-DecryptTunnelBuildRecord
RouterContext-ProcessDeliveryStatusMessage
RouterContext-ProcessGarlicMessage
ToBase64Standard
)

string(REPLACE "fuzzer-no-link" "fuzzer" _LINK_FLAGS "${_SANITIZE_FLAGS}")

foreach(F IN LISTS FUZZERS)
add_executable(fuzz-${F} fuzz-${F}.cc)
target_link_libraries(fuzz-${F} ${LIBS})
target_link_options(fuzz-${F} PRIVATE ${_LINK_FLAGS})
endforeach()

32 changes: 32 additions & 0 deletions fuzzing/fuzz-Base32ToByteStream.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@


#include <stdint.h>
#include <stddef.h>

#include <Base.h>

#include "fuzzing.h"


bool
fuzzing_testinput(const uint8_t * data, size_t size)
{
size_t outlen;
uint8_t * out;


if(size < 2)
return true;

outlen = (data[0] << 8) | data[1];
outlen++;

data += 2;
size -= 2;

out = new uint8_t[outlen];
i2p::data::Base32ToByteStream((const char *) data, size, out, outlen);
delete [] out;

return true;
}
32 changes: 32 additions & 0 deletions fuzzing/fuzz-Base64ToByteStream.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@


#include <stdint.h>
#include <stddef.h>

#include <Base.h>

#include "fuzzing.h"


bool
fuzzing_testinput(const uint8_t * data, size_t size)
{
size_t outlen;
uint8_t * out;


if(size < 2)
return true;

outlen = (data[0] << 8) | data[1];
outlen++;

data += 2;
size -= 2;

out = new uint8_t[outlen];
i2p::data::Base64ToByteStream((const char *) data, size, out, outlen);
delete [] out;

return true;
}
23 changes: 23 additions & 0 deletions fuzzing/fuzz-BlindedPublicKey.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@


#include <stdint.h>
#include <stddef.h>
#include <string>

#include <Blinding.h>

#include "fuzzing.h"


bool
fuzzing_testinput(const uint8_t * data, size_t size)
{
std::string str((const char *) data, size);
i2p::data::BlindedPublicKey * bpk;


bpk = new i2p::data::BlindedPublicKey(str);
delete bpk;

return true;
}
32 changes: 32 additions & 0 deletions fuzzing/fuzz-ByteStreamToBase32.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@


#include <stdint.h>
#include <stddef.h>

#include <Base.h>

#include "fuzzing.h"


bool
fuzzing_testinput(const uint8_t * data, size_t size)
{
size_t outlen;
char * out;


if(size < (2 + 1))
return true;

outlen = (data[0] << 8) | data[1];
outlen++;

data += 2;
size -= 2;

out = new char[outlen];
i2p::data::ByteStreamToBase32(data, size, out, outlen);
delete [] out;

return true;
}
32 changes: 32 additions & 0 deletions fuzzing/fuzz-ByteStreamToBase64.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@


#include <stdint.h>
#include <stddef.h>

#include <Base.h>

#include "fuzzing.h"


bool
fuzzing_testinput(const uint8_t * data, size_t size)
{
size_t outlen;
char * out;


if(size < (2 + 1))
return true;

outlen = (data[0] << 8) | data[1];
outlen++;

data += 2;
size -= 2;

out = new char[outlen];
i2p::data::ByteStreamToBase64(data, size, out, outlen);
delete [] out;

return true;
}
29 changes: 29 additions & 0 deletions fuzzing/fuzz-HandleI2NPMessage.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@


#include <stdint.h>
#include <stddef.h>

#include <I2NPProtocol.h>

#include "fuzzing.h"


bool
fuzzing_testinput(const uint8_t * data, size_t size)
{
i2p::I2NPMessageType msgType;


if(size < 1)
return true;

msgType = (i2p::I2NPMessageType) data[0];

data++;
size--;

i2p::HandleI2NPMessage(
i2p::CreateI2NPMessage(msgType, data, size));

return true;
}
21 changes: 21 additions & 0 deletions fuzzing/fuzz-IdentityEx.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@


#include <stdint.h>
#include <stddef.h>

#include <Identity.h>

#include "fuzzing.h"


bool
fuzzing_testinput(const uint8_t * data, size_t size)
{
i2p::data::IdentityEx * ident;


ident = new i2p::data::IdentityEx(data, size);
delete ident;

return true;
}
21 changes: 21 additions & 0 deletions fuzzing/fuzz-LeaseSet.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@


#include <stdint.h>
#include <stddef.h>

#include <LeaseSet.h>

#include "fuzzing.h"


bool
fuzzing_testinput(const uint8_t * data, size_t size)
{
i2p::data::LeaseSet * ls;


ls = new i2p::data::LeaseSet(data, size, false);
delete ls;

return true;
}