Skip to content

Fix: guard addJitter against zero/sub-nanosecond durations to prevent panic (fixes #8149)#8178

Merged
yurishkuro merged 2 commits into
jaegertracing:mainfrom
shivamtiwari3:fix/addjitter-panic-on-zero-duration
Mar 16, 2026
Merged

Fix: guard addJitter against zero/sub-nanosecond durations to prevent panic (fixes #8149)#8178
yurishkuro merged 2 commits into
jaegertracing:mainfrom
shivamtiwari3:fix/addjitter-panic-on-zero-duration

Conversation

@shivamtiwari3
Copy link
Copy Markdown
Contributor

Summary

Fixes #8149.

addJitter in internal/sampling/samplingstrategy/adaptive/post_aggregator.go passed int64(jitterAmount/2) directly to rand.Int63n. When jitterAmount is 0 or 1ns, integer division yields 0, and rand.Int63n(0) panics at runtime with panic: invalid argument to Int63n.


Root Cause

In post_aggregator.go:145:

func addJitter(jitterAmount time.Duration) time.Duration {
    return (jitterAmount / 2) + time.Duration(rand.Int63n(int64(jitterAmount/2)))
}

rand.Int63n(n) requires n > 0; it panics otherwise. No guard prevented calling it with n == 0. A misconfigured FollowerLeaseRefreshInterval (e.g. set to 0 or 1ns in a YAML config or test environment) or an unexpected zero value reaching addJitter from provider.go:92 would crash the process.


Solution

Compute half = jitterAmount / 2 once. If half <= 0 (covers jitterAmount == 0 and jitterAmount == 1ns), return jitterAmount unchanged — no jitter is added, but the caller is not panicked. Otherwise apply the existing formula using half.

func addJitter(jitterAmount time.Duration) time.Duration {
    half := jitterAmount / 2
    if half <= 0 {
        return jitterAmount
    }
    return half + time.Duration(rand.Int63n(int64(half)))
}

Testing

  • Added TestAddJitter in post_aggregator_test.go:
    • addJitter(0) returns 0 without panicking
    • addJitter(1ns) returns 1ns without panicking (sub-nanosecond integer division edge case)
    • For normal durations (2ms, 1s, 20s, 60s): 100 calls each confirm the result is always in [d/2, d)
  • All existing 17 tests in the package continue to pass

Run with:

go test ./internal/sampling/samplingstrategy/adaptive/...

Checklist

  • Fixes the root cause (not just the symptom)
  • New test covers the exact failing scenarios from the bug report
  • All existing tests pass
  • No unrelated changes
  • Code style matches project conventions
  • Read CONTRIBUTING.md and followed its requirements

@shivamtiwari3 shivamtiwari3 requested a review from a team as a code owner March 15, 2026 15:39
Copilot AI review requested due to automatic review settings March 15, 2026 15:39
@shivamtiwari3 shivamtiwari3 force-pushed the fix/addjitter-panic-on-zero-duration branch 2 times, most recently from 49d6ecb to a97fc99 Compare March 15, 2026 15:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prevents a runtime panic in adaptive sampling’s jitter calculation by guarding rand.Int63n against zero (or sub-nanosecond truncation to zero) bounds, and adds unit tests to cover the edge cases reported in #8149.

Changes:

  • Add a half := jitterAmount / 2 guard in addJitter to avoid rand.Int63n(0) panics.
  • Add TestAddJitter to validate zero/1ns inputs and ensure typical durations stay within expected bounds.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
internal/sampling/samplingstrategy/adaptive/post_aggregator.go Adds a small-duration guard to prevent rand.Int63n panic in addJitter.
internal/sampling/samplingstrategy/adaptive/post_aggregator_test.go Adds tests covering the panic scenarios and validating jitter bounds for normal durations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +720 to +723
assert.Equal(t, time.Duration(0), addJitter(0))

// 1ns duration: jitterAmount/2 == 0, must not panic and must return 1ns
assert.Equal(t, time.Duration(1), addJitter(1))
Comment on lines +145 to +149
half := jitterAmount / 2
if half <= 0 {
return jitterAmount
}
return half + time.Duration(rand.Int63n(int64(half)))
shivamtiwari3 added a commit to shivamtiwari3/jaeger that referenced this pull request Mar 16, 2026
…arity

Replace raw time.Duration(0) and time.Duration(1) literals with the
explicit 0*time.Nanosecond and time.Nanosecond constants to make the
intended unit immediately clear to readers.

Per Copilot review suggestion on PR jaegertracing#8178.
@shivamtiwari3
Copy link
Copy Markdown
Contributor Author

Addressed both Copilot review suggestions:

  1. Test constants — Updated TestAddJitter to use 0*time.Nanosecond and time.Nanosecond instead of the raw time.Duration(0)/time.Duration(1) literals so the intended unit is immediately clear.

  2. PR description accuracy — The root-cause text referenced Options.FollowerLeaseRefreshInterval; the actual call site in this repo is p.followerRefreshInterval inside provider.go. Clarified: the bug is triggered whenever the resolved duration passed to addJitter is ≤ 1ns, regardless of which configuration field or code path produces that value. No scope change — the fix stays in addJitter itself.

… panic (fixes jaegertracing#8149)

Root cause: addJitter called rand.Int63n(int64(jitterAmount/2)); when
jitterAmount is 0 or 1ns the integer division yields 0, and rand.Int63n(0)
panics at runtime.

Fix: compute half = jitterAmount/2 once and return jitterAmount unchanged
when half <= 0, so no call to rand.Int63n is made for degenerate inputs.

Signed-off-by: shivamtiwari3 <33183708+shivamtiwari3@users.noreply.github.com>
…arity

Replace raw time.Duration(0) and time.Duration(1) literals with the
explicit 0*time.Nanosecond and time.Nanosecond constants to make the
intended unit immediately clear to readers.

Per Copilot review suggestion on PR jaegertracing#8178.

Signed-off-by: shivamtiwari3 <33183708+shivamtiwari3@users.noreply.github.com>
@shivamtiwari3 shivamtiwari3 force-pushed the fix/addjitter-panic-on-zero-duration branch from 5cc3195 to 31446be Compare March 16, 2026 15:58
@shivamtiwari3
Copy link
Copy Markdown
Contributor Author

Added Signed-off-by to both commits to fix the DCO check. No other changes.

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.67%. Comparing base (ef50c53) to head (31446be).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8178   +/-   ##
=======================================
  Coverage   95.67%   95.67%           
=======================================
  Files         317      317           
  Lines       16747    16750    +3     
=======================================
+ Hits        16023    16026    +3     
  Misses        571      571           
  Partials      153      153           
Flag Coverage Δ
badger_v1 9.05% <ø> (ø)
badger_v2 1.04% <ø> (ø)
cassandra-4.x-v1-manual 13.25% <ø> (ø)
cassandra-4.x-v2-auto 1.03% <ø> (ø)
cassandra-4.x-v2-manual 1.03% <ø> (ø)
cassandra-5.x-v1-manual 13.25% <ø> (ø)
cassandra-5.x-v2-auto 1.03% <ø> (ø)
cassandra-5.x-v2-manual 1.03% <ø> (ø)
clickhouse 1.16% <ø> (ø)
elasticsearch-6.x-v1 16.83% <ø> (+0.23%) ⬆️
elasticsearch-7.x-v1 16.86% <ø> (+0.23%) ⬆️
elasticsearch-8.x-v1 17.01% <ø> (+0.23%) ⬆️
elasticsearch-8.x-v2 1.04% <ø> (ø)
elasticsearch-9.x-v2 1.04% <ø> (ø)
grpc_v1 7.79% <ø> (ø)
grpc_v2 1.04% <ø> (ø)
kafka-3.x-v2 1.04% <ø> (ø)
memory_v2 1.04% <ø> (ø)
opensearch-1.x-v1 16.91% <ø> (+0.23%) ⬆️
opensearch-2.x-v1 16.91% <ø> (+0.23%) ⬆️
opensearch-2.x-v2 1.04% <ø> (ø)
opensearch-3.x-v2 1.04% <ø> (ø)
query 1.04% <ø> (ø)
tailsampling-processor 0.52% <ø> (ø)
unittests 94.36% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@yurishkuro yurishkuro added this pull request to the merge queue Mar 16, 2026
Merged via the queue into jaegertracing:main with commit 6275e86 Mar 16, 2026
68 of 69 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Potential runtime panic in adaptive sampling addJitter function

3 participants