RealDataBench.cpp reads past line bounds and passes invalid versions #58

Closed
opened 2026-06-29 00:03:51 +00:00 by weaselbot · 0 comments
Member

While exercising RealDataBench.cpp with a minimal dataset, it aborts immediately on a std::span bounds assertion.

Locations

  • RealDataBench.cpp line 89: write = line.subspan(2, line.size());
  • RealDataBench.cpp line 95: reads.push_back(line.subspan(2, line.size()));

std::span::subspan(offset, count) takes a count, not an end offset. For a line of length N, these calls request N bytes starting at offset 2, but only N - 2 bytes are available after the P / L prefix. In a Debug build this triggers the assertion from std::span::subspan (__offset + __count <= size()); in a Release build it silently reads into the following line's memory.

The intended expression is almost certainly line.subspan(2, line.size() - 2) (with a guard for lines shorter than 2 bytes).

Additional API contract violations

  • Line 103: iter->readVersion = version - 100; produces a negative readVersion for the first 100 batches, violating the documented requirement that all versions be >= 0. In Debug builds this aborts at ConflictSet.cpp:4873; in Release it wraps through InternalVersionT and yields incorrect conflict results.
  • Line 119: cs.setOldestVersion(version - 10000); produces a negative oldestVersion for the first 10 000 batches, violating the same contract and the monotonicity requirement for setOldestVersion.

Reproduction

printf 'P hello\nL world\n\n' > sample.txt
./real_data_bench sample.txt

Result (Debug build):

/usr/include/c++/16/span:442:
constexpr std::span<_Type, 18446744073709551615>::subspan(size_type, size_type):
Assertion '__offset + __count <= size()' failed.

Expected vs actual

  • Expected: The benchmark strips the two-byte prefix from each line without out-of-bounds access, and only passes non-negative, monotonically increasing versions to the conflict set.
  • Actual: It requests more bytes than the line contains, and passes negative readVersion / oldestVersion values during the warmup phase.

Impact

RealDataBench cannot run on the documented memetracker9 dataset without crashing in Debug or reading out of bounds in Release, and its early measurements are based on invalid API inputs.

While exercising `RealDataBench.cpp` with a minimal dataset, it aborts immediately on a `std::span` bounds assertion. ## Locations - `RealDataBench.cpp` line 89: `write = line.subspan(2, line.size());` - `RealDataBench.cpp` line 95: `reads.push_back(line.subspan(2, line.size()));` `std::span::subspan(offset, count)` takes a *count*, not an end offset. For a line of length `N`, these calls request `N` bytes starting at offset `2`, but only `N - 2` bytes are available after the `P ` / `L ` prefix. In a Debug build this triggers the assertion from `std::span::subspan` (`__offset + __count <= size()`); in a Release build it silently reads into the following line's memory. The intended expression is almost certainly `line.subspan(2, line.size() - 2)` (with a guard for lines shorter than 2 bytes). ## Additional API contract violations - Line 103: `iter->readVersion = version - 100;` produces a negative `readVersion` for the first 100 batches, violating the documented requirement that all versions be `>= 0`. In Debug builds this aborts at `ConflictSet.cpp:4873`; in Release it wraps through `InternalVersionT` and yields incorrect conflict results. - Line 119: `cs.setOldestVersion(version - 10000);` produces a negative `oldestVersion` for the first 10 000 batches, violating the same contract and the monotonicity requirement for `setOldestVersion`. ## Reproduction ```bash printf 'P hello\nL world\n\n' > sample.txt ./real_data_bench sample.txt ``` Result (Debug build): ``` /usr/include/c++/16/span:442: constexpr std::span<_Type, 18446744073709551615>::subspan(size_type, size_type): Assertion '__offset + __count <= size()' failed. ``` ## Expected vs actual - **Expected:** The benchmark strips the two-byte prefix from each line without out-of-bounds access, and only passes non-negative, monotonically increasing versions to the conflict set. - **Actual:** It requests more bytes than the line contains, and passes negative `readVersion` / `oldestVersion` values during the warmup phase. ## Impact `RealDataBench` cannot run on the documented memetracker9 dataset without crashing in Debug or reading out of bounds in Release, and its early measurements are based on invalid API inputs.
weaselbot was assigned by andrew 2026-06-29 17:31:10 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: weaselab/conflict-set#58