upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormtg0001 <106211915+mtg0001@users.noreply.github.com>2026-08-04 15:31:55 -0300
committerGitHub <noreply@github.com>2026-08-04 15:31:55 -0300
commitb3a5a858e536acf65e6c6761293626628f2227bf (patch)
tree881dbe44ac6c0ea28f5a65cbfd9b835ba73ea648 /src
parent173b4649e90f4f5ba49e92569eb063709e647c7d (diff)
fuzz: add P2P message parser harness (#142)
* fuzz: add P2P message parser harness * fuzz: avoid duplicate legacy header includes * fuzz: seed the corpus with our network magic, not Bitcoin's The two seed inputs began f5 be b6 d9, which is Bitcoin's message start. Ours is bf 20 5c fd. CMessageHeader::IsValid rejects on that field first, so both seeds died at the first check and the smoke run exercised the reject path and nothing else. libFuzzer would have to mutate its way onto four exact bytes before reaching any parser, which does not happen in 128 runs. The job would have gone green while covering none of what it was added to cover. --------- Co-authored-by: Gilcimar Duarte <ti@gpm.infra> Co-authored-by: Bitflash-sh <btf01@proton.me>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile34
-rw-r--r--src/fuzz_net_message.cpp32
2 files changed, 65 insertions, 1 deletions
diff --git a/src/Makefile b/src/Makefile
index 3577dd6..ac0226e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2,6 +2,7 @@
2# Called by: make linux (root Makefile) 2# Called by: make linux (root Makefile)
3 3
4CXX ?= g++ 4CXX ?= g++
5FUZZ_CXX ?= clang++
5 6
6SECP_INC ?= /usr/local/include 7SECP_INC ?= /usr/local/include
7SECP_LIB ?= /usr/local/lib 8SECP_LIB ?= /usr/local/lib
@@ -33,6 +34,9 @@ CXXFLAGS = -std=gnu++14 -O2 $(WARNFLAGS) -fpermissive -pthread \
33 -I$(SECP_INC) -I$(RANDOMX_DIR)/src \ 34 -I$(SECP_INC) -I$(RANDOMX_DIR)/src \
34 -I/usr/include/nlohmann \ 35 -I/usr/include/nlohmann \
35 -I$(IMGUI_DIR) 36 -I$(IMGUI_DIR)
37FUZZ_CXXFLAGS = $(filter-out -O2,$(CXXFLAGS)) -O1 -g -fno-omit-frame-pointer \
38 -fsanitize=fuzzer-no-link,address,undefined
39FUZZ_LDFLAGS = -fsanitize=fuzzer,address,undefined
36 40
37LIBS = -L$(SECP_LIB) -lsecp256k1 \ 41LIBS = -L$(SECP_LIB) -lsecp256k1 \
38 -L$(RANDOMX_DIR)/build -lrandomx \ 42 -L$(RANDOMX_DIR)/build -lrandomx \
@@ -117,6 +121,9 @@ NODE_LIBS = -L$(SECP_LIB) -lsecp256k1 \
117NODE_ONLY_OBJS = $(patsubst obj/%,obj-node/%,$(NODE_OBJS)) \ 121NODE_ONLY_OBJS = $(patsubst obj/%,obj-node/%,$(NODE_OBJS)) \
118 obj-node/main_gui.o obj-node/headless.o 122 obj-node/main_gui.o obj-node/headless.o
119 123
124FUZZ_OBJS = $(patsubst obj/%,obj-fuzz/%,$(NODE_OBJS)) \
125 obj-fuzz/fuzz_net_message.o
126
120obj-node/%.o: %.cpp $(HEADERS) 127obj-node/%.o: %.cpp $(HEADERS)
121 @mkdir -p obj-node 128 @mkdir -p obj-node
122 $(CXX) -c $(CXXFLAGS) -DBITFLASH_NO_GUI -o $@ $< 129 $(CXX) -c $(CXXFLAGS) -DBITFLASH_NO_GUI -o $@ $<
@@ -129,8 +136,31 @@ bitflash-node: $(NODE_ONLY_OBJS)
129 $(CXX) $(CXXFLAGS) -o $@ $^ $(NODE_LIBS) 136 $(CXX) $(CXXFLAGS) -o $@ $^ $(NODE_LIBS)
130 @echo "Built: bitflash-node (headless, no libGL needed)" 137 @echo "Built: bitflash-node (headless, no libGL needed)"
131 138
139obj-fuzz/%.o: %.cpp $(HEADERS)
140 @mkdir -p obj-fuzz
141 $(FUZZ_CXX) -c $(FUZZ_CXXFLAGS) -DBITFLASH_FUZZ -o $@ $<
142
143obj-fuzz/sha.o: sha.cpp sha.h
144 @mkdir -p obj-fuzz
145 $(FUZZ_CXX) -c $(FUZZ_CXXFLAGS) -DBITFLASH_FUZZ -O1 -o $@ $<
146
147obj-fuzz/fuzz_net_message.o: fuzz_net_message.cpp $(HEADERS)
148 @mkdir -p obj-fuzz
149 $(FUZZ_CXX) -c $(FUZZ_CXXFLAGS) -DBITFLASH_FUZZ -o $@ $<
150
151fuzz-net-message: $(FUZZ_OBJS)
152 $(FUZZ_CXX) $(filter-out -fsanitize=fuzzer-no-link%,$(FUZZ_CXXFLAGS)) \
153 $(FUZZ_LDFLAGS) -o $@ $^ $(NODE_LIBS)
154 @echo "Built: fuzz-net-message"
155
156fuzz-net-message-smoke: fuzz-net-message
157 @mkdir -p ../work/fuzz-corpus/net-message
158 @printf '\277\040\134\375ping\000\000\000\000\000\000\000\000\000\000\000\000' > ../work/fuzz-corpus/net-message/ping-header
159 @printf '\277\040\134\375version\000\000\000\000\000\000\000\000\000' > ../work/fuzz-corpus/net-message/version-header
160 ./fuzz-net-message -runs=128 ../work/fuzz-corpus/net-message
161
132clean: 162clean:
133 rm -rf obj obj-node bitflash bitflash-node test_bip32 163 rm -rf obj obj-node obj-fuzz bitflash bitflash-node fuzz-net-message test_bip32
134 164
135test_bip32: test_bip32.cpp bip32.cpp bip32.h bip39_english.h 165test_bip32: test_bip32.cpp bip32.cpp bip32.h bip39_english.h
136 $(CXX) $(CXXFLAGS) -o $@ test_bip32.cpp bip32.cpp -lssl -lcrypto 166 $(CXX) $(CXXFLAGS) -o $@ test_bip32.cpp bip32.cpp -lssl -lcrypto
@@ -144,3 +174,5 @@ tests: test_bip32 bitflash-node
144 ./bitflash-node -selftest=wallet-encrypt 174 ./bitflash-node -selftest=wallet-encrypt
145 ./bitflash-node -selftest=net-message 175 ./bitflash-node -selftest=net-message
146 ./bitflash-node -selftest=consensus-limits 176 ./bitflash-node -selftest=consensus-limits
177
178.PHONY: tests fuzz-net-message-smoke
diff --git a/src/fuzz_net_message.cpp b/src/fuzz_net_message.cpp
new file mode 100644
index 0000000..1104d90
--- /dev/null
+++ b/src/fuzz_net_message.cpp
@@ -0,0 +1,32 @@
1// Copyright (c) 2026 Bitflash developers
2// Distributed under the MIT/X11 software license.
3//
4// libFuzzer harness for the P2P message envelope parser. It feeds arbitrary
5// receive-buffer bytes into ProcessMessages() through a dummy CNode, without
6// opening sockets or starting node threads.
7
8#include "headers_core.h"
9
10#include <stdint.h>
11#include <stddef.h>
12
13// Stand-ins normally supplied by the GUI/headless entry objects.
14map<string,string> mapAddressBook;
15bool gPoolServerRunning = false;
16void MainFrameRepaint() {}
17
18extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
19{
20 // Keep this first target focused on parser behavior, not multi-megabyte
21 // allocation pressure. The protocol size guards have their own selftest.
22 if (size > 4096)
23 return 0;
24
25 CNode node(INVALID_SOCKET, CAddress("127.0.0.1"));
26 node.nVersion = 0; // exercise pre-version gating plus the version parser
27 if (size > 0)
28 node.vRecv.write((const char*)data, (int)size);
29
30 ProcessMessages(&node);
31 return 0;
32}