Skip to content

Commit

Permalink
fix: fix memory leak on failed http requests
Browse files Browse the repository at this point in the history
In many error cases the http response body was not closed as the `defer` statement was only executed after the error handling.

Thus the connection can't be reused. This caused the creation of many goroutines, massively increasing the memory consumption. A prominent scenario is if a CSAF provider does not provide both sha256 and sha512 checksums.
  • Loading branch information
mgoetzegb committed Mar 11, 2025
1 parent 3e16741 commit 91b33cf
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions cmd/csaf_downloader/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,15 @@ nextAdvisory:
"error", err)
continue
}
responseBody, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
stats.downloadFailed++
slog.Warn("Cannot read response body",
"url", file.URL(),
"error", err)
continue
}

if resp.StatusCode != http.StatusOK {
stats.downloadFailed++
Expand Down Expand Up @@ -556,8 +565,7 @@ nextAdvisory:
var doc any

if err := func() error {
defer resp.Body.Close()
tee := io.TeeReader(resp.Body, hasher)
tee := io.TeeReader(bytes.NewReader(responseBody), hasher)
return json.NewDecoder(tee).Decode(&doc)
}(); err != nil {
stats.downloadFailed++
Expand Down Expand Up @@ -758,11 +766,11 @@ func loadSignature(client util.Client, p string) (*crypto.PGPSignature, []byte,
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, nil, fmt.Errorf(
"fetching signature from '%s' failed: %s (%d)", p, resp.Status, resp.StatusCode)
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, nil, err
Expand Down Expand Up @@ -823,11 +831,11 @@ func loadHash(client util.Client, p string) ([]byte, []byte, error) {
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, nil, fmt.Errorf(
"fetching hash from '%s' failed: %s (%d)", p, resp.Status, resp.StatusCode)
}
defer resp.Body.Close()
var data bytes.Buffer
tee := io.TeeReader(resp.Body, &data)
hash, err := util.HashFromReader(tee)
Expand Down

0 comments on commit 91b33cf

Please sign in to comment.