doWithMaxSize behaves like Do but caps the size of the decompressed payload at maxMessageSize+1 bytes. The Decompressor interface does not allow extra parameters, so callers inside the package type-assert to *gzipDecompressor to invoke this method directly. The +1 byte makes it possible for the call
(r io.Reader, maxMessageSize int64)
| 138 | // possible for the caller to detect that the limit was exceeded and |
| 139 | // return ResourceExhausted instead of materializing an unbounded payload. |
| 140 | func (d *gzipDecompressor) doWithMaxSize(r io.Reader, maxMessageSize int64) ([]byte, error) { |
| 141 | var z *gzip.Reader |
| 142 | switch maybeZ := d.pool.Get().(type) { |
| 143 | case nil: |
| 144 | newZ, err := gzip.NewReader(r) |
| 145 | if err != nil { |
| 146 | return nil, err |
| 147 | } |
| 148 | z = newZ |
| 149 | case *gzip.Reader: |
| 150 | z = maybeZ |
| 151 | if err := z.Reset(r); err != nil { |
| 152 | d.pool.Put(z) |
| 153 | return nil, err |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | defer func() { |
| 158 | z.Close() |
| 159 | d.pool.Put(z) |
| 160 | }() |
| 161 | var src io.Reader = z |
| 162 | if maxMessageSize < math.MaxInt64 { |
| 163 | src = io.LimitReader(z, maxMessageSize+1) |
| 164 | } |
| 165 | return io.ReadAll(src) |
| 166 | } |
| 167 | |
| 168 | func (d *gzipDecompressor) Type() string { |
| 169 | return "gzip" |