Skip to content

fix(dogstatsd): reject tag_length.end() <= MIN_TAG_LENGTH upfront#1875

Open
blt wants to merge 1 commit into
mainfrom
blt/fix-dogstatsd-tag-length-wrapper-underflow
Open

fix(dogstatsd): reject tag_length.end() <= MIN_TAG_LENGTH upfront#1875
blt wants to merge 1 commit into
mainfrom
blt/fix-dogstatsd-tag-length-wrapper-underflow

Conversation

@blt
Copy link
Copy Markdown
Collaborator

@blt blt commented May 16, 2026

Summary

The dogstatsd::common::tags::Generator wrapper subtracts one from tag_length.end() to account for the on-wire : separator, then forwards the adjusted range to common::tags::Generator. The inner generator requires start() >= MIN_TAG_LENGTH = 3. When the caller's tag_length.end() equalled MIN_TAG_LENGTH -- e.g. ConfRange::Constant(3) or ConfRange::Inclusive { min: 3, max: 3 } -- the wrapper produced Inclusive { min: 3, max: 2 }. The inner then rejected the range on min <= max and the failure bubbled up as Error::StringGenerate, which drops the underlying message and points callers at pool generation rather than at the tag-length range that was actually at fault.

This change validates the constraint at the wrapper entrypoint and returns a dedicated Error::TagLengthEndTooSmall variant naming the offending value and the minimum required. The wrapper docstring is updated to record the post-adjust end > MIN_TAG_LENGTH contract.

Discovered while fuzzing DogStatsD::new from an external rig: the symptom was a StringGenerate failure at specific seeds, with no indication that the actual root cause was the configured tag-length range collapsing to its lower bound.

Test plan

  • cargo test -p lading-payload -- 211 tests pass including three new wrapper tests (tag_length_constant_at_min_rejected, tag_length_inclusive_min_equals_max_at_min_rejected, tag_length_at_min_plus_one_accepted).
  • cargo clippy -p lading-payload --all-targets -- clean.
  • CHANGELOG entry added under Unreleased.

The dogstatsd `common::tags::Generator` wrapper subtracts one from
`tag_length.end()` to account for the on-wire `:` separator before
forwarding to the inner generator. The inner generator requires
`start() >= MIN_TAG_LENGTH = 3`. When the caller's `tag_length.end()`
equalled `MIN_TAG_LENGTH` -- e.g. `Constant(3)` or `Inclusive { 3, 3 }` --
the wrapper produced `Inclusive { 3, 2 }` and the inner rejected it on
`min <= max`. That rejection surfaced upstream as `Error::StringGenerate`,
which dropped the underlying message and pointed callers at pool
generation rather than the config range that was actually at fault.

Validate the constraint at the wrapper entrypoint and return a dedicated
`Error::TagLengthEndTooSmall` variant naming the offending value and the
minimum required. Tests cover both the rejection cases and the smallest
accepted `end` value.
@blt blt requested a review from a team as a code owner May 16, 2026 00:38
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.

1 participant