Skip to content

Fix potential OOB-read in delta diff#719

Open
danielinux wants to merge 2 commits intowolfSSL:masterfrom
danielinux:fixes-20260310
Open

Fix potential OOB-read in delta diff#719
danielinux wants to merge 2 commits intowolfSSL:masterfrom
danielinux:fixes-20260310

Conversation

@danielinux
Copy link
Member

F/434 - potential out-of-bounds read while creating the patch

Also includes minor unrelated fix:

F/436: Added missing parenthesis around macro

Copilot AI review requested due to automatic review settings March 10, 2026 16:25
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

Fixes a potential out-of-bounds read in wb_diff() when extending matches to the end of the input buffers, and adds unit tests to reproduce those edge cases. Also includes a small macro correctness tweak.

Changes:

  • Add bounds checks in wb_diff() match-extension loops to prevent OOB reads.
  • Add new unit tests covering “match extends to end of src_b” scenarios.
  • Fix a macro precedence issue by adding missing parentheses.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
tools/unit-tests/unit-delta.c Adds regression tests for the OOB scenario; refactors buffer initialization helper.
src/delta.c Adds bounds checks to prevent match-extension loops from reading past buffer ends.
src/libwolfboot.c Wraps a macro expression in parentheses to avoid precedence issues.

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

Comment on lines +170 to +182
uint32_t sector_size;
int ret;

sector_size = wb_diff_get_sector_size();
ck_assert_uint_gt(sector_size, BLOCK_HDR_SIZE);

src_a = calloc(1, sector_size + BLOCK_HDR_SIZE);
src_b = calloc(1, sector_size + BLOCK_HDR_SIZE + 1);
ck_assert_ptr_nonnull(src_a);
ck_assert_ptr_nonnull(src_b);

ret = wb_diff_init(&diff_ctx, src_a, sector_size + BLOCK_HDR_SIZE,
src_b, sector_size + BLOCK_HDR_SIZE + 1);
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

wb_diff_get_sector_size() returns an int, but the test stores it in a uint32_t. If the function returns a negative value on error, it will wrap to a large unsigned number, making the ck_assert_uint_gt pass and potentially triggering huge allocations. Store the return value in an int (or size_t after validating it’s positive), assert it’s > 0 / > BLOCK_HDR_SIZE using signed asserts, then convert for allocation sizes.

Suggested change
uint32_t sector_size;
int ret;
sector_size = wb_diff_get_sector_size();
ck_assert_uint_gt(sector_size, BLOCK_HDR_SIZE);
src_a = calloc(1, sector_size + BLOCK_HDR_SIZE);
src_b = calloc(1, sector_size + BLOCK_HDR_SIZE + 1);
ck_assert_ptr_nonnull(src_a);
ck_assert_ptr_nonnull(src_b);
ret = wb_diff_init(&diff_ctx, src_a, sector_size + BLOCK_HDR_SIZE,
src_b, sector_size + BLOCK_HDR_SIZE + 1);
int sector_size;
int ret;
sector_size = wb_diff_get_sector_size();
ck_assert_int_gt(sector_size, (int)BLOCK_HDR_SIZE);
src_a = calloc(1, (size_t)sector_size + BLOCK_HDR_SIZE);
src_b = calloc(1, (size_t)sector_size + BLOCK_HDR_SIZE + 1);
ck_assert_ptr_nonnull(src_a);
ck_assert_ptr_nonnull(src_b);
ret = wb_diff_init(&diff_ctx, src_a, (size_t)sector_size + BLOCK_HDR_SIZE,
src_b, (size_t)sector_size + BLOCK_HDR_SIZE + 1);

Copilot uses AI. Check for mistakes.
}
END_TEST

static void initialize_buffers(uint8_t *src_a, uint8_t *src_b, size_t size)
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

initialize_buffers() now takes a size parameter, but it still writes to fixed indices (510, 1022) unconditionally. This will go out of bounds if the helper is ever called with a smaller buffer size. Either guard these writes (e.g., only set them when size > 1022) or compute the marker positions relative to size.

Copilot uses AI. Check for mistakes.
Comment on lines 223 to 224
src_a[510] = ESC;
memcpy(src_b + 4090, src_a + 500, 20);


/* Copy a sequence from B to itself, ahead */
src_b[1022] = ESC;
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

initialize_buffers() now takes a size parameter, but it still writes to fixed indices (510, 1022) unconditionally. This will go out of bounds if the helper is ever called with a smaller buffer size. Either guard these writes (e.g., only set them when size > 1022) or compute the marker positions relative to size.

Copilot uses AI. Check for mistakes.
Comment on lines +305 to +307
while (((uintptr_t)(pa - ctx->src_a) < (uintptr_t)ctx->size_a) &&
(ctx->off_b < ctx->size_b) &&
(*pa == *(ctx->src_b + ctx->off_b))) {
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The new bounds checks rely on casting pointer differences to uintptr_t, which is harder to reason about and can mask sign/width issues (and tends to trip static analysis). Prefer expressing bounds in terms of end pointers (e.g., pa < ctx->src_a + ctx->size_a and pb < ctx->src_b + pb_end) or use size_t for offsets derived from pointer subtraction and compare against (size_t)ctx->size_*.

Copilot uses AI. Check for mistakes.
Comment on lines +365 to +367
while (((uintptr_t)(pb - ctx->src_b) < pb_end) &&
(ctx->off_b < ctx->size_b) &&
(*pb == *(ctx->src_b + ctx->off_b))) {
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The new bounds checks rely on casting pointer differences to uintptr_t, which is harder to reason about and can mask sign/width issues (and tends to trip static analysis). Prefer expressing bounds in terms of end pointers (e.g., pa < ctx->src_a + ctx->size_a and pb < ctx->src_b + pb_end) or use size_t for offsets derived from pointer subtraction and compare against (size_t)ctx->size_*.

Copilot uses AI. Check for mistakes.
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