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 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 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 @@ -208,20 +210,46 @@ 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()


# Use std::atomic instead of GCC builtins on macOS PowerPC:
# For more information refer to: https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111
# This has been fixed in Boost 1.81, nevertheless we retain the setting for the sake of compatibility.
Expand Down Expand Up @@ -336,6 +364,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 @@ -390,3 +420,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()
54 changes: 54 additions & 0 deletions fuzzing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

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
)

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;
}
Loading