Skip to content

Memoizer reuses readers initialized with different DynamicMetadataOptions #4472

Description

@Darlokt

As a continuation of #4464, FormatTools.equalReaders currently compares only the metadata level.
It does not compare validation or reader-specific DynamicMetadataOptions.
Memoizer can therefore deserialize reader state initialized with options that differ from the current request. A current .bfoptions sidecar is also not loaded into the fresh reader before the compatibility check.

This can affect pixel decoding, metadata parsing, and other reader-specific initialization behavior.

Minimal reproduction

String id = "/tmp/options.fake";

FakeReader firstReader = new FakeReader();
DynamicMetadataOptions firstOptions = new DynamicMetadataOptions();
firstOptions.set("reader.option", "first");
firstReader.setMetadataOptions(firstOptions);
try (Memoizer first = new Memoizer(firstReader, 0)) {
  first.setId(id); // saves memo initialized with "first"
}

FakeReader secondReader = new FakeReader();
DynamicMetadataOptions secondOptions = new DynamicMetadataOptions();
secondOptions.set("reader.option", "second");
secondReader.setMetadataOptions(secondOptions);
try (Memoizer second = new Memoizer(secondReader, 0)) {
  second.setId(id);
  assert !second.isLoadedFromMemo(); // fails on the base branch
}

The same stale hit can be reproduced by changing <id>.bfoptions while preserving the primary file.

Expected behavior

Memoizer accepts a cached reader only when all effective metadata options match the current reader.
Built-in options should use value equality.
A custom MetadataOptions implementation that retains identity equality should safely miss the cache.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions