Skip to content

Commit 0ef5286

Browse files
committed
Fix unpack error on Python 3.2.
ctx.user.encoding and ctx.user.unicode_errors may refer to deallocated string.
1 parent eb61b4d commit 0ef5286

File tree

1 file changed

+35
-23
lines changed

1 file changed

+35
-23
lines changed

msgpack/_msgpack.pyx

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# coding: utf-8
22
#cython: embedsignature=True
33

4-
import warnings
5-
64
from cpython cimport *
75
cdef extern from "Python.h":
86
ctypedef char* const_char_ptr "const char*"
@@ -233,7 +231,9 @@ cdef extern from "unpack.h":
233231
void template_init(template_context* ctx)
234232
object template_data(template_context* ctx)
235233

236-
cdef inline init_ctx(template_context *ctx, object object_hook, object object_pairs_hook, object list_hook, bint use_list, encoding, unicode_errors):
234+
cdef inline init_ctx(template_context *ctx,
235+
object object_hook, object object_pairs_hook, object list_hook,
236+
bint use_list, char* encoding, char* unicode_errors):
237237
template_init(ctx)
238238
ctx.user.use_list = use_list
239239
ctx.user.object_hook = ctx.user.list_hook = <PyObject*>NULL
@@ -259,20 +259,8 @@ cdef inline init_ctx(template_context *ctx, object object_hook, object object_pa
259259
raise TypeError("list_hook must be a callable.")
260260
ctx.user.list_hook = <PyObject*>list_hook
261261

262-
if encoding is None:
263-
ctx.user.encoding = NULL
264-
ctx.user.unicode_errors = NULL
265-
else:
266-
if isinstance(encoding, unicode):
267-
_bencoding = encoding.encode('ascii')
268-
else:
269-
_bencoding = encoding
270-
ctx.user.encoding = PyBytes_AsString(_bencoding)
271-
if isinstance(unicode_errors, unicode):
272-
_berrors = unicode_errors.encode('ascii')
273-
else:
274-
_berrors = unicode_errors
275-
ctx.user.unicode_errors = PyBytes_AsString(_berrors)
262+
ctx.user.encoding = encoding
263+
ctx.user.unicode_errors = unicode_errors
276264

277265
def unpackb(object packed, object object_hook=None, object list_hook=None,
278266
bint use_list=1, encoding=None, unicode_errors="strict",
@@ -288,10 +276,22 @@ def unpackb(object packed, object object_hook=None, object list_hook=None,
288276

289277
cdef char* buf
290278
cdef Py_ssize_t buf_len
279+
cdef char* cenc = NULL
280+
cdef char* cerr = NULL
291281

292282
PyObject_AsReadBuffer(packed, <const_void_ptr*>&buf, &buf_len)
293283

294-
init_ctx(&ctx, object_hook, object_pairs_hook, list_hook, use_list, encoding, unicode_errors)
284+
if encoding is not None:
285+
if isinstance(encoding, unicode):
286+
encoding = encoding.encode('ascii')
287+
cenc = PyBytes_AsString(encoding)
288+
289+
if unicode_errors is not None:
290+
if isinstance(unicode_errors, unicode):
291+
unicode_errors = unicode_errors.encode('ascii')
292+
cerr = PyBytes_AsString(unicode_errors)
293+
294+
init_ctx(&ctx, object_hook, object_pairs_hook, list_hook, use_list, cenc, cerr)
295295
ret = template_construct(&ctx, buf, buf_len, &off)
296296
if ret == 1:
297297
obj = template_data(&ctx)
@@ -370,10 +370,7 @@ cdef class Unpacker(object):
370370
cdef object file_like_read
371371
cdef Py_ssize_t read_size
372372
cdef object object_hook
373-
cdef object _bencoding
374-
cdef object _berrors
375-
cdef char *encoding
376-
cdef char *unicode_errors
373+
cdef object encoding, unicode_errors
377374
cdef size_t max_buffer_size
378375

379376
def __cinit__(self):
@@ -387,6 +384,8 @@ cdef class Unpacker(object):
387384
object object_hook=None, object object_pairs_hook=None, object list_hook=None,
388385
encoding=None, unicode_errors='strict', int max_buffer_size=0,
389386
):
387+
cdef char *cenc, *cerr
388+
390389
self.file_like = file_like
391390
if file_like:
392391
self.file_like_read = file_like.read
@@ -406,7 +405,20 @@ cdef class Unpacker(object):
406405
self.buf_size = read_size
407406
self.buf_head = 0
408407
self.buf_tail = 0
409-
init_ctx(&self.ctx, object_hook, object_pairs_hook, list_hook, use_list, encoding, unicode_errors)
408+
409+
if encoding is not None:
410+
if isinstance(encoding, unicode):
411+
encoding = encoding.encode('ascii')
412+
self.encoding = encoding
413+
cenc = PyBytes_AsString(encoding)
414+
415+
if unicode_errors is not None:
416+
if isinstance(unicode_errors, unicode):
417+
unicode_errors = unicode_errors.encode('ascii')
418+
self.unicode_errors = unicode_errors
419+
cerr = PyBytes_AsString(unicode_errors)
420+
421+
init_ctx(&self.ctx, object_hook, object_pairs_hook, list_hook, use_list, cenc, cerr)
410422

411423
def feed(self, object next_bytes):
412424
cdef char* buf

0 commit comments

Comments
 (0)