@@ -28,6 +28,11 @@ cdef extern from "unpack.h":
2828 PyObject* ext_hook
2929 char * encoding
3030 char * unicode_errors
31+ Py_ssize_t max_str_len
32+ Py_ssize_t max_bin_len
33+ Py_ssize_t max_array_len
34+ Py_ssize_t max_map_len
35+ Py_ssize_t max_ext_len
3136
3237 ctypedef struct unpack_context:
3338 msgpack_user user
@@ -46,10 +51,18 @@ cdef extern from "unpack.h":
4651cdef inline init_ctx(unpack_context * ctx,
4752 object object_hook, object object_pairs_hook,
4853 object list_hook, object ext_hook,
49- bint use_list, char * encoding, char * unicode_errors):
54+ bint use_list, char * encoding, char * unicode_errors,
55+ Py_ssize_t max_str_len, Py_ssize_t max_bin_len,
56+ Py_ssize_t max_array_len, Py_ssize_t max_map_len,
57+ Py_ssize_t max_ext_len):
5058 unpack_init(ctx)
5159 ctx.user.use_list = use_list
5260 ctx.user.object_hook = ctx.user.list_hook = < PyObject* > NULL
61+ ctx.user.max_str_len = max_str_len
62+ ctx.user.max_bin_len = max_bin_len
63+ ctx.user.max_array_len = max_array_len
64+ ctx.user.max_map_len = max_map_len
65+ ctx.user.max_ext_len = max_ext_len
5366
5467 if object_hook is not None and object_pairs_hook is not None :
5568 raise TypeError (" object_pairs_hook and object_hook are mutually exclusive." )
@@ -85,7 +98,12 @@ def default_read_extended_type(typecode, data):
8598
8699def unpackb (object packed , object object_hook = None , object list_hook = None ,
87100 bint use_list = 1 , encoding = None , unicode_errors = " strict" ,
88- object_pairs_hook = None , ext_hook = ExtType):
101+ object_pairs_hook = None , ext_hook = ExtType,
102+ Py_ssize_t max_str_len = 2147483647 , # 2**32-1
103+ Py_ssize_t max_bin_len = 2147483647 ,
104+ Py_ssize_t max_array_len = 2147483647 ,
105+ Py_ssize_t max_map_len = 2147483647 ,
106+ Py_ssize_t max_ext_len = 2147483647 ):
89107 """
90108 Unpack packed_bytes to object. Returns an unpacked object.
91109
@@ -115,7 +133,8 @@ def unpackb(object packed, object object_hook=None, object list_hook=None,
115133 cerr = PyBytes_AsString(unicode_errors)
116134
117135 init_ctx(& ctx, object_hook, object_pairs_hook, list_hook, ext_hook,
118- use_list, cenc, cerr)
136+ use_list, cenc, cerr,
137+ max_str_len, max_bin_len, max_array_len, max_map_len, max_ext_len)
119138 ret = unpack_construct(& ctx, buf, buf_len, & off)
120139 if ret == 1 :
121140 obj = unpack_data(& ctx)
@@ -144,8 +163,7 @@ def unpack(object stream, object object_hook=None, object list_hook=None,
144163
145164
146165cdef class Unpacker(object ):
147- """
148- Streaming unpacker.
166+ """ Streaming unpacker.
149167
150168 arguments:
151169
@@ -183,6 +201,19 @@ cdef class Unpacker(object):
183201 Raises `BufferFull` exception when it is insufficient.
184202 You shoud set this parameter when unpacking data from untrasted source.
185203
204+ :param int max_str_len:
205+ Limits max length of str. (default: 2**31-1)
206+
207+ :param int max_bin_len:
208+ Limits max length of bin. (default: 2**31-1)
209+
210+ :param int max_array_len:
211+ Limits max length of array. (default: 2**31-1)
212+
213+ :param int max_map_len:
214+ Limits max length of map. (default: 2**31-1)
215+
216+
186217 example of streaming deserialize from file-like object::
187218
188219 unpacker = Unpacker(file_like)
@@ -220,8 +251,13 @@ cdef class Unpacker(object):
220251
221252 def __init__ (self , file_like = None , Py_ssize_t read_size = 0 , bint use_list = 1 ,
222253 object object_hook = None , object object_pairs_hook = None , object list_hook = None ,
223- str encoding = None , str unicode_errors = ' strict' , int max_buffer_size = 0 ,
224- object ext_hook = ExtType):
254+ encoding = None , unicode_errors = ' strict' , int max_buffer_size = 0 ,
255+ object ext_hook = ExtType,
256+ Py_ssize_t max_str_len = 2147483647 , # 2**32-1
257+ Py_ssize_t max_bin_len = 2147483647 ,
258+ Py_ssize_t max_array_len = 2147483647 ,
259+ Py_ssize_t max_map_len = 2147483647 ,
260+ Py_ssize_t max_ext_len = 2147483647 ):
225261 cdef char * cenc= NULL ,
226262 cdef char * cerr= NULL
227263
@@ -253,19 +289,25 @@ cdef class Unpacker(object):
253289 if encoding is not None :
254290 if isinstance (encoding, unicode ):
255291 self .encoding = encoding.encode(' ascii' )
256- else :
292+ elif isinstance (encoding, bytes) :
257293 self .encoding = encoding
294+ else :
295+ raise TypeError (" encoding should be bytes or unicode" )
258296 cenc = PyBytes_AsString(self .encoding)
259297
260298 if unicode_errors is not None :
261299 if isinstance (unicode_errors, unicode ):
262300 self .unicode_errors = unicode_errors.encode(' ascii' )
263- else :
301+ elif isinstance (unicode_errors, bytes) :
264302 self .unicode_errors = unicode_errors
303+ else :
304+ raise TypeError (" unicode_errors should be bytes or unicode" )
265305 cerr = PyBytes_AsString(self .unicode_errors)
266306
267307 init_ctx(& self .ctx, object_hook, object_pairs_hook, list_hook,
268- ext_hook, use_list, cenc, cerr)
308+ ext_hook, use_list, cenc, cerr,
309+ max_str_len, max_bin_len, max_array_len,
310+ max_map_len, max_ext_len)
269311
270312 def feed (self , object next_bytes ):
271313 """ Append `next_bytes` to internal buffer."""
@@ -365,7 +407,7 @@ cdef class Unpacker(object):
365407 raise ValueError (" Unpack failed: error = %d " % (ret,))
366408
367409 def read_bytes (self , Py_ssize_t nbytes ):
368- """ read a specified number of raw bytes from the stream"""
410+ """ Read a specified number of raw bytes from the stream"""
369411 cdef size_t nread
370412 nread = min (self .buf_tail - self .buf_head, nbytes)
371413 ret = PyBytes_FromStringAndSize(self .buf + self .buf_head, nread)
@@ -375,8 +417,7 @@ cdef class Unpacker(object):
375417 return ret
376418
377419 def unpack (self , object write_bytes = None ):
378- """
379- unpack one object
420+ """ Unpack one object
380421
381422 If write_bytes is not None, it will be called with parts of the raw
382423 message as it is unpacked.
@@ -386,8 +427,7 @@ cdef class Unpacker(object):
386427 return self ._unpack(unpack_construct, write_bytes)
387428
388429 def skip (self , object write_bytes = None ):
389- """
390- read and ignore one object, returning None
430+ """ Read and ignore one object, returning None
391431
392432 If write_bytes is not None, it will be called with parts of the raw
393433 message as it is unpacked.
0 commit comments