Skip to content

genesis: improve client fuzzer#8481

Draft
two-heart wants to merge 1 commit intofiredancer-io:mainfrom
two-heart:fuzz-genesis
Draft

genesis: improve client fuzzer#8481
two-heart wants to merge 1 commit intofiredancer-io:mainfrom
two-heart:fuzz-genesis

Conversation

@two-heart
Copy link
Contributor

No description provided.

Copilot AI review requested due to automatic review settings February 26, 2026 12:15
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR significantly enhances the genesis client fuzzer by adding comprehensive fuzzing capabilities including multi-peer support, structured input generation, custom mutation logic, and multiple test scenarios covering various HTTP response edge cases.

Changes:

  • Expanded the fuzzer from a simple single-peer test to support up to 4 concurrent peers with configurable scenarios
  • Added a custom mutator (LLVMFuzzerCustomMutator) that generates structured fuzzing inputs with awareness of the protocol being tested
  • Implemented 12 distinct test scenarios covering various edge cases like incomplete headers, malformed responses, missing content-length, overflow conditions, and timeout scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +483 to +485
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
ulong step_budget = 16UL + fuzz_mut_roll( &rng, FUZZ_MAX_STEPS-15UL );
data[ cursor++ ] = (uchar)(step_budget - 16UL);
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential buffer overflow: After the loop ending at line 481, cursor could equal or exceed max_sz. Lines 483-485 unconditionally execute fuzz_mut_ensure and write data[cursor++], which would result in an out-of-bounds write when cursor >= max_sz. Add a bounds check before this write: if(cursor<max_sz) or ensure the loop leaves cursor less than max_sz.

Suggested change
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
ulong step_budget = 16UL + fuzz_mut_roll( &rng, FUZZ_MAX_STEPS-15UL );
data[ cursor++ ] = (uchar)(step_budget - 16UL);
if( cursor<max_sz ) {
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
ulong step_budget = 16UL + fuzz_mut_roll( &rng, FUZZ_MAX_STEPS-15UL );
data[ cursor++ ] = (uchar)(step_budget - 16UL);
}

Copilot uses AI. Check for mistakes.
Comment on lines +484 to +497
ulong step_budget = 16UL + fuzz_mut_roll( &rng, FUZZ_MAX_STEPS-15UL );
data[ cursor++ ] = (uchar)(step_budget - 16UL);

