Skip to content

Task scheduler: assert-elided bounds check + div-by-zero in LocalQueue work-stealing registry #611

Closed

Description

@drsnuggles8

Describe the bug
OloEngine/src/OloEngine/Task/LocalQueue.h's lock-free work-stealing scheduler guards two invariants only with OLO_CORE_ASSERT, which compiles to a pure no-op in Dist builds (Core/Assert.h):

  • TLocalQueueRegistry::AddLocalQueue() (~line 369-376): u32 Index = m_NumLocalQueues.fetch_add(1, ...) is bounds-checked only via assert before m_LocalQueues[Index].store(...). In a Dist build, registering more than MaxLocalQueues (1024) queues writes out of the fixed-size m_LocalQueues array — silent out-of-bounds memory corruption, not a crash.
  • TLocalQueueRegistry::StealItem() (~line 380-384): CachedRandomIndex = CachedRandomIndex % NumQueues where NumQueues = m_NumLocalQueues.load(...). There is no guard at all (not even an assert) against NumQueues == 0 — if StealItem is ever reached before any local queue has registered, this is a division-by-zero in every build config, not just Dist.

SonarQube's S3519 independently flags related out-of-bounds-index patterns in the adjacent Task/NamedThreads.h (m_Queues[...]/m_ThreadIds[...], also assert-only-guarded against a fixed ENamedThread::Count array), consistent with the same assert-elided-bounds-check class — worth a quick audit pass alongside the primary fix, though those arrays are indexed by a compile-time-bounded enum so the blast radius there is smaller than the dynamically-growing LocalQueue index.

To Reproduce

  1. In a Dist (or otherwise OLO_CORE_ASSERT-stripped) build, register more than MaxLocalQueues (1024) local queues via TLocalQueueRegistry::AddLocalQueue() — e.g. spin up >1024 task-system worker/local queues.
  2. Observe out-of-bounds write into m_LocalQueues instead of a controlled failure.
  3. Separately: call StealItem() on a registry with zero registered queues (any build config) and observe the % 0 divide-by-zero.

Expected behavior
Both invariants should fail safely (early return / release-mode-safe clamp, or a real runtime check that survives Dist builds) instead of corrupting memory or invoking UB, since this is a hot concurrency primitive used engine-wide by the task scheduler.

Additional context
Found via a signal-hygiene sweep of assert-only bounds checks in concurrency primitives during the 2026-07 feature freeze (Tier 2: latent bugs in concurrency code, per docs/agent-rules/sonarqube-review-alignment.md's guidance that SonarQube reliability noise is mostly false positives but real bugs cluster in concurrency primitives). Scope: OloEngine/src/OloEngine/Task/LocalQueue.h primarily, with a smaller audit pass over NamedThreads.h's equivalent pattern.

Score

capability: 3
craft: 3
stability: 5
decay: 3
effort: 3
confidence: 0.7
learning: 2
fun: 2
kano: table-stakes
blocked_by: []
blocks: []

Rated per issue-scoring · score = confidence × (capability + craft + stability + decay) / effort.

Activity

  1. added
    bugSomething isn't working
    robustnessProduction hardening / shipping robustness
    on Jul 10, 2026
  2. coderabbitai commented on Jul 10, 2026

    @coderabbitai
    Contributor
    🔗 Related PRs

    #93 - Port UE5.7 task system to OloEngine [closed]
    #318 - feat(physics): powered 3D joint motors + friction (hinge/slider) [merged]
    #355 - fix(memory): acquire loads for lock-free allocator page publish/consu… [merged]
    #370 - fix(task): drain standby stack atomically in StartShutdown to fix #35… [merged]
    #400 - fix(net,task): isfinite-guard untrusted float ingestion (network snap… [merged]


    🧪 Issue enrichment is currently in open beta.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  3. drsnuggles8 commented on Jul 10, 2026

    @drsnuggles8
    OwnerAuthor

    Fixed in #614.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrobustnessProduction hardening / shipping robustness

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions