Deferred finding D3 from the v0.8.0 review (release ticket #220). Low severity.
Problem
internal/submit/summary.go's SummaryParser.Feed accumulates bytes into p.buf until it sees a \n. The display side caps an oversized tqdm line via displayLineMax (16 MB) in streamDisplayAndParse (watch.go) and drains the rest, but the drained bytes still flow through the TeeReader into SummaryParser.Feed. So a pathological ingestor emitting many MB of \r-redraws with no \n for the life of a (up to 1h JobWatchTimeout) run makes p.buf grow without the display-side cap applying to the parser.
Fix
Cap p.buf growth: when the partial (newline-less) buffered line passes a ceiling, drop it (and the rest of that line, up to the next \n) so the parser has the same bound the display path does. Mirror displayLineMax — they live in the same submit package, so reference it directly to avoid drift (const parserLineMax = displayLineMax).
A real banner line is tens of bytes; newline-less content past 16 MB cannot be one, so dropping it is safe. After the oversized line finally terminates, the parser resumes normally and still parses the closing banner.
Acceptance
p.buf stays bounded (≤ parserLineMax) under a multi-MB newline-less flood.- A real banner arriving after the flood still parses.
- New white-box test in
summary_test.go.
Branch → PR into develop. Rolls up under #220.
Deferred finding D3 from the v0.8.0 review (release ticket #220). Low severity.
Problem
internal/submit/summary.go'sSummaryParser.Feedaccumulates bytes intop.bufuntil it sees a\n. The display side caps an oversized tqdm line viadisplayLineMax(16 MB) instreamDisplayAndParse(watch.go) and drains the rest, but the drained bytes still flow through theTeeReaderintoSummaryParser.Feed. So a pathological ingestor emitting many MB of\r-redraws with no\nfor the life of a (up to 1hJobWatchTimeout) run makesp.bufgrow without the display-side cap applying to the parser.Fix
Cap
p.bufgrowth: when the partial (newline-less) buffered line passes a ceiling, drop it (and the rest of that line, up to the next\n) so the parser has the same bound the display path does. MirrordisplayLineMax— they live in the samesubmitpackage, so reference it directly to avoid drift (const parserLineMax = displayLineMax).A real banner line is tens of bytes; newline-less content past 16 MB cannot be one, so dropping it is safe. After the oversized line finally terminates, the parser resumes normally and still parses the closing banner.
Acceptance
p.bufstays bounded (≤parserLineMax) under a multi-MB newline-less flood.summary_test.go.Branch → PR into
develop. Rolls up under #220.