From 3f2b094bead0d8fb0ecc034c15856cddf50a237c Mon Sep 17 00:00:00 2001 From: Gabor Szabad <3198500+ubiuser@users.noreply.github.com> Date: Fri, 9 Oct 2026 09:43:43 +0100 Subject: [PATCH] Add consumer support for gzip.NewReader --- README.md | 1 + passes/bodyclose/bodyclose.go | 3 ++- .../testdata/src/consumption/consumption.go | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ed5909a..19aecf5 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ When `-check-consumption` is enabled, the following patterns are recognized as v - `json.NewDecoder(resp.Body)` - `bufio.NewScanner(resp.Body)` - `bufio.NewReader(resp.Body)` +- `gzip.NewReader(resp.Body)` ##### Limitations and False Positives diff --git a/passes/bodyclose/bodyclose.go b/passes/bodyclose/bodyclose.go index 2a2eaa8..cf95a06 100644 --- a/passes/bodyclose/bodyclose.go +++ b/passes/bodyclose/bodyclose.go @@ -455,7 +455,8 @@ func (r *runner) isConsumptionFunction(call *ssa.Call) bool { if (pkg == "io" && (name == "Copy" || name == "ReadAll")) || (pkg == "io/ioutil" && name == "ReadAll") || (pkg == "encoding/json" && name == "NewDecoder") || - (pkg == "bufio" && (name == "NewScanner" || name == "NewReader")) { + (pkg == "bufio" && (name == "NewScanner" || name == "NewReader")) || + (pkg == "compress/gzip" && name == "NewReader") { return true } } diff --git a/passes/bodyclose/testdata/src/consumption/consumption.go b/passes/bodyclose/testdata/src/consumption/consumption.go index 30d2eb9..1eace12 100644 --- a/passes/bodyclose/testdata/src/consumption/consumption.go +++ b/passes/bodyclose/testdata/src/consumption/consumption.go @@ -2,6 +2,7 @@ package consumption import ( "bufio" + "compress/gzip" "encoding/json" "io" "io/ioutil" @@ -80,6 +81,22 @@ func consumedWithBufioReader() { _, _, _ = reader.ReadLine() } +// Pattern 7: gzip.NewReader +func consumedWithGzipReader() { + resp, err := http.Get("http://example.com/") // OK - gzip.NewReader detected + if err != nil { + return + } + defer resp.Body.Close() + + reader, err := gzip.NewReader(resp.Body) + if err != nil { + return + } + + reader.Close() +} + // Pattern 7: Helper function with known consumption func consumedInHelper() { resp, err := http.Get("http://example.com/") // OK - helper uses io.Copy