Skip to content

mcpx(settings): ParseBytes accepts non-finite spellings — NaN/Inf (bare and suffixed) validate as MinInt64, a residual #1697's sign/range checks do not catch #3521

Closed

Description

@dezren39

Summary

settings.ParseBytes (pkgs/mcpx/internal/settings/value.go:450) accepts the non-finite float spellings NaN and Inf — bare and with size suffixes (NaNMB, InfGB) — and converts them to math.MinInt64 (-9223372036854775808) with no error. Validate's KindBytes branch (value.go:510-513) accepts anything ParseBytes does not error on, so a KindBytes setting (e.g. http.streamBufferInit, http.bodyLimit, artifacts.quota, logging.maxBytes) can be applied at any layer (file/env/flag/preset/runtime) with the value NaN and every reader then sees the most negative int64 there is.

This is a residual of #1697 (byte sizes accept negatives and int64 overflow), not a duplicate of it: #1697's acceptance pins refusing "negative results and magnitudes that do not fit in an int64". NaN is neither — every comparison against NaN is false, so a fix that adds the obvious sign/range checks (f < 0, f * mult > MaxInt64) still admits NaN (and a > MaxInt64 check alone admits +Inf spellings only via the conversion, not via the check). The non-finite spellings need an explicit math.IsNaN / math.IsInf rejection, and regression tests that name them.

Evidence (verified this run, main 74bf342)

Line trace, pkgs/mcpx/internal/settings/value.go:

  • ParseBytes (:450-479) strips a suffix, then strconv.ParseFloat(v, 64) + int64(f * float64(mult)) with no finiteness check. Go's ParseFloat accepts NaN, nan, Inf, +Inf, Infinity (case-insensitive); converting a non-finite float to int64 yields math.MinInt64 on amd64/arm64.
  • Validate KindBytes case (:510-513) returns an error only when ParseBytes errors — so the values above are valid settings. Set.Bytes() (:325) discards the parse error the same way.
  • Consumers spend the result as in mcpx(settings): byte sizes accept negatives and int64 overflow — http.streamBufferInit=-1 passes validation, then panics the CLI with 'makeslice: cap out of range' at the first streaming read #1697: make([]byte, 0, set.Bytes("http.streamBufferInit")) (internal/cli/opcmd.go:557-558, internal/cli/client.go:1238) panics on the negative cap; http.MaxBytesReader with a negative limit (internal/daemon/routes_secrets.go:49,114 and the other http.bodyLimit call sites, whose bodyBytes helper at internal/daemon/server.go:1196 does not guard <= 0 either) rejects every request body; guarded consumers (artifacts Quota <= 0 = no ceiling, internal/artifacts/artifacts.go:483; logging maxBytes <= 0 = default, internal/logging/file.go:86) silently reinterpret a configured cap as no cap / default.

Laptop probe (real ParseBytes extracted verbatim from internal/settings/value.go; the laptop clone's file is md5-identical to sandbox main, b55906a4286878d8897d1e60300e0f5c; probe + logs at ~/git/fleet/probe-2026-11-01-laneA-parsebytes/ on the laptop):

"16MB"                     -> 16000000 err=<nil> validateAccepts=true   (control)
"64KiB"                    -> 65536 err=<nil> validateAccepts=true      (control)
"banana"                   -> 0 err=not a size: "banana" validateAccepts=false  (control)
"1e999"                    -> 0 err=not a size: "1e999" validateAccepts=false   (ParseFloat range error — correctly refused)
"NaN"                      -> -9223372036854775808 err=<nil> validateAccepts=true
"nan"                      -> -9223372036854775808 err=<nil> validateAccepts=true
"Inf"                      -> -9223372036854775808 err=<nil> validateAccepts=true
"+Inf"                     -> -9223372036854775808 err=<nil> validateAccepts=true
"NaNMB"                    -> -9223372036854775808 err=<nil> validateAccepts=true
"InfGB"                    -> -9223372036854775808 err=<nil> validateAccepts=true

Note the contrast the probe pins: 1e999 is refused because ParseFloat itself range-errors, while the named non-finite spellings sail through the same parser — the hole is specifically the non-finite names, not float parsing in general.

Why it matters

The settings system is the choke point whose job is keeping an invalid value out of a running process. A generated or fat-fingered config carrying NaN (a spelling JSON-adjacent tooling and template engines readily emit for "unknown") currently validates cleanly and then either crashes the CLI at the first streaming read, makes the daemon reject every request body, or silently uncaps a store quota the operator believed was set — the same three failure shapes as #1697, reachable through a spelling its fix does not obviously cover.

Acceptance criteria

Notes for triage

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    on Nov 1, 2026
  2. developing-today commented on Nov 1, 2026

    @developing-today
    Contributor
  3. added
    priority/lowNice to have; do when convenient
    queue/queuedHas a queued task in the Supabase agent queue
    app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Nov 1, 2026
  4. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  5. added
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 2, 2026
  6. 25 remaining items

  7. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Nov 3, 2026
  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: picked-up
    task: 6147 (repo-health-code-pilot, repo-worker-code; lane 9aca43b4-5439-4939-9f71-323f5d32521b)
    state: claimed (resume of parked task); prior work intact
    verified: Fresh 2026-11-03T08:28Z: branch queue/6147-3521-parsebytes-nonfinite @ 8643e8a exists in /home/user/git/fleet/6147-3521-parsebytes-nonfinite (clean); PR #4788 OPEN; diff matches packet scope (explicit math.IsNaN/IsInf guard + extended test tables). CI so far: line-limit pass + CodeRabbit skipping; Go test workflows not yet reporting.
    next: Run targeted go tests locally; read CI fresh; merge if green, else park.

  9. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 3, 2026
  10. added a commit that references this issue on Nov 3, 2026
  11. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: done
    task: 6147 (repo-health-code-pilot, repo-worker-code; lane 9aca43b4-5439-4939-9f71-323f5d32521b)
    state: MERGED — PR #4788 merged as eeb8764 (2026-11-03T08:24Z); issue closed by merge; merge commit on origin/main verified.
    tests: Targeted go test ./internal/settings/ -run TestParseBytes|TestByteSizes|TestValidate PASS in worktree; full settings package shows only the 5 pre-existing clean-main failures (TestEveryDocumentHasAChapter, TestEverySettingHasAnEffectProbeOrAnExemption, TestNoUndeclaredEnvRead, TestTheEnvironmentDocIsCurrent, TestTheScriptEnvironmentIsWhatTheCodeSets) proven identical on pristine origin/main worktree. CI on PR: production line-limit pass; mergeStateStatus CLEAN at merge.
    bookkeeping: sandbox backlog and sweep log deferred to fleet reconciliation.

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

Metadata

Metadata

Assignees

Labels

app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientsource/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions