branch Attitude Adjustment packages
[12.09/packages.git] / lang / python-cjson / patches / 001-unicode-buffer-overflow.patch
1 === modified file 'cjson.c'
2 --- a/cjson.c   2007-08-24 16:12:17 +0000
3 +++ b/cjson.c   2010-05-26 05:05:55 +0000
4 @@ -613,6 +613,25 @@
5      char *p;
6  
7      static const char *hexdigit = "0123456789abcdef";
8 +#ifdef Py_UNICODE_WIDE
9 +    const Py_ssize_t expandsize = 10;
10 +#else
11 +    const Py_ssize_t expandsize = 6;
12 +#endif
13 +
14 +    /* Initial allocation is based on the longest-possible unichr
15 +       escape.
16 +
17 +       In wide (UTF-32) builds '\U00xxxxxx' is 10 chars per source
18 +       unichr, so in this case it's the longest unichr escape. In
19 +       narrow (UTF-16) builds this is five chars per source unichr
20 +       since there are two unichrs in the surrogate pair, so in narrow
21 +       (UTF-16) builds it's not the longest unichr escape.
22 +
23 +       In wide or narrow builds '\uxxxx' is 6 chars per source unichr,
24 +       so in the narrow (UTF-16) build case it's the longest unichr
25 +       escape.
26 +    */
27  
28      s = PyUnicode_AS_UNICODE(unicode);
29      size = PyUnicode_GET_SIZE(unicode);
30 @@ -623,7 +642,7 @@
31          return NULL;
32      }
33  
34 -    repr = PyString_FromStringAndSize(NULL, 2 + 6*size + 1);
35 +    repr = PyString_FromStringAndSize(NULL, 2 + expandsize*size + 1);
36      if (repr == NULL)
37          return NULL;
38  
39 @@ -644,15 +663,6 @@
40  #ifdef Py_UNICODE_WIDE
41          /* Map 21-bit characters to '\U00xxxxxx' */
42          else if (ch >= 0x10000) {
43 -            int offset = p - PyString_AS_STRING(repr);
44 -
45 -            /* Resize the string if necessary */
46 -            if (offset + 12 > PyString_GET_SIZE(repr)) {
47 -                if (_PyString_Resize(&repr, PyString_GET_SIZE(repr) + 100))
48 -                    return NULL;
49 -                p = PyString_AS_STRING(repr) + offset;
50 -            }
51 -
52              *p++ = '\\';
53              *p++ = 'U';
54              *p++ = hexdigit[(ch >> 28) & 0x0000000F];
55
56 === modified file 'jsontest.py'
57 --- a/jsontest.py       2007-08-24 16:12:17 +0000
58 +++ b/jsontest.py       2010-05-26 05:05:55 +0000
59 @@ -316,6 +316,18 @@
60  
61      def testWriteLong(self):
62          self.assertEqual("12345678901234567890", cjson.encode(12345678901234567890))
63 +
64 +    def testWriteLongUnicode(self):
65 +        # This test causes a buffer overrun in cjson 1.0.5, on UCS4 builds.
66 +        # The string length is only resized for wide unicode characters if
67 +        # there is less than 12 bytes of space left. Padding with
68 +        # narrow-but-escaped characters prevents string resizing.
69 +        # Note that u'\U0001D11E\u1234' also breaks, but sometimes goes
70 +        # undetected.
71 +        s = cjson.encode(u'\U0001D11E\U0001D11E\U0001D11E\U0001D11E'
72 +                         u'\u1234\u1234\u1234\u1234\u1234\u1234')
73 +        self.assertEqual(r'"\U0001d11e\U0001d11e\U0001d11e\U0001d11e'
74 +                         r'\u1234\u1234\u1234\u1234\u1234\u1234"', s)
75          
76  def main():
77      unittest.main()
78
79