Skip to content

Stim - RareErrorIterator constructor crashes with probability=1.0 when _GLIBCXX_ASSERTIONS is enabled #4026

@amccaskey

Description

@amccaskey

Required prerequisites

  • Consult the security policy. If reporting a security vulnerability, do not report the bug using this form. Use the process described in the policy to report the issue.
  • Make sure you've read the documentation. Your issue may be addressed there.
  • Search the issue tracker to verify that this hasn't already been reported. +1 or comment there if it has.
  • If possible, make a PR with a failing test to give us a starting point to work on!

Describe the bug

Component: runtime/nvqir/stim (Stim third-party library integration)

Severity: Medium — crashes unit tests under Debug/assertion-enabled builds


Description

The stim::RareErrorIterator constructor in tpls/Stim/src/stim/util_bot/probability_util.cc crashes with a std::geometric_distribution assertion failure when called with probability=1.0. This occurs in test_runtime_stim during noise simulation tests that apply bit-flip channels with probability 1.0.

Steps to Reproduce

  1. Build CUDA-Q with _GLIBCXX_ASSERTIONS enabled (e.g., Debug or RelWithDebInfo build type)
  2. Run unittests/test_runtime_stim --gtest_filter=*Noise*checkBitFlipTypeSimple

Observed Behavior

/usr/include/c++/11/bits/random.h:4001:
std::geometric_distribution<_IntType>::param_type::param_type(double):
Assertion '(_M_p > 0.0) && (_M_p < 1.0)' failed.

The program aborts in the RareErrorIterator constructor.

Expected Behavior

The test should pass. probability=1.0 is a valid input — every sample should be a hit.

Root Cause

In tpls/Stim/src/stim/util_bot/probability_util.cc, line 23-24:

RareErrorIterator::RareErrorIterator(float probability)
    : next_candidate(0), is_one(probability == 1), dist(probability) {

The constructor correctly sets is_one = true when probability == 1.0, which causes next() to bypass sampling from the distribution. However, the dist(probability) member initializer still constructs a std::geometric_distribution with p=1.0. Per the C++ standard, std::geometric_distribution requires 0 < p < 1 strictly. When _GLIBCXX_ASSERTIONS is enabled, libstdc++ enforces this precondition and aborts.

In non-assertion builds (e.g., Release mode), the invalid distribution is silently constructed and never sampled (due to the is_one bypass), so the bug is latent.

Suggested Fix

Use a valid placeholder probability when p == 1.0, since the distribution will never be sampled:

 RareErrorIterator::RareErrorIterator(float probability)
-    : next_candidate(0), is_one(probability == 1), dist(probability) {
+    : next_candidate(0), is_one(probability == 1), dist(is_one ? 0.5f : probability) {

This has been verified to fix the failing test.

Affected Tests

  • stim_NoiseTest.checkBitFlipTypeSimple (crashes)
  • Potentially any noise test where a Kraus channel produces an effective error probability of exactly 1.0

Environment

  • GCC 11 with libstdc++ (_GLIBCXX_ASSERTIONS enabled)
  • Stim version bundled in tpls/Stim/

Steps to reproduce the bug

n/a

Expected behavior

n/a

Is this a regression? If it is, put the last known working version (or commit) here.

Not a regression

Environment

n/a

Suggestions

n/a

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