@@ -28,6 +28,11 @@ cdef extern from "unpack.h":
28
28
PyObject* ext_hook
29
29
char * encoding
30
30
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
31
36
32
37
ctypedef struct unpack_context:
33
38
msgpack_user user
@@ -46,10 +51,18 @@ cdef extern from "unpack.h":
46
51
cdef inline init_ctx(unpack_context * ctx,
47
52
object object_hook, object object_pairs_hook,
48
53
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):
50
58
unpack_init(ctx)
51
59
ctx.user.use_list = use_list
52
60
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
53
66
54
67
if object_hook is not None and object_pairs_hook is not None :
55
68
raise TypeError (" object_pairs_hook and object_hook are mutually exclusive." )
@@ -85,7 +98,12 @@ def default_read_extended_type(typecode, data):
85
98
86
99
def unpackb (object packed , object object_hook = None , object list_hook = None ,
87
100
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 ):
89
107
"""
90
108
Unpack packed_bytes to object. Returns an unpacked object.
91
109
@@ -115,7 +133,8 @@ def unpackb(object packed, object object_hook=None, object list_hook=None,
115
133
cerr = PyBytes_AsString(unicode_errors)
116
134
117
135
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)
119
138
ret = unpack_construct(& ctx, buf, buf_len, & off)
120
139
if ret == 1 :
121
140
obj = unpack_data(& ctx)
@@ -144,8 +163,7 @@ def unpack(object stream, object object_hook=None, object list_hook=None,
144
163
145
164
146
165
cdef class Unpacker(object ):
147
- """
148
- Streaming unpacker.
166
+ """ Streaming unpacker.
149
167
150
168
arguments:
151
169
@@ -183,6 +201,19 @@ cdef class Unpacker(object):
183
201
Raises `BufferFull` exception when it is insufficient.
184
202
You shoud set this parameter when unpacking data from untrasted source.
185
203
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
+
186
217
example of streaming deserialize from file-like object::
187
218
188
219
unpacker = Unpacker(file_like)
@@ -220,8 +251,13 @@ cdef class Unpacker(object):
220
251
221
252
def __init__ (self , file_like = None , Py_ssize_t read_size = 0 , bint use_list = 1 ,
222
253
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 ):
225
261
cdef char * cenc= NULL ,
226
262
cdef char * cerr= NULL
227
263
@@ -253,19 +289,25 @@ cdef class Unpacker(object):
253
289
if encoding is not None :
254
290
if isinstance (encoding, unicode ):
255
291
self .encoding = encoding.encode(' ascii' )
256
- else :
292
+ elif isinstance (encoding, bytes) :
257
293
self .encoding = encoding
294
+ else :
295
+ raise TypeError (" encoding should be bytes or unicode" )
258
296
cenc = PyBytes_AsString(self .encoding)
259
297
260
298
if unicode_errors is not None :
261
299
if isinstance (unicode_errors, unicode ):
262
300
self .unicode_errors = unicode_errors.encode(' ascii' )
263
- else :
301
+ elif isinstance (unicode_errors, bytes) :
264
302
self .unicode_errors = unicode_errors
303
+ else :
304
+ raise TypeError (" unicode_errors should be bytes or unicode" )
265
305
cerr = PyBytes_AsString(self .unicode_errors)
266
306
267
307
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)
269
311
270
312
def feed (self , object next_bytes ):
271
313
""" Append `next_bytes` to internal buffer."""
@@ -365,7 +407,7 @@ cdef class Unpacker(object):
365
407
raise ValueError (" Unpack failed: error = %d " % (ret,))
366
408
367
409
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"""
369
411
cdef size_t nread
370
412
nread = min (self .buf_tail - self .buf_head, nbytes)
371
413
ret = PyBytes_FromStringAndSize(self .buf + self .buf_head, nread)
@@ -375,8 +417,7 @@ cdef class Unpacker(object):
375
417
return ret
376
418
377
419
def unpack (self , object write_bytes = None ):
378
- """
379
- unpack one object
420
+ """ Unpack one object
380
421
381
422
If write_bytes is not None, it will be called with parts of the raw
382
423
message as it is unpacked.
@@ -386,8 +427,7 @@ cdef class Unpacker(object):
386
427
return self ._unpack(unpack_construct, write_bytes)
387
428
388
429
def skip (self , object write_bytes = None ):
389
- """
390
- read and ignore one object, returning None
430
+ """ Read and ignore one object, returning None
391
431
392
432
If write_bytes is not None, it will be called with parts of the raw
393
433
message as it is unpacked.
0 commit comments