mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-04-27 20:43:43 +03:00
Merge pull request #2974 from wiredfool/webp_leak
Fix memory leak when opening webp files
This commit is contained in:
commit
797d67b9a3
|
@ -1,38 +0,0 @@
|
||||||
from __future__ import division
|
|
||||||
from helper import unittest, PillowTestCase
|
|
||||||
import sys
|
|
||||||
from PIL import Image
|
|
||||||
from io import BytesIO
|
|
||||||
|
|
||||||
# Limits for testing the leak
|
|
||||||
mem_limit = 16 # max increase in MB
|
|
||||||
iterations = 5000
|
|
||||||
test_file = "Tests/images/hopper.webp"
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or MacOS")
|
|
||||||
class TestWebPLeaks(PillowTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
try:
|
|
||||||
from PIL import _webp
|
|
||||||
except ImportError:
|
|
||||||
self.skipTest('WebP support not installed')
|
|
||||||
|
|
||||||
def _get_mem_usage(self):
|
|
||||||
from resource import getpagesize, getrusage, RUSAGE_SELF
|
|
||||||
mem = getrusage(RUSAGE_SELF).ru_maxrss
|
|
||||||
return mem * getpagesize() / 1024 / 1024
|
|
||||||
|
|
||||||
def test_leak_load(self):
|
|
||||||
with open(test_file, 'rb') as f:
|
|
||||||
im_data = f.read()
|
|
||||||
start_mem = self._get_mem_usage()
|
|
||||||
for _ in range(iterations):
|
|
||||||
with Image.open(BytesIO(im_data)) as im:
|
|
||||||
im.load()
|
|
||||||
mem = (self._get_mem_usage() - start_mem)
|
|
||||||
self.assertLess(mem, mem_limit, msg='memory usage limit exceeded')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
25
Tests/test_webp_leaks.py
Normal file
25
Tests/test_webp_leaks.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
from helper import unittest, PillowLeakTestCase
|
||||||
|
from PIL import Image, features
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
test_file = "Tests/images/hopper.webp"
|
||||||
|
|
||||||
|
@unittest.skipUnless(features.check('webp'), "WebP is not installed")
|
||||||
|
class TestWebPLeaks(PillowLeakTestCase):
|
||||||
|
|
||||||
|
mem_limit = 3 * 1024 # kb
|
||||||
|
iterations = 100
|
||||||
|
|
||||||
|
def test_leak_load(self):
|
||||||
|
with open(test_file, 'rb') as f:
|
||||||
|
im_data = f.read()
|
||||||
|
|
||||||
|
def core():
|
||||||
|
with Image.open(BytesIO(im_data)) as im:
|
||||||
|
im.load()
|
||||||
|
|
||||||
|
self._test_leak(core)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -410,6 +410,7 @@ PyObject* _anim_decoder_get_next(PyObject* self, PyObject* args)
|
||||||
uint8_t* buf;
|
uint8_t* buf;
|
||||||
int timestamp;
|
int timestamp;
|
||||||
PyObject* bytes;
|
PyObject* bytes;
|
||||||
|
PyObject* ret;
|
||||||
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject*)self;
|
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject*)self;
|
||||||
|
|
||||||
if (!WebPAnimDecoderGetNext(decp->dec, &buf, ×tamp)) {
|
if (!WebPAnimDecoderGetNext(decp->dec, &buf, ×tamp)) {
|
||||||
|
@ -419,7 +420,11 @@ PyObject* _anim_decoder_get_next(PyObject* self, PyObject* args)
|
||||||
|
|
||||||
bytes = PyBytes_FromStringAndSize((char *)buf,
|
bytes = PyBytes_FromStringAndSize((char *)buf,
|
||||||
decp->info.canvas_width * 4 * decp->info.canvas_height);
|
decp->info.canvas_width * 4 * decp->info.canvas_height);
|
||||||
return Py_BuildValue("Si", bytes, timestamp);
|
|
||||||
|
ret = Py_BuildValue("Si", bytes, timestamp);
|
||||||
|
|
||||||
|
Py_DECREF(bytes);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* _anim_decoder_has_more_frames(PyObject* self, PyObject* args)
|
PyObject* _anim_decoder_has_more_frames(PyObject* self, PyObject* args)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user