/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/_bencode_pyx.pyx

  • Committer: Martin
  • Date: 2018-08-21 00:53:34 UTC
  • mto: This revision was merged to the branch mainline in revision 7074.
  • Revision ID: gzlist@googlemail.com-20180821005334-e1ogxakojyybpwib
Fix recursion check in C bencode implementation

Hard to get Cython to do the right thing but by inverting the
return code can use the standard except handling.

Avoid going through a Python call when encoding, which requires
the encode recursion check to work too.

Adjust tests to use a smaller limit to be more managable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
from __future__ import absolute_import
20
20
 
 
21
from cpython.bool cimport (
 
22
    PyBool_Check,
 
23
    )
21
24
from cpython.bytes cimport (
22
25
    PyBytes_CheckExact,
23
26
    PyBytes_FromStringAndSize,
24
27
    PyBytes_AS_STRING,
25
28
    PyBytes_GET_SIZE,
26
29
    )
27
 
from cpython.long cimport (
28
 
    PyLong_CheckExact,
 
30
from cpython.dict cimport (
 
31
    PyDict_CheckExact,
29
32
    )
30
33
from cpython.int cimport (
31
34
    PyInt_CheckExact,
32
35
    PyInt_FromString,
33
36
    )
34
 
from cpython.tuple cimport (
35
 
    PyTuple_CheckExact,
36
 
    )
37
37
from cpython.list cimport (
38
38
    PyList_CheckExact,
39
39
    PyList_Append,
40
40
    )
41
 
from cpython.dict cimport (
42
 
    PyDict_CheckExact,
43
 
    )
44
 
from cpython.bool cimport (
45
 
    PyBool_Check,
 
41
from cpython.long cimport (
 
42
    PyLong_CheckExact,
46
43
    )
47
44
from cpython.mem cimport (
48
45
    PyMem_Free,
49
46
    PyMem_Malloc,
50
47
    PyMem_Realloc,
51
48
    )
 
49
from cpython.tuple cimport (
 
50
    PyTuple_CheckExact,
 
51
    )
52
52
 
53
53
from libc.stdlib cimport (
54
54
    strtol,
57
57
    memcpy,
58
58
    )
59
59
 
 
60
cdef extern from "python-compat.h":
 
61
    int snprintf(char* buffer, size_t nsize, char* fmt, ...)
 
62
    # Use wrapper with inverted error return so Cython can propogate
 
63
    int BrzPy_EnterRecursiveCall(char *) except 0
 
64
 
60
65
cdef extern from "Python.h":
61
 
    # There is no cython module for ceval.h for some reason
62
 
    int Py_GetRecursionLimit()
63
 
    int Py_EnterRecursiveCall(char *)
64
66
    void Py_LeaveRecursiveCall()
65
67
 
66
 
cdef extern from "python-compat.h":
67
 
    int snprintf(char* buffer, size_t nsize, char* fmt, ...)
68
 
 
69
68
cdef class Decoder
70
69
cdef class Encoder
71
70
 
114
113
        if 0 == self.size:
115
114
            raise ValueError('stream underflow')
116
115
 
117
 
        if Py_EnterRecursiveCall("_decode_object"):
118
 
            raise RuntimeError("too deeply nested")
 
116
        BrzPy_EnterRecursiveCall(" while bencode decoding")
119
117
        try:
120
118
            ch = self.tail[0]
121
119
            if c'0' <= ch <= c'9':
129
127
            elif ch == c'd':
130
128
                D_UPDATE_TAIL(self, 1)
131
129
                return self._decode_dict()
132
 
            else:
133
 
                raise ValueError('unknown object type identifier %r' % ch)
134
130
        finally:
135
131
            Py_LeaveRecursiveCall()
 
132
        raise ValueError('unknown object type identifier %r' % ch)
136
133
 
137
134
    cdef int _read_digits(self, char stop_char) except -1:
138
135
        cdef int i
342
339
        cdef Py_ssize_t x_len
343
340
        x_len = PyBytes_GET_SIZE(x)
344
341
        self._ensure_buffer(x_len + INT_BUF_SIZE)
345
 
        n = snprintf(self.tail, INT_BUF_SIZE, b'%d:', x_len)
 
342
        n = snprintf(self.tail, INT_BUF_SIZE, b'%ld:', x_len)
346
343
        if n < 0:
347
344
            raise MemoryError('string %s too big to encode' % x)
348
345
        memcpy(<void *>(self.tail+n), PyBytes_AS_STRING(x), x_len)
378
375
        E_UPDATE_TAIL(self, 1)
379
376
        return 1
380
377
 
381
 
    def process(self, object x):
382
 
        if Py_EnterRecursiveCall("encode"):
383
 
            raise RuntimeError("too deeply nested")
 
378
    cpdef object process(self, object x):
 
379
        BrzPy_EnterRecursiveCall(" while bencode encoding")
384
380
        try:
385
381
            if PyBytes_CheckExact(x):
386
382
                self._encode_string(x)