ulong steps_to_emit = fd_ulong_min( step_budget, 40UL + fuzz_mut_roll( &rng, 24UL ) );
for( ulong step=0UL; step<steps_to_emit && cursor<max_sz; step++ ) {
fuzz_mut_ensure( data, &data_sz, cursor+2UL, max_sz, &rng );
if( FD_UNLIKELY( cursor>=data_sz ) ) break;
data[ cursor++ ] = (uchar)fuzz_mut_roll( &rng, peer_cnt );
uchar action = (uchar)fuzz_mut_roll( &rng, 8UL );
if( (action==7U) && (0UL==fuzz_mut_roll( &rng, 2UL )) ) action |= 0x40U;
if( 0UL==fuzz_mut_roll( &rng, 9UL ) ) action |= 0x80U;
data[ cursor++ ] = action;
if( (action & 7U)==0U ) {
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential buffer overflow: After line 491 increments cursor, cursor could equal max_sz. Line 495 then writes data[cursor++] without checking bounds, resulting in an out-of-bounds write. Similarly, if cursor equals max_sz after line 495, lines 497-498 could also write out of bounds. Add bounds checks or modify the loop to ensure cursor never reaches max_sz before writes.

Suggested change
ulong step_budget = 16UL + fuzz_mut_roll( &rng, FUZZ_MAX_STEPS-15UL );
data[ cursor++ ] = (uchar)(step_budget - 16UL);
ulong steps_to_emit = fd_ulong_min( step_budget, 40UL + fuzz_mut_roll( &rng, 24UL ) );
for( ulong step=0UL; step<steps_to_emit && cursor<max_sz; step++ ) {
fuzz_mut_ensure( data, &data_sz, cursor+2UL, max_sz, &rng );
if( FD_UNLIKELY( cursor>=data_sz ) ) break;
data[ cursor++ ] = (uchar)fuzz_mut_roll( &rng, peer_cnt );
uchar action = (uchar)fuzz_mut_roll( &rng, 8UL );
if( (action==7U) && (0UL==fuzz_mut_roll( &rng, 2UL )) ) action |= 0x40U;
if( 0UL==fuzz_mut_roll( &rng, 9UL ) ) action |= 0x80U;
data[ cursor++ ] = action;
if( (action & 7U)==0U ) {
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
ulong step_budget = 16UL + fuzz_mut_roll( &rng, FUZZ_MAX_STEPS-15UL );
if( FD_UNLIKELY( cursor>=max_sz ) ) return data_sz;
data[ cursor++ ] = (uchar)(step_budget - 16UL);
ulong steps_to_emit = fd_ulong_min( step_budget, 40UL + fuzz_mut_roll( &rng, 24UL ) );
for( ulong step=0UL; step<steps_to_emit && cursor<max_sz; step++ ) {
fuzz_mut_ensure( data, &data_sz, cursor+2UL, max_sz, &rng );
if( FD_UNLIKELY( cursor>=data_sz ) ) break;
if( FD_UNLIKELY( cursor>=max_sz ) ) break;
data[ cursor++ ] = (uchar)fuzz_mut_roll( &rng, peer_cnt );
uchar action = (uchar)fuzz_mut_roll( &rng, 8UL );
if( (action==7U) && (0UL==fuzz_mut_roll( &rng, 2UL )) ) action |= 0x40U;
if( 0UL==fuzz_mut_roll( &rng, 9UL ) ) action |= 0x80U;
if( FD_UNLIKELY( cursor>=max_sz ) ) break;
data[ cursor++ ] = action;
if( (action & 7U)==0U ) {
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
if( FD_UNLIKELY( cursor>=max_sz ) ) break;

Copilot uses AI. Check for mistakes.
Comment on lines +464 to +470
if( mode>=8UL ) {
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
data[ cursor++ ] = fuzz_mut_u8( &rng );
}

fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
data[ cursor++ ] = (uchar)fuzz_mut_roll( &rng, 3UL );
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential buffer overflow: After line 462 sets cursor to min(max_sz, cursor+body_sz), cursor could equal max_sz. If mode is greater than or equal to 8, the code calls fuzz_mut_ensure which will clamp data_sz to max_sz, but then line 466 writes data[cursor++] where cursor could be max_sz, resulting in an out-of-bounds write. Add a check: if(cursor<max_sz) before the write or change the condition to if(mode>=8UL && cursor<max_sz).

Suggested change
if( mode>=8UL ) {
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
data[ cursor++ ] = fuzz_mut_u8( &rng );
}
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
data[ cursor++ ] = (uchar)fuzz_mut_roll( &rng, 3UL );
if( mode>=8UL && cursor<max_sz ) {
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
data[ cursor++ ] = fuzz_mut_u8( &rng );
}
if( cursor<max_sz ) {
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
data[ cursor++ ] = (uchar)fuzz_mut_roll( &rng, 3UL );
}

Copilot uses AI. Check for mistakes.
Comment on lines +469 to +470
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
data[ cursor++ ] = (uchar)fuzz_mut_roll( &rng, 3UL );
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential buffer overflow: After line 462 sets cursor to min(max_sz, cursor+body_sz), cursor could equal max_sz. Lines 469-470 unconditionally execute fuzz_mut_ensure and write data[cursor++], which would result in an out-of-bounds write when cursor equals max_sz. The loop condition cursor<max_sz on line 447 is only checked at the start of each iteration, not before these writes. Add a check before this write or break the loop if cursor >= max_sz after line 467.

Copilot uses AI. Check for mistakes.
fuzz_mut_ensure( data, &data_sz, cursor+1UL, max_sz, &rng );
uchar send_now = (uchar)(fuzz_mut_roll( &rng, 4UL ) ? 1U : 0U);
data[ cursor++ ] = send_now;
if( send_now ) {
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential buffer overflow: After line 476 increments cursor, cursor could equal max_sz. If send_now is true, lines 478-479 execute fuzz_mut_ensure and write data[cursor++], which would result in an out-of-bounds write when cursor equals max_sz. Add a check: change line 477 to if(send_now && cursor<max_sz) to prevent the out-of-bounds write.

Suggested change
if( send_now ) {
if( send_now && cursor<max_sz ) {

Copilot uses AI. Check for mistakes.
@two-heart two-heart marked this pull request as draft February 26, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants