diff --git a/CHANGELOG.md b/CHANGELOG.md index d628d852..47c6d464 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## [Unreleased] +### Fix +- Fix memory bloat in some cases. ## [3.7.0] - 2022-07-27 ### Add diff --git a/bufpool/bufpool.go b/bufpool/bufpool.go index c9698af1..b8f378eb 100644 --- a/bufpool/bufpool.go +++ b/bufpool/bufpool.go @@ -73,7 +73,7 @@ func (p *Pool) calibrateAndClean() { metrics.SetBufferMaxSize(p.name, p.maxSize) } -func (p *Pool) Get(size int) *bytes.Buffer { +func (p *Pool) Get(size int, grow bool) *bytes.Buffer { p.mutex.Lock() defer p.mutex.Unlock() @@ -115,7 +115,10 @@ func (p *Pool) Get(size int) *bytes.Buffer { buf.Reset() - growSize := imath.Max(size, p.defaultSize) + growSize := p.defaultSize + if grow { + growSize = imath.Max(size, growSize) + } if growSize > buf.Cap() { buf.Grow(growSize) @@ -145,7 +148,7 @@ func (p *Pool) Put(buf *bytes.Buffer) { if b == nil { p.buffers[i] = buf - if buf.Cap() > 0 { + if buf.Len() > 0 { metrics.ObserveBufferSize(p.name, buf.Cap()) } diff --git a/imagedata/read.go b/imagedata/read.go index 818a0bdd..24bbcd99 100644 --- a/imagedata/read.go +++ b/imagedata/read.go @@ -44,7 +44,7 @@ func readAndCheckImage(r io.Reader, contentLength int) (*ImageData, error) { return nil, ErrSourceFileTooBig } - buf := downloadBufPool.Get(contentLength) + buf := downloadBufPool.Get(contentLength, false) cancel := func() { downloadBufPool.Put(buf) } if config.MaxSrcFileSize > 0 { @@ -54,17 +54,27 @@ func readAndCheckImage(r io.Reader, contentLength int) (*ImageData, error) { br := bufreader.New(r, buf) meta, err := imagemeta.DecodeMeta(br) - if err == imagemeta.ErrFormat { - return nil, ErrSourceImageTypeNotSupported - } if err != nil { + buf.Reset() + cancel() + + if err == imagemeta.ErrFormat { + return nil, ErrSourceImageTypeNotSupported + } + return nil, checkTimeoutErr(err) } if err = security.CheckDimensions(meta.Width(), meta.Height()); err != nil { + buf.Reset() + cancel() return nil, err } + if contentLength > buf.Cap() { + buf.Grow(contentLength - buf.Len()) + } + if err = br.Flush(); err != nil { cancel() return nil, checkTimeoutErr(err)