Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion fuzzing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,11 @@ add_executable(fuzz_evm_payload
../src/evm_parser.c
)
target_compile_definitions(fuzz_evm_payload PRIVATE NO_BOLOS_SDK=1)
target_link_libraries(fuzz_evm_payload mock_bolos)
target_link_libraries(fuzz_evm_payload mock_bolos)

add_executable(fuzz_swap_token_utils
fuzzer_swap_token_utils.c
../src/swap/swap_token_utils.c
)
target_compile_definitions(fuzz_swap_token_utils PRIVATE NO_BOLOS_SDK=1)
target_link_libraries(fuzz_swap_token_utils mock_bolos)
67 changes: 67 additions & 0 deletions fuzzing/fuzzer_swap_token_utils.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <stdint.h>
#include <stddef.h>
#include <string.h>

#include "swap/swap_token_utils.h"

#define MAX_ASSET_LEN 16
#define MAX_OUT_LEN 64
#define MAX_STR_LEN 16

static size_t min_size(size_t a, size_t b) {
return (a < b) ? a : b;
}

static uint64_t load_u64_be(const uint8_t *data, size_t len) {
uint64_t v = 0;
for (size_t i = 0; i < len; i++) {
v = (v << 8) | data[i];
}
return v;
}

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (data == NULL || size == 0) return 0;

size_t offset = 0;
uint8_t flags = data[offset++];

uint8_t decimals = (offset < size) ? data[offset++] : 0;

size_t amount_len = min_size(8, size - offset);
uint64_t amount = load_u64_be(data + offset, amount_len);
offset += amount_len;

uint8_t out_len_hint = (offset < size) ? data[offset++] : 0;
size_t out_len = out_len_hint % (MAX_OUT_LEN + 1);

const char *asset = NULL;
char asset_buf[MAX_ASSET_LEN + 1];
if ((flags & 0x1) && offset < size) {
size_t asset_len = data[offset++] % (MAX_ASSET_LEN + 1);
size_t avail = size - offset;
if (asset_len > avail) asset_len = avail;
memcpy(asset_buf, data + offset, asset_len);
asset_buf[asset_len] = '\0';
asset = asset_buf;
offset += asset_len;
}

char out_buf[MAX_OUT_LEN + 1];
memset(out_buf, 0, sizeof(out_buf));
(void)print_token_amount(amount, asset, decimals, out_buf, out_len);

uint8_t str_buf[MAX_STR_LEN];
size_t str_len = min_size(MAX_STR_LEN, size - offset);
memset(str_buf, 0, sizeof(str_buf));
if (str_len > 0) {
memcpy(str_buf, data + offset, str_len);
}

uint64_t parsed = 0;
size_t len_hint = data[0] % (MAX_STR_LEN + 1);
(void)swap_str_to_u64(str_buf, len_hint, &parsed);
(void)swap_str_to_u64(str_buf, MAX_STR_LEN, &parsed);

return 0;
}
8 changes: 6 additions & 2 deletions fuzzing/run_fuzzing.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ setup_directories() {
# Create corpus directories for each fuzzer
mkdir -p "$CORPUS_DIR/proto_varlen_parser"
mkdir -p "$CORPUS_DIR/evm_payload"

mkdir -p "$CORPUS_DIR/swap_token_utils"

print_status "Directories created"
}

Expand Down Expand Up @@ -94,6 +95,9 @@ generate_corpus() {
# ERC20 transfer selector only
printf "\xA9\x05\x9C\xBB" > "$CORPUS_DIR/evm_payload/selector.bin"
# Full calldata: selector + 32-byte address word + 32-byte amount word
# swap_token_utils seeds
printf "\x01\x08\x00\x00\x00\x00\x00\x00\x00\x01\x20\x04HBAR" > "$CORPUS_DIR/swap_token_utils/hbar_valid.bin"
printf "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x10" > "$CORPUS_DIR/swap_token_utils/max_valid.bin"
(
printf "\xA9\x05\x9C\xBB"
# address word: 12 zero pad + 20 0x11 bytes
Expand Down Expand Up @@ -156,7 +160,7 @@ run_fuzzer() {
run_all_fuzzers() {
print_status "Starting fuzzing campaign..."

local fuzzers=("proto_varlen_parser" "evm_payload")
local fuzzers=("proto_varlen_parser" "evm_payload" "swap_token_utils")

for fuzzer in "${fuzzers[@]}"; do
run_fuzzer "$fuzzer" "$FUZZ_TIME"
Expand Down
Loading