Summary
buf curl's documented combined "headers, blank line, body" file format fails with unexpected EOF when the file has CRLF line endings — the Windows default — because the blank separator line is never recognized. A separator line containing only whitespace fails the same way on any OS. For Windows users this documented feature is effectively 100% broken.
Reproduction
printf 'x-token: abc\r\n\r\n{"name":"foo"}\r\n' > req_crlf.txt
buf curl --http2-prior-knowledge -H @req_crlf.txt -d @req_crlf.txt http://127.0.0.1:9/foo.v1.FooService/Bar
# Failure: req_crlf.txt: unexpected EOF
The same content with LF endings parses fine (verified: it proceeds past file parsing to schema resolution).
Root cause
private/buf/bufcurl/headers.go:133-151 — lineReader.ReadLine strips only \n, so in a CRLF file the separator line arrives as "\r". The blank-line/body check compares raw while the very next check trims:
if line == "" && stopAtBlankLine { // "\r" fails this...
... return body reader ...
}
line = strings.TrimSpace(line)
if strings.TrimSpace(line) == "" || strings.HasPrefix(line, "#") {
continue // ...but is skipped here as an ignorable blank
}
So the separator is swallowed, the loop consumes the JSON body as headers, and EOF triggers io.ErrUnexpectedEOF (headers.go:135-138).
Expected
The separator check should tolerate \r/whitespace (trim before comparing, or strip \r in ReadLine), making CRLF files work like LF files.
Found via a full mutest (mutation-testing) run over this repo; verified manually with an LF/CRLF differential against a local build.
Summary
buf curl's documented combined "headers, blank line, body" file format fails withunexpected EOFwhen the file has CRLF line endings — the Windows default — because the blank separator line is never recognized. A separator line containing only whitespace fails the same way on any OS. For Windows users this documented feature is effectively 100% broken.Reproduction
The same content with LF endings parses fine (verified: it proceeds past file parsing to schema resolution).
Root cause
private/buf/bufcurl/headers.go:133-151—lineReader.ReadLinestrips only\n, so in a CRLF file the separator line arrives as"\r". The blank-line/body check compares raw while the very next check trims:So the separator is swallowed, the loop consumes the JSON body as headers, and EOF triggers
io.ErrUnexpectedEOF(headers.go:135-138).Expected
The separator check should tolerate
\r/whitespace (trim before comparing, or strip\rinReadLine), making CRLF files work like LF files.Found via a full mutest (mutation-testing) run over this repo; verified manually with an LF/CRLF differential against a local build.