msgpack pack and unpack throws only exception that inherit from MsgpackBaseException. cython and fallback throws same exceptions

This commit is contained in:
palaviv 2016-02-12 11:00:39 +02:00
parent 82b3121507
commit 7d2d46effc
4 changed files with 71 additions and 52 deletions

View file

@ -6,7 +6,7 @@ from libc.stdlib cimport *
from libc.string cimport * from libc.string cimport *
from libc.limits cimport * from libc.limits cimport *
from msgpack.exceptions import PackValueError from msgpack.exceptions import PackValueError, PackOverflowError
from msgpack import ExtType from msgpack import ExtType
@ -166,7 +166,7 @@ cdef class Packer(object):
default_used = True default_used = True
continue continue
else: else:
raise raise PackOverflowError("Integer value out of range")
elif PyInt_CheckExact(o) if strict_types else PyInt_Check(o): elif PyInt_CheckExact(o) if strict_types else PyInt_Check(o):
longval = o longval = o
ret = msgpack_pack_long(&self.pk, longval) ret = msgpack_pack_long(&self.pk, longval)
@ -180,7 +180,7 @@ cdef class Packer(object):
elif PyBytes_CheckExact(o) if strict_types else PyBytes_Check(o): elif PyBytes_CheckExact(o) if strict_types else PyBytes_Check(o):
L = len(o) L = len(o)
if L > (2**32)-1: if L > (2**32)-1:
raise ValueError("bytes is too large") raise PackValueError("bytes is too large")
rawval = o rawval = o
ret = msgpack_pack_bin(&self.pk, L) ret = msgpack_pack_bin(&self.pk, L)
if ret == 0: if ret == 0:
@ -191,7 +191,7 @@ cdef class Packer(object):
o = PyUnicode_AsEncodedString(o, self.encoding, self.unicode_errors) o = PyUnicode_AsEncodedString(o, self.encoding, self.unicode_errors)
L = len(o) L = len(o)
if L > (2**32)-1: if L > (2**32)-1:
raise ValueError("unicode string is too large") raise PackValueError("unicode string is too large")
rawval = o rawval = o
ret = msgpack_pack_raw(&self.pk, L) ret = msgpack_pack_raw(&self.pk, L)
if ret == 0: if ret == 0:
@ -211,7 +211,7 @@ cdef class Packer(object):
elif not strict_types and PyDict_Check(o): elif not strict_types and PyDict_Check(o):
L = len(o) L = len(o)
if L > (2**32)-1: if L > (2**32)-1:
raise ValueError("dict is too large") raise PackValueError("dict is too large")
ret = msgpack_pack_map(&self.pk, L) ret = msgpack_pack_map(&self.pk, L)
if ret == 0: if ret == 0:
for k, v in o.items(): for k, v in o.items():
@ -225,13 +225,13 @@ cdef class Packer(object):
rawval = o.data rawval = o.data
L = len(o.data) L = len(o.data)
if L > (2**32)-1: if L > (2**32)-1:
raise ValueError("EXT data is too large") raise PackValueError("EXT data is too large")
ret = msgpack_pack_ext(&self.pk, longval, L) ret = msgpack_pack_ext(&self.pk, longval, L)
ret = msgpack_pack_raw_body(&self.pk, rawval, L) ret = msgpack_pack_raw_body(&self.pk, rawval, L)
elif PyList_CheckExact(o) if strict_types else (PyTuple_Check(o) or PyList_Check(o)): elif PyList_CheckExact(o) if strict_types else (PyTuple_Check(o) or PyList_Check(o)):
L = len(o) L = len(o)
if L > (2**32)-1: if L > (2**32)-1:
raise ValueError("list is too large") raise PackValueError("list is too large")
ret = msgpack_pack_array(&self.pk, L) ret = msgpack_pack_array(&self.pk, L)
if ret == 0: if ret == 0:
for v in o: for v in o:

View file

@ -1,4 +1,8 @@
class UnpackException(Exception): class MsgpackBaseException(Exception):
pass
class UnpackException(MsgpackBaseException):
pass pass
@ -22,8 +26,12 @@ class ExtraData(ValueError):
def __str__(self): def __str__(self):
return "unpack(b) received extra data." return "unpack(b) received extra data."
class PackException(Exception): class PackException(MsgpackBaseException):
pass pass
class PackValueError(PackException, ValueError): class PackValueError(PackException, ValueError):
pass pass
class PackOverflowError(PackValueError, OverflowError):
pass

View file

@ -51,6 +51,7 @@ from msgpack.exceptions import (
OutOfData, OutOfData,
UnpackValueError, UnpackValueError,
PackValueError, PackValueError,
PackOverflowError,
ExtraData) ExtraData)
from msgpack import ExtType from msgpack import ExtType
@ -363,17 +364,17 @@ class Unpacker(object):
obj = self._fb_read(n, write_bytes) obj = self._fb_read(n, write_bytes)
typ = TYPE_RAW typ = TYPE_RAW
if n > self._max_str_len: if n > self._max_str_len:
raise ValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len)
elif b & 0b11110000 == 0b10010000: elif b & 0b11110000 == 0b10010000:
n = b & 0b00001111 n = b & 0b00001111
typ = TYPE_ARRAY typ = TYPE_ARRAY
if n > self._max_array_len: if n > self._max_array_len:
raise ValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len)
elif b & 0b11110000 == 0b10000000: elif b & 0b11110000 == 0b10000000:
n = b & 0b00001111 n = b & 0b00001111
typ = TYPE_MAP typ = TYPE_MAP
if n > self._max_map_len: if n > self._max_map_len:
raise ValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len)
elif b == 0xc0: elif b == 0xc0:
obj = None obj = None
elif b == 0xc2: elif b == 0xc2:
@ -384,37 +385,37 @@ class Unpacker(object):
typ = TYPE_BIN typ = TYPE_BIN
n = struct.unpack("B", self._fb_read(1, write_bytes))[0] n = struct.unpack("B", self._fb_read(1, write_bytes))[0]
if n > self._max_bin_len: if n > self._max_bin_len:
raise ValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) raise UnpackValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len))
obj = self._fb_read(n, write_bytes) obj = self._fb_read(n, write_bytes)
elif b == 0xc5: elif b == 0xc5:
typ = TYPE_BIN typ = TYPE_BIN
n = struct.unpack(">H", self._fb_read(2, write_bytes))[0] n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
if n > self._max_bin_len: if n > self._max_bin_len:
raise ValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) raise UnpackValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len))
obj = self._fb_read(n, write_bytes) obj = self._fb_read(n, write_bytes)
elif b == 0xc6: elif b == 0xc6:
typ = TYPE_BIN typ = TYPE_BIN
n = struct.unpack(">I", self._fb_read(4, write_bytes))[0] n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
if n > self._max_bin_len: if n > self._max_bin_len:
raise ValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) raise UnpackValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len))
obj = self._fb_read(n, write_bytes) obj = self._fb_read(n, write_bytes)
elif b == 0xc7: # ext 8 elif b == 0xc7: # ext 8
typ = TYPE_EXT typ = TYPE_EXT
L, n = struct.unpack('Bb', self._fb_read(2, write_bytes)) L, n = struct.unpack('Bb', self._fb_read(2, write_bytes))
if L > self._max_ext_len: if L > self._max_ext_len:
raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len))
obj = self._fb_read(L, write_bytes) obj = self._fb_read(L, write_bytes)
elif b == 0xc8: # ext 16 elif b == 0xc8: # ext 16
typ = TYPE_EXT typ = TYPE_EXT
L, n = struct.unpack('>Hb', self._fb_read(3, write_bytes)) L, n = struct.unpack('>Hb', self._fb_read(3, write_bytes))
if L > self._max_ext_len: if L > self._max_ext_len:
raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len))
obj = self._fb_read(L, write_bytes) obj = self._fb_read(L, write_bytes)
elif b == 0xc9: # ext 32 elif b == 0xc9: # ext 32
typ = TYPE_EXT typ = TYPE_EXT
L, n = struct.unpack('>Ib', self._fb_read(5, write_bytes)) L, n = struct.unpack('>Ib', self._fb_read(5, write_bytes))
if L > self._max_ext_len: if L > self._max_ext_len:
raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len))
obj = self._fb_read(L, write_bytes) obj = self._fb_read(L, write_bytes)
elif b == 0xca: elif b == 0xca:
obj = struct.unpack(">f", self._fb_read(4, write_bytes))[0] obj = struct.unpack(">f", self._fb_read(4, write_bytes))[0]
@ -439,65 +440,65 @@ class Unpacker(object):
elif b == 0xd4: # fixext 1 elif b == 0xd4: # fixext 1
typ = TYPE_EXT typ = TYPE_EXT
if self._max_ext_len < 1: if self._max_ext_len < 1:
raise ValueError("%s exceeds max_ext_len(%s)" % (1, self._max_ext_len)) raise UnpackValueError("%s exceeds max_ext_len(%s)" % (1, self._max_ext_len))
n, obj = struct.unpack('b1s', self._fb_read(2, write_bytes)) n, obj = struct.unpack('b1s', self._fb_read(2, write_bytes))
elif b == 0xd5: # fixext 2 elif b == 0xd5: # fixext 2
typ = TYPE_EXT typ = TYPE_EXT
if self._max_ext_len < 2: if self._max_ext_len < 2:
raise ValueError("%s exceeds max_ext_len(%s)" % (2, self._max_ext_len)) raise UnpackValueError("%s exceeds max_ext_len(%s)" % (2, self._max_ext_len))
n, obj = struct.unpack('b2s', self._fb_read(3, write_bytes)) n, obj = struct.unpack('b2s', self._fb_read(3, write_bytes))
elif b == 0xd6: # fixext 4 elif b == 0xd6: # fixext 4
typ = TYPE_EXT typ = TYPE_EXT
if self._max_ext_len < 4: if self._max_ext_len < 4:
raise ValueError("%s exceeds max_ext_len(%s)" % (4, self._max_ext_len)) raise UnpackValueError("%s exceeds max_ext_len(%s)" % (4, self._max_ext_len))
n, obj = struct.unpack('b4s', self._fb_read(5, write_bytes)) n, obj = struct.unpack('b4s', self._fb_read(5, write_bytes))
elif b == 0xd7: # fixext 8 elif b == 0xd7: # fixext 8
typ = TYPE_EXT typ = TYPE_EXT
if self._max_ext_len < 8: if self._max_ext_len < 8:
raise ValueError("%s exceeds max_ext_len(%s)" % (8, self._max_ext_len)) raise UnpackValueError("%s exceeds max_ext_len(%s)" % (8, self._max_ext_len))
n, obj = struct.unpack('b8s', self._fb_read(9, write_bytes)) n, obj = struct.unpack('b8s', self._fb_read(9, write_bytes))
elif b == 0xd8: # fixext 16 elif b == 0xd8: # fixext 16
typ = TYPE_EXT typ = TYPE_EXT
if self._max_ext_len < 16: if self._max_ext_len < 16:
raise ValueError("%s exceeds max_ext_len(%s)" % (16, self._max_ext_len)) raise UnpackValueError("%s exceeds max_ext_len(%s)" % (16, self._max_ext_len))
n, obj = struct.unpack('b16s', self._fb_read(17, write_bytes)) n, obj = struct.unpack('b16s', self._fb_read(17, write_bytes))
elif b == 0xd9: elif b == 0xd9:
typ = TYPE_RAW typ = TYPE_RAW
n = struct.unpack("B", self._fb_read(1, write_bytes))[0] n = struct.unpack("B", self._fb_read(1, write_bytes))[0]
if n > self._max_str_len: if n > self._max_str_len:
raise ValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len)
obj = self._fb_read(n, write_bytes) obj = self._fb_read(n, write_bytes)
elif b == 0xda: elif b == 0xda:
typ = TYPE_RAW typ = TYPE_RAW
n = struct.unpack(">H", self._fb_read(2, write_bytes))[0] n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
if n > self._max_str_len: if n > self._max_str_len:
raise ValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len)
obj = self._fb_read(n, write_bytes) obj = self._fb_read(n, write_bytes)
elif b == 0xdb: elif b == 0xdb:
typ = TYPE_RAW typ = TYPE_RAW
n = struct.unpack(">I", self._fb_read(4, write_bytes))[0] n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
if n > self._max_str_len: if n > self._max_str_len:
raise ValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len)
obj = self._fb_read(n, write_bytes) obj = self._fb_read(n, write_bytes)
elif b == 0xdc: elif b == 0xdc:
n = struct.unpack(">H", self._fb_read(2, write_bytes))[0] n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
if n > self._max_array_len: if n > self._max_array_len:
raise ValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len)
typ = TYPE_ARRAY typ = TYPE_ARRAY
elif b == 0xdd: elif b == 0xdd:
n = struct.unpack(">I", self._fb_read(4, write_bytes))[0] n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
if n > self._max_array_len: if n > self._max_array_len:
raise ValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len)
typ = TYPE_ARRAY typ = TYPE_ARRAY
elif b == 0xde: elif b == 0xde:
n = struct.unpack(">H", self._fb_read(2, write_bytes))[0] n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
if n > self._max_map_len: if n > self._max_map_len:
raise ValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len)
typ = TYPE_MAP typ = TYPE_MAP
elif b == 0xdf: elif b == 0xdf:
n = struct.unpack(">I", self._fb_read(4, write_bytes))[0] n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
if n > self._max_map_len: if n > self._max_map_len:
raise ValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len)
typ = TYPE_MAP typ = TYPE_MAP
else: else:
raise UnpackValueError("Unknown header: 0x%x" % b) raise UnpackValueError("Unknown header: 0x%x" % b)
@ -683,7 +684,7 @@ class Packer(object):
obj = self._default(obj) obj = self._default(obj)
default_used = True default_used = True
continue continue
raise PackValueError("Integer value out of range") raise PackOverflowError("Integer value out of range")
if self._use_bin_type and check(obj, (bytes, memoryview)): if self._use_bin_type and check(obj, (bytes, memoryview)):
n = len(obj) n = len(obj)
if n <= 0xff: if n <= 0xff:
@ -778,7 +779,7 @@ class Packer(object):
def pack_array_header(self, n): def pack_array_header(self, n):
if n >= 2**32: if n >= 2**32:
raise ValueError raise PackValueError
self._fb_pack_array_header(n) self._fb_pack_array_header(n)
ret = self._buffer.getvalue() ret = self._buffer.getvalue()
if self._autoreset: if self._autoreset:
@ -789,7 +790,7 @@ class Packer(object):
def pack_map_header(self, n): def pack_map_header(self, n):
if n >= 2**32: if n >= 2**32:
raise ValueError raise PackValueError
self._fb_pack_map_header(n) self._fb_pack_map_header(n)
ret = self._buffer.getvalue() ret = self._buffer.getvalue()
if self._autoreset: if self._autoreset:
@ -807,7 +808,7 @@ class Packer(object):
raise TypeError("data must have bytes type") raise TypeError("data must have bytes type")
L = len(data) L = len(data)
if L > 0xffffffff: if L > 0xffffffff:
raise ValueError("Too large data") raise PackValueError("Too large data")
if L == 1: if L == 1:
self._buffer.write(b'\xd4') self._buffer.write(b'\xd4')
elif L == 2: elif L == 2:

View file

@ -3,36 +3,42 @@
from __future__ import absolute_import, division, print_function, unicode_literals from __future__ import absolute_import, division, print_function, unicode_literals
import pytest import pytest
from msgpack import packb, unpackb, Packer, Unpacker, ExtType from msgpack import packb, unpackb, Packer, Unpacker, ExtType, PackException, PackOverflowError, PackValueError
from msgpack import UnpackValueError, UnpackException, MsgpackBaseException
def test_integer(): @pytest.mark.parametrize("expected_exception", [OverflowError, ValueError, PackOverflowError,
PackException, PackValueError, MsgpackBaseException])
def test_integer(expected_exception):
x = -(2 ** 63) x = -(2 ** 63)
assert unpackb(packb(x)) == x assert unpackb(packb(x)) == x
with pytest.raises((OverflowError, ValueError)): with pytest.raises(expected_exception):
packb(x-1) packb(x-1)
x = 2 ** 64 - 1 x = 2 ** 64 - 1
assert unpackb(packb(x)) == x assert unpackb(packb(x)) == x
with pytest.raises((OverflowError, ValueError)): with pytest.raises(expected_exception):
packb(x+1) packb(x+1)
def test_array_header(): @pytest.mark.parametrize("expected_exception", [ValueError, PackException, PackValueError, MsgpackBaseException])
def test_array_header(expected_exception):
packer = Packer() packer = Packer()
packer.pack_array_header(2**32-1) packer.pack_array_header(2**32-1)
with pytest.raises((OverflowError, ValueError)): with pytest.raises(expected_exception):
packer.pack_array_header(2**32) packer.pack_array_header(2**32)
def test_map_header(): @pytest.mark.parametrize("expected_exception", [ValueError, PackException, PackValueError, MsgpackBaseException])
def test_map_header(expected_exception):
packer = Packer() packer = Packer()
packer.pack_map_header(2**32-1) packer.pack_map_header(2**32-1)
with pytest.raises((OverflowError, ValueError)): with pytest.raises(expected_exception):
packer.pack_array_header(2**32) packer.pack_array_header(2**32)
def test_max_str_len(): @pytest.mark.parametrize("expected_exception", [ValueError, UnpackValueError, UnpackException, MsgpackBaseException])
def test_max_str_len(expected_exception):
d = 'x' * 3 d = 'x' * 3
packed = packb(d) packed = packb(d)
@ -41,12 +47,13 @@ def test_max_str_len():
assert unpacker.unpack() == d assert unpacker.unpack() == d
unpacker = Unpacker(max_str_len=2, encoding='utf-8') unpacker = Unpacker(max_str_len=2, encoding='utf-8')
with pytest.raises(ValueError): with pytest.raises(expected_exception):
unpacker.feed(packed) unpacker.feed(packed)
unpacker.unpack() unpacker.unpack()
def test_max_bin_len(): @pytest.mark.parametrize("expected_exception", [ValueError, UnpackValueError, UnpackException, MsgpackBaseException])
def test_max_bin_len(expected_exception):
d = b'x' * 3 d = b'x' * 3
packed = packb(d, use_bin_type=True) packed = packb(d, use_bin_type=True)
@ -55,12 +62,13 @@ def test_max_bin_len():
assert unpacker.unpack() == d assert unpacker.unpack() == d
unpacker = Unpacker(max_bin_len=2) unpacker = Unpacker(max_bin_len=2)
with pytest.raises(ValueError): with pytest.raises(expected_exception):
unpacker.feed(packed) unpacker.feed(packed)
unpacker.unpack() unpacker.unpack()
def test_max_array_len(): @pytest.mark.parametrize("expected_exception", [ValueError, UnpackValueError, UnpackException, MsgpackBaseException])
def test_max_array_len(expected_exception):
d = [1,2,3] d = [1,2,3]
packed = packb(d) packed = packb(d)
@ -69,12 +77,13 @@ def test_max_array_len():
assert unpacker.unpack() == d assert unpacker.unpack() == d
unpacker = Unpacker(max_array_len=2) unpacker = Unpacker(max_array_len=2)
with pytest.raises(ValueError): with pytest.raises(expected_exception):
unpacker.feed(packed) unpacker.feed(packed)
unpacker.unpack() unpacker.unpack()
def test_max_map_len(): @pytest.mark.parametrize("expected_exception", [ValueError, UnpackValueError, UnpackException, MsgpackBaseException])
def test_max_map_len(expected_exception):
d = {1: 2, 3: 4, 5: 6} d = {1: 2, 3: 4, 5: 6}
packed = packb(d) packed = packb(d)
@ -83,12 +92,13 @@ def test_max_map_len():
assert unpacker.unpack() == d assert unpacker.unpack() == d
unpacker = Unpacker(max_map_len=2) unpacker = Unpacker(max_map_len=2)
with pytest.raises(ValueError): with pytest.raises(expected_exception):
unpacker.feed(packed) unpacker.feed(packed)
unpacker.unpack() unpacker.unpack()
def test_max_ext_len(): @pytest.mark.parametrize("expected_exception", [ValueError, UnpackValueError, UnpackException, MsgpackBaseException])
def test_max_ext_len(expected_exception):
d = ExtType(42, b"abc") d = ExtType(42, b"abc")
packed = packb(d) packed = packb(d)
@ -97,7 +107,7 @@ def test_max_ext_len():
assert unpacker.unpack() == d assert unpacker.unpack() == d
unpacker = Unpacker(max_ext_len=2) unpacker = Unpacker(max_ext_len=2)
with pytest.raises(ValueError): with pytest.raises(expected_exception):
unpacker.feed(packed) unpacker.feed(packed)
unpacker.unpack() unpacker.unpack()