Skip to content
This repository was archived by the owner on Jun 5, 2026. It is now read-only.
This repository was archived by the owner on Jun 5, 2026. It is now read-only.

fix: HashCounter::iter() stack-overflows via 4096-deep nested Chain iterators #39

Description

@korniltsev-grafanista

Summary

HashCounter::iter() in src/collector.rs builds a left-leaning chain of 4096 nested Box<dyn Iterator> + Chain pairs — one per bucket (BUCKETS = 1 << 12 = 4096):

Box<Chain<Box<Chain<Box<Chain<...>>, BucketIterator>>, BucketIterator>>

Calling size_hint() on the returned iterator recurses through all 4096 levels via vtable dispatch (Chain::size_hintBox<dyn Iterator>::size_hint → vtable → Chain::size_hint → ...), eventually causing a stack overflow.

Reproduction

RUSTFLAGS="-Zsanitizer=address" cargo +nightly test --target aarch64-apple-darwin --lib

ASAN reports:

ERROR: AddressSanitizer: stack-overflow on address ...
    #0 ... Chain::size_hint  chain.rs:182
    #1 ... Box<dyn Iterator>::size_hint  iter.rs:24
    #2 ... Chain::size_hint  chain.rs:185
    #3 ... Box<dyn Iterator>::size_hint  iter.rs:24
    ... (repeating ~4096 times)

The recursion depth equals BUCKETS, which at 4096 is deep enough to overflow even without ASAN on constrained stacks (e.g. signal handler stacks, threads with reduced stack size).

Fix

Replace the manual chaining loop with flat_map, which has O(1) stack depth:

pub fn iter(&self) -> impl Iterator<Item = &Entry<T>> {
    self.buckets.iter().flat_map(|bucket| bucket.iter())
}

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