Skip to content

Commit 500a238

Browse files
authored
Fix Unpacker max_buffer_length handling (#506)
1 parent b75e341 commit 500a238

File tree

3 files changed

+24
-17
lines changed

3 files changed

+24
-17
lines changed

msgpack/_unpacker.pyx

+12-16
Original file line numberDiff line numberDiff line change
@@ -440,34 +440,30 @@ cdef class Unpacker(object):
440440
self.buf_size = buf_size
441441
self.buf_tail = tail + _buf_len
442442

443-
cdef read_from_file(self):
444-
next_bytes = self.file_like_read(
445-
min(self.read_size,
446-
self.max_buffer_size - (self.buf_tail - self.buf_head)
447-
))
443+
cdef int read_from_file(self) except -1:
444+
cdef Py_ssize_t remains = self.max_buffer_size - (self.buf_tail - self.buf_head)
445+
if remains <= 0:
446+
raise BufferFull
447+
448+
next_bytes = self.file_like_read(min(self.read_size, remains))
448449
if next_bytes:
449450
self.append_buffer(PyBytes_AsString(next_bytes), PyBytes_Size(next_bytes))
450451
else:
451452
self.file_like = None
453+
return 0
452454

453455
cdef object _unpack(self, execute_fn execute, bint iter=0):
454456
cdef int ret
455457
cdef object obj
456458
cdef Py_ssize_t prev_head
457459

458-
if self.buf_head >= self.buf_tail and self.file_like is not None:
459-
self.read_from_file()
460-
461460
while 1:
462461
prev_head = self.buf_head
463-
if prev_head >= self.buf_tail:
464-
if iter:
465-
raise StopIteration("No more data to unpack.")
466-
else:
467-
raise OutOfData("No more data to unpack.")
468-
469-
ret = execute(&self.ctx, self.buf, self.buf_tail, &self.buf_head)
470-
self.stream_offset += self.buf_head - prev_head
462+
if prev_head < self.buf_tail:
463+
ret = execute(&self.ctx, self.buf, self.buf_tail, &self.buf_head)
464+
self.stream_offset += self.buf_head - prev_head
465+
else:
466+
ret = 0
471467

472468
if ret == 1:
473469
obj = unpack_data(&self.ctx)

msgpack/fallback.py

+2
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ def _reserve(self, n, raise_outofdata=True):
423423

424424
# Read from file
425425
remain_bytes = -remain_bytes
426+
if remain_bytes + len(self._buffer) > self._max_buffer_size:
427+
raise BufferFull
426428
while remain_bytes > 0:
427429
to_read_bytes = max(self._read_size, remain_bytes)
428430
read_data = self.file_like.read(to_read_bytes)

test/test_sequnpack.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# coding: utf-8
33
import io
44
from msgpack import Unpacker, BufferFull
5-
from msgpack import pack
5+
from msgpack import pack, packb
66
from msgpack.exceptions import OutOfData
77
from pytest import raises
88

@@ -78,6 +78,15 @@ def test_maxbuffersize():
7878
assert ord("b") == next(unpacker)
7979

8080

81+
def test_maxbuffersize_file():
82+
buff = io.BytesIO(packb(b"a" * 10) + packb([b"a" * 20] * 2))
83+
unpacker = Unpacker(buff, read_size=1, max_buffer_size=19, max_bin_len=20)
84+
assert unpacker.unpack() == b"a" * 10
85+
# assert unpacker.unpack() == [b"a" * 20]*2
86+
with raises(BufferFull):
87+
print(unpacker.unpack())
88+
89+
8190
def test_readbytes():
8291
unpacker = Unpacker(read_size=3)
8392
unpacker.feed(b"foobar")

0 commit comments

Comments
 (0)