Skip to content

fix: undefined behavior in indexed() for rank-0 histograms#432

Open
henryiii wants to merge 1 commit into
boostorg:developfrom
henryiii:henryiii/fix/rank0-indexed
Open

fix: undefined behavior in indexed() for rank-0 histograms#432
henryiii wants to merge 1 commit into
boostorg:developfrom
henryiii:henryiii/fix/rank0-indexed

Conversation

@henryiii

Copy link
Copy Markdown
Contributor

🤖 AI text below 🤖

Fixes #430.

For a rank-0 histogram, indexed_range::iterator::operator++ dereferenced the first slot of the per-axis index buffer, which is empty when there are no axes. That read uninitialized stack memory and, with unlucky stack contents, walked the cell iterator out of bounds — observed as a reproducible segfault on free-threaded Windows via the Python bindings (scikit-hep/boost-histogram#1153).

The fix skips the index update when the index buffer is empty; the single cell of a rank-0 histogram is still visited exactly once, so indexed(), algorithm::sum(h, coverage::inner), and algorithm::empty now all work for rank 0.

Regression tests cover indexed() (both coverages), sum, and empty on a rank-0 histogram. They pass only by luck without the fix (the uninitialized read is stack-layout dependent and needs MemorySanitizer to detect reliably), but they pin down the intended behavior.

@HDembinski

Copy link
Copy Markdown
Collaborator

This needs an update now.

I am surprised that a rank 0 histogram still has a single accumulator. I suppose that's consistent with numpy, but not something I remember defining as an explicit edge case.

@henryiii
henryiii force-pushed the henryiii/fix/rank0-indexed branch from f7585d0 to 45e5004 Compare July 23, 2026 17:39
For a rank-0 histogram the per-axis index buffer is empty, but
operator++ dereferenced its first slot anyway, reading uninitialized
memory. Depending on stack contents this walked the cell iterator out
of bounds (observed as a segfault on free-threaded Windows in
scikit-hep/boost-histogram). Skip the index update when there are no
axes; the single cell is still visited once. This also fixes
algorithm::sum(h, coverage::inner) and algorithm::empty for rank-0.

Fixes boostorg#430

Assisted-by: ClaudeCode:claude-fable-5
@henryiii
henryiii force-pushed the henryiii/fix/rank0-indexed branch from 45e5004 to b95f88b Compare July 23, 2026 17:48
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.

indexed() is undefined behavior for rank-0 (zero-axis) histograms

2 participants