net/http: fix nil didTimeout deref when a client dial fails

Client.do calls didTimeout() on the error path (line 461), and the contract is
that send() returns a non-nil didTimeout whenever err != nil. TinyGo dropped
setRequestCancel but left the roundTrip error path returning the nil named
return value, so any http.Client{Timeout: ...} request whose dial failed (e.g.
connection refused) panicked with a nil func-value dereference instead of
returning the error. Return alwaysFalse on those error paths, matching the
other error returns in send().

Verified: http.Client{Timeout}.Get to a refused port now returns
"connection refused" instead of panicking.
This commit is contained in:
Moses Narrow
2026-07-14 19:34:14 -05:00
committed by Ron Evans
parent e75c5f0526
commit 70037cf71f
+6 -2
View File
@@ -213,10 +213,14 @@ func send(req *Request, deadline time.Time) (resp *Response, didTimeout func() b
// TINYGO: Remove TLS error check // TINYGO: Remove TLS error check
return nil, didTimeout, err // didTimeout must be non-nil whenever err != nil: c.do calls
// didTimeout() on the error path. The named return is nil here (TinyGo
// dropped setRequestCancel), so return alwaysFalse instead to avoid a
// nil func-value dereference on a failed dial.
return nil, alwaysFalse, err
} }
if resp == nil { if resp == nil {
return nil, didTimeout, fmt.Errorf("http: sendit returned a nil *Response with a nil error") return nil, alwaysFalse, fmt.Errorf("http: sendit returned a nil *Response with a nil error")
} }
// TINYGO: Skip check for resp.Body == nil since we'll set it in roundTrip // TINYGO: Skip check for resp.Body == nil since we'll set it in roundTrip