mirror of https://github.com/PurpleI2P/i2pd.git
Chad Fraleigh
1 year ago
23 changed files with 813 additions and 4 deletions
@ -0,0 +1,54 @@
@@ -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() |
||||
|
@ -0,0 +1,32 @@
@@ -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; |
||||
} |
@ -0,0 +1,32 @@
@@ -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; |
||||
} |
@ -0,0 +1,23 @@
@@ -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; |
||||
} |
@ -0,0 +1,32 @@
@@ -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; |
||||
} |
@ -0,0 +1,32 @@
@@ -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; |
||||
} |
@ -0,0 +1,29 @@
@@ -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; |
||||
} |
@ -0,0 +1,21 @@
@@ -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; |
||||
} |
@ -0,0 +1,21 @@
@@ -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; |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <LeaseSet.h> |
||||
|
||||
#include "fuzzing.h" |
||||
|
||||
|
||||
bool |
||||
fuzzing_testinput(const uint8_t * data, size_t size) |
||||
{ |
||||
uint8_t storeType; |
||||
i2p::data::LeaseSet2 * ls; |
||||
|
||||
|
||||
if(size < 1) |
||||
return true; |
||||
|
||||
storeType = data[0]; |
||||
|
||||
// Same check as in NetDb::HandleDatabaseStoreMsg()
|
||||
if(storeType == i2p::data::NETDB_STORE_TYPE_LEASESET) |
||||
return true; |
||||
|
||||
data++; |
||||
size--; |
||||
|
||||
// Same check as in NetDb::HandleDatabaseStoreMsg()
|
||||
if(size > i2p::data::MAX_LS_BUFFER_SIZE) |
||||
return true; |
||||
|
||||
ls = new i2p::data::LeaseSet2(storeType, data, size, false); |
||||
delete ls; |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <NetDb.hpp> |
||||
|
||||
#include "fuzzing.h" |
||||
|
||||
|
||||
bool |
||||
fuzzing_testinput(const uint8_t * data, size_t size) |
||||
{ |
||||
i2p::data::netdb.AddRouterInfo(data, size); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <I2NPProtocol.h> |
||||
#include <NetDb.hpp> |
||||
|
||||
#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::data::netdb.HandleDatabaseLookupMsg( |
||||
i2p::CreateI2NPMessage(msgType, data, size)); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <I2NPProtocol.h> |
||||
#include <NetDb.hpp> |
||||
|
||||
#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::data::netdb.HandleDatabaseSearchReplyMsg( |
||||
i2p::CreateI2NPMessage(msgType, data, size)); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <I2NPProtocol.h> |
||||
#include <NetDb.hpp> |
||||
|
||||
#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::data::netdb.HandleDatabaseStoreMsg( |
||||
i2p::CreateI2NPMessage(msgType, data, size)); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <I2NPProtocol.h> |
||||
#include <NetDb.hpp> |
||||
|
||||
#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::data::netdb.HandleNTCP2RouterInfoMsg( |
||||
i2p::CreateI2NPMessage(msgType, data, size)); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <I2NPProtocol.h> |
||||
#include <NetDb.hpp> |
||||
|
||||
#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::data::netdb.PostI2NPMsg( |
||||
i2p::CreateI2NPMessage(msgType, data, size)); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <I2NPProtocol.h> |
||||
#include <RouterContext.h> |
||||
|
||||
#include "fuzzing.h" |
||||
|
||||
|
||||
bool |
||||
fuzzing_testinput(const uint8_t * data, size_t size) |
||||
{ |
||||
uint8_t clearText[i2p::ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; |
||||
|
||||
|
||||
if(size < i2p::TUNNEL_BUILD_RECORD_SIZE) |
||||
return true; |
||||
|
||||
i2p::context.DecryptTunnelBuildRecord(data, clearText); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <I2NPProtocol.h> |
||||
#include <RouterContext.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::context.ProcessDeliveryStatusMessage( |
||||
i2p::CreateI2NPMessage(msgType, data, size)); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <I2NPProtocol.h> |
||||
#include <RouterContext.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::context.ProcessGarlicMessage( |
||||
i2p::CreateI2NPMessage(msgType, data, size)); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
#ifndef _FUZZING_H_ |
||||
#define _FUZZING_H_ |
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
|
||||
|
||||
void fuzzing_tick(void); |
||||
|
||||
void fuzzing_throttle(void); |
||||
|
||||
bool fuzzing_testinput(const uint8_t * data, size_t size); |
||||
|
||||
|
||||
#endif /* !_FUZZING_H_ */ |
@ -0,0 +1,162 @@
@@ -0,0 +1,162 @@
|
||||
|
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include <Config.h> |
||||
#include <Log.h> |
||||
#include <FS.h> |
||||
#include <Destination.h> |
||||
#include <NetDb.hpp> |
||||
#include <Tunnel.h> |
||||
#include <RouterContext.h> |
||||
#include <Transports.h> |
||||
#include <version.h> |
||||
|
||||
#include "fuzzing.h" |
||||
|
||||
|
||||
static bool (*runner)(const uint8_t *, size_t); |
||||
|
||||
|
||||
static |
||||
bool |
||||
run_single(const uint8_t * data, size_t size) |
||||
{ |
||||
bool status; |
||||
|
||||
|
||||
status = fuzzing_testinput(data, size); |
||||
|
||||
fuzzing_tick(); |
||||
fuzzing_throttle(); |
||||
|
||||
return status; |
||||
} |
||||
|
||||
|
||||
static |
||||
bool |
||||
run_batch(const uint8_t * data, size_t size) |
||||
{ |
||||
bool status; |
||||
size_t chunklen; |
||||
|
||||
|
||||
if(size < 2) |
||||
{ |
||||
// XXX - Test something to prevent fuzzer from giving up
|
||||
status = fuzzing_testinput(data, size); |
||||
fuzzing_tick(); |
||||
} |
||||
else |
||||
{ |
||||
status = false; |
||||
|
||||
while(size >= 2) |
||||
{ |
||||
chunklen = (data[0] << 8) | data[1]; |
||||
|
||||
data += 2; |
||||
size -= 2; |
||||
|
||||
if(chunklen > size) |
||||
chunklen = size; |
||||
|
||||
if(fuzzing_testinput(data, chunklen)) |
||||
status = true; |
||||
|
||||
data += chunklen; |
||||
size -= chunklen; |
||||
|
||||
fuzzing_tick(); |
||||
} |
||||
} |
||||
|
||||
fuzzing_throttle(); |
||||
|
||||
return status; |
||||
} |
||||
|
||||
|
||||
static |
||||
void |
||||
do_stop(void) |
||||
{ |
||||
i2p::tunnel::tunnels.Stop(); |
||||
i2p::transport::transports.Stop(); |
||||
i2p::data::netdb.Stop(); |
||||
i2p::log::Logger().Stop(); |
||||
} |
||||
|
||||
|
||||
static |
||||
void |
||||
do_setup(void) |
||||
{ |
||||
i2p::log::Logger().Start(); |
||||
i2p::log::Logger().SetLogLevel("critical"); |
||||
|
||||
i2p::config::Init(); |
||||
i2p::config::ParseCmdline(1, (char *[]) { (char *) "foo" }); |
||||
|
||||
// Disable networking
|
||||
i2p::config::SetOption("ipv4", false); |
||||
i2p::config::SetOption("ipv6", false); |
||||
|
||||
i2p::fs::DetectDataDir("testdata", false); |
||||
i2p::fs::Init(); |
||||
|
||||
i2p::context.SetNetID(I2PD_NET_ID); |
||||
i2p::context.Init(); |
||||
|
||||
i2p::data::netdb.Start(); |
||||
|
||||
i2p::transport::transports.Start(true, true); |
||||
|
||||
i2p::tunnel::tunnels.Start(); |
||||
|
||||
// Stop threads before destructor called to avoid crash on exit
|
||||
atexit(do_stop); |
||||
} |
||||
|
||||
|
||||
static |
||||
bool |
||||
do_init(void) |
||||
{ |
||||
do_setup(); |
||||
|
||||
//
|
||||
// If FUZZING_BATCH env variable set, run batch mode.
|
||||
//
|
||||
// Pros:
|
||||
// More data queued at once before time to process/empty all of it
|
||||
// Better change of hitting thread bugs
|
||||
//
|
||||
// Cons:
|
||||
// Input test data limited to 64k
|
||||
// Input buffer under/over-reads may go un-noticed
|
||||
//
|
||||
if(getenv("FUZZING_BATCH") != nullptr) |
||||
runner = run_batch; |
||||
else |
||||
runner = run_single; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
extern "C" |
||||
int |
||||
LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) |
||||
{ |
||||
static bool inited = do_init(); |
||||
|
||||
|
||||
// Suppress compiler warning
|
||||
(void) inited; |
||||
|
||||
return runner(data, size) ? 0 : -1; |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
|
||||
#include <thread> |
||||
|
||||
#include "fuzzing.h" |
||||
|
||||
|
||||
static unsigned int counter = 0; |
||||
|
||||
|
||||
void |
||||
fuzzing_tick(void) |
||||
{ |
||||
counter++; |
||||
} |
||||
|
||||
|
||||
void |
||||
fuzzing_throttle(void) |
||||
{ |
||||
unsigned int delay; |
||||
|
||||
|
||||
// Give queues time to drain (avoid OOM or crash)
|
||||
// - Too high a delay slows down fuzzing
|
||||
// - Too low a delay causes intermittent crash on exit
|
||||
delay = 50 + (counter / 50); |
||||
counter = 0; |
||||
|
||||
if(delay > 5000) |
||||
delay = 5000; |
||||
|
||||
std::this_thread::sleep_for (std::chrono::milliseconds(delay)); |
||||
} |
Loading…
Reference in new issue