Skip to content

file_store: Store::load never terminates when a changeset entry decodes to zero bytes #2307

Open

Description

@noahjoeris

Describe the bug

EntryIter::next (crates/file_store/src/entry_iter.rs) treats every successful deserialize_from as progress but never checks that the read advanced the file offset. For a changeset type whose bincode encoding is zero bytes (e.g. (), which implements Merge in bdk_core), any trailing byte after the magic bytes makes Store::dump decode the same position over and over, so Store::load never returns.

This affects loading a corrupted or hand-edited store file. #2258 appears to address this by framing each entry with a length prefix.

This issue was found by AI.

To Reproduce

Add crates/file_store/tests/test_zero_width.rs and run cargo test -p bdk_file_store --test test_zero_width:

use bdk_file_store::Store;
use std::time::Duration;

const MAGIC: &[u8] = b"bdk_test_magic";

#[test]
fn load_terminates_on_zero_width_changeset() {
    let dir = tempfile::tempdir().unwrap();
    let path = dir.path().join("db");
    let mut bytes = MAGIC.to_vec();
    bytes.push(0xff); // any trailing byte
    std::fs::write(&path, &bytes).unwrap();

    let (tx, rx) = std::sync::mpsc::channel();
    std::thread::spawn(move || {
        let result = Store::<()>::load(MAGIC, &path);
        let _ = tx.send(result.is_ok());
    });
    // `()` decodes as zero bytes, so the file offset never advances and `load` never reaches EOF.
    assert!(
        rx.recv_timeout(Duration::from_secs(5)).is_ok(),
        "load did not terminate"
    );
}

Current output:

thread 'load_terminates_on_zero_width_changeset' panicked at crates/file_store/tests/test_zero_width.rs:20:5:
load did not terminate

Expected behavior

Loading a store file should always terminate, returning either the aggregated changeset or an error.

Activity

  1. Brijesh-Thakkar commented on Sep 30, 2026

    @Brijesh-Thakkar

    Heyy I would love to work on thiss issue
    Thankss

  2. added a commit that references this issue on Sep 30, 2026
    78fa2d3
  3. luhrhenz commented on Oct 8, 2026

    @luhrhenz

    i have created a pr to fix this issue , please review

  4. Brijesh-Thakkar commented on Oct 9, 2026

    @Brijesh-Thakkar

    @luhrhenz Heyyyy
    #2333 Please see the comment i did before i made the PR as draft
    Hope that helps
    Thanks

  5. luhrhenz commented on Oct 9, 2026

    @luhrhenz

    @Brijesh-Thakkar yeahhh, thanks
    that's why i also added a code comment noting the relationship with the #2258 , so which ever lands first, so the regression test will be there to keep as guard.

  6. nymius commented on Oct 13, 2026

    @nymius
    Contributor

    Would a changeset of type () ever be valid? Why would anyone have something like that? I've prevented this error in #2258, but I don't know why anyone would have something like this, except to produce this issue, which sounds as a self inflicted error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    • Status
      In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions