8000 Merge pull request #94 from msgpack/strict-input-check · imclab/msgpack-python@3a9dc1d · GitHub
[go: up one dir, main page]

Skip to content

Commit 3a9dc1d

Browse files
committed
Merge pull request msgpack#94 from msgpack/strict-input-check
Add tests for limits.
2 parents ac4cd06 + a72e75d commit 3a9dc1d

File tree

3 files changed

+92
-4
lines changed

3 files changed

+92
-4
lines changed

msgpack/_packer.pyx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ cdef class Packer(object):
135135
else:
136136
ret = msgpack_pack_false(&self.pk)
137137
elif PyLong_Check(o):
138+
# PyInt_Check(long) is True for Python 3.
139+
# Sow we should test long before int.
138140
if o > 0:
139141
ullval = o
140142
ret = msgpack_pack_unsigned_long_long(&self.pk, ullval)
@@ -152,30 +154,41 @@ cdef class Packer(object):
152154
dval = o
153155
ret = msgpack_pack_double(&self.pk, dval)
154156
elif PyBytes_Check(o):
155-
rawval = o
156157
L = len(o)
158+
if L > (2**32)-1:
159+
raise ValueError("bytes is too large")
160+
rawval = o
157161
ret = msgpack_pack_bin(&self.pk, L)
158162
if ret == 0:
159163
ret = msgpack_pack_raw_body(&self.pk, rawval, L)
160164
elif PyUnicode_Check(o):
161165
if not self.encoding:
162166
raise TypeError("Can't encode unicode string: no encoding is specified")
163167
o = PyUnicode_AsEncodedString(o, self.encoding, self.unicode_errors)
168+
L = len(o)
169+
if L > (2**32)-1:
170+
raise ValueError("dict is too large")
164171
rawval = o
165172
ret = msgpack_pack_raw(&self.pk, len(o))
166173
if ret == 0:
167174
ret = msgpack_pack_raw_body(&self.pk, rawval, len(o))
168175
elif PyDict_CheckExact(o):
169176
d = <dict>o
170-
ret = msgpack_pack_map(&self.pk, len(d))
177+
L = len(d)
178+
if L > (2**32)-1:
179+
raise ValueError("dict is too large")
180+
ret = msgpack_pack_map(&self.pk, L)
171181
if ret == 0:
172182
for k, v in d.iteritems():
173183
ret = self._pack(k, nest_limit-1)
174184
if ret != 0: break
175185
ret = self._pack(v, nest_limit-1)
176186
if ret != 0: break
177187
elif PyDict_Check(o):
178-
ret = msgpack_pack_map(&self.pk, len(o))
188+
L = len(o)
189+
if L > (2**32)-1:
190+
raise ValueError("dict is too large")
191+
ret = msgpack_pack_map(&self.pk, L)
179192
if ret == 0:
180193
for k, v in o.items():
181194
ret = self._pack(k, nest_limit-1)
@@ -187,10 +200,15 @@ cdef class Packer(object):
187200
longval = o.code
188201
rawval = o.data
189202
L = len(o.data)
203+
if L > (2**32)-1:
204+
raise ValueError("EXT data is too large")
190205
ret = msgpack_pack_ext(&self.pk, longval, L)
191206
ret = msgpack_pack_raw_body(&self.pk, rawval, L)
192207
elif PyTuple_Check(o) or PyList_Check(o):
193-
ret = msgpack_pack_array(&self.pk, len(o))
208+
L = len(o)
209+
if L > (2**32)-1:
210+
raise ValueError("list is too large")
211+
ret = msgpack_pack_array(&self.pk, L)
194212
if ret == 0:
195213
for v in o:
196214
ret = self._pack(v, nest_limit-1)
@@ -220,6 +238,8 @@ cdef class Packer(object):
220238
msgpack_pack_raw_body(&self.pk, data, len(data))
221239

222240
def pack_array_header(self, size_t size):
241+
if size > (2**32-1):
242+
raise ValueError
223243
cdef int ret = msgpack_pack_array(&self.pk, size)
224244
if ret == -1:
225245
raise MemoryError
@@ -231,6 +251,8 @@ cdef class Packer(object):
231251
return buf
232252

233253
def pack_map_header(self, size_t size):
254+
if size > (2**32-1):
255+
raise ValueError
234256
cdef int ret = msgpack_pack_map(&self.pk, size)
235257
if ret == -1:
236258
raise MemoryError

msgpack/fallback.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,8 @@ def pack_map_pairs(self, pairs):
633633
return ret
634634

635635
def pack_array_header(self, n):
636+
if n >= 2**32:
637+
raise ValueError
636638
self._fb_pack_array_header(n)
637639
ret = self._buffer.getvalue()
638640
if self._autoreset:
@@ -642,6 +644,8 @@ def pack_array_header(self, n):
642644
return ret
643645

644646
def pack_map_header(self, n):
647+
if n >= 2**32:
648+
raise ValueError
645649
self._fb_pack_map_header(n)
646650
ret = self._buffer.getvalue()
647651
if self._autoreset:

test/test_limits.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
from __future__ import absolute_import, division, print_function, unicode_literals
4+
import pytest
5+
6+
from msgpack import packb, unpackb, Packer
7+
8+
9+
def test_integer():
10+
x = -(2 ** 63)
11+
assert unpackb(packb(x)) == x
12+
with pytest.raises((OverflowError, ValueError)):
13+
packb(x-1)
14+
15+
x = 2 ** 64 - 1
16+
assert unpackb(packb(x)) == x
17+
with pytest.raises((OverflowError, ValueError)):
18+
packb(x+1)
19+
20+
21+
def test_array_header():
22+
packer = Packer()
23+
packer.pack_array_header(2**32-1)
24+
with pytest.raises(ValueError):
25+
packer.pack_array_header(2**32)
26+
27+
28+
def test_map_header():
29+
packer = Packer()
30+
packer.pack_map_header(2**32-1)
31+
with pytest.raises(ValueError):
32+
packer.pack_array_header(2**32)
33+
34+
35+
# PyPy fails following tests because of constant folding?
36+
# https://bugs.pypy.org/issue1721
37+
#@pytest.mark.skipif(True, reason="Requires very large memory.")
38+
#def test_binary():
39+
# x = b'x' * (2**32 - 1)
40+
# assert unpackb(packb(x)) == x
41+
# del x
42+
# x = b'x' * (2**32)
43+
# with pytest.raises(ValueError):
44+
# packb(x)
45+
#
46+
#
47+
#@pytest.mark.skipif(True, reason="Requires very large memory.")
48+
#def test_string():
49+
# x = 'x' * (2**32 - 1)
50+
# assert unpackb(packb(x)) == x
51+
# x += 'y'
52+
# with pytest.raises(ValueError):
53+
# packb(x)
54+
#
55+
#
56+
#@pytest.mark.skipif(True, reason="Requires very large memory.")
57+
#def test_array():
58+
# x = [0] * (2**32 - 1)
59+
# assert unpackb(packb(x)) == x
60+
# x.append(0)
61+
# with pytest.raises(ValueError):
62+
# packb(x)

0 commit comments

Comments
 (0)
0