Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6107a68

Browse files
committed
Merged revisions 81908 via svnmerge from
svn+ssh://[email protected]/python/branches/py3k ................ r81908 | antoine.pitrou | 2010-06-11 23:46:32 +0200 (ven., 11 juin 2010) | 11 lines Merged revisions 81907 via svnmerge from svn+ssh://[email protected]/python/trunk ........ r81907 | antoine.pitrou | 2010-06-11 23:42:26 +0200 (ven., 11 juin 2010) | 5 lines Issue #8941: decoding big endian UTF-32 data in UCS-2 builds could crash the interpreter with characters outside the Basic Multilingual Plane (higher than 0x10000). ........ ................
1 parent 4a3acca commit 6107a68

3 files changed

Lines changed: 50 additions & 19 deletions

File tree

Lib/test/test_codecs.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,16 @@ def test_decoder_state(self):
354354
self.check_state_handling_decode(self.encoding,
355355
"spamspam", self.spambe)
356356

357+
def test_issue8941(self):
358+
# Issue #8941: insufficient result allocation when decoding into
359+
# surrogate pairs on UCS-2 builds.
360+
encoded_le = b'\xff\xfe\x00\x00' + b'\x00\x00\x01\x00' * 1024
361+
self.assertEqual('\U00010000' * 1024,
362+
codecs.utf_32_decode(encoded_le)[0])
363+
encoded_be = b'\x00\x00\xfe\xff' + b'\x00\x01\x00\x00' * 1024
364+
self.assertEqual('\U00010000' * 1024,
365+
codecs.utf_32_decode(encoded_be)[0])
366+
357367
class UTF32LETest(ReadTest):
358368
encoding = "utf-32-le"
359369

@@ -387,6 +397,13 @@ def test_errors(self):
387397
self.assertRaises(UnicodeDecodeError, codecs.utf_32_le_decode,
388398
b"\xff", "strict", True)
389399

400+
def test_issue8941(self):
401+
# Issue #8941: insufficient result allocation when decoding into
402+
# surrogate pairs on UCS-2 builds.
403+
encoded = b'\x00\x00\x01\x00' * 1024
404+
self.assertEqual('\U00010000' * 1024,
405+
codecs.utf_32_le_decode(encoded)[0])
406+
390407
class UTF32BETest(ReadTest):
391408
encoding = "utf-32-be"
392409

@@ -420,6 +437,14 @@ def test_errors(self):
420437
self.assertRaises(UnicodeDecodeError, codecs.utf_32_be_decode,
421438
b"\xff", "strict", True)
422439

440+
def test_issue8941(self):
441+
# Issue #8941: insufficient result allocation when decoding into
442+
# surrogate pairs on UCS-2 builds.
443+
encoded = b'\x00\x01\x00\x00' * 1024
444+
self.assertEqual('\U00010000' * 1024,
445+
codecs.utf_32_be_decode(encoded)[0])
446+
447+
423448
class UTF16Test(ReadTest):
424449
encoding = "utf-16"
425450

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ What's New in Python 3.1.3?
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #8941: decoding big endian UTF-32 data in UCS-2 builds could crash
16+
the interpreter with characters outside the Basic Multilingual Plane
17+
(higher than 0x10000).
18+
1519
- In the str.format(), raise a ValueError when indexes to arguments are too
1620
large.
1721

Objects/unicodeobject.c

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,11 +2618,11 @@ PyUnicode_DecodeUTF32Stateful(const char *s,
26182618
PyUnicodeObject *unicode;
26192619
Py_UNICODE *p;
26202620
#ifndef Py_UNICODE_WIDE
2621-
int i, pairs;
2621+
int pairs = 0;
26222622
#else
26232623
const int pairs = 0;
26242624
#endif
2625-
const unsigned char *q, *e;
2625+
const unsigned char *q, *e, *qq;
26262626
int bo = 0; /* assume native ordering by default */
26272627
const char *errmsg = "";
26282628
/* Offsets from q for retrieving bytes in the right order. */
@@ -2633,23 +2633,7 @@ PyUnicode_DecodeUTF32Stateful(const char *s,
26332633
#endif
26342634
PyObject *errorHandler = NULL;
26352635
PyObject *exc = NULL;
2636-
/* On narrow builds we split characters outside the BMP into two
2637-
codepoints => count how much extra space we need. */
2638-
#ifndef Py_UNICODE_WIDE
2639-
for (i = pairs = 0; i < size/4; i++)
2640-
if (((Py_UCS4 *)s)[i] >= 0x10000)
2641-
pairs++;
2642-
#endif
2643-
2644-
/* This might be one to much, because of a BOM */
2645-
unicode = _PyUnicode_New((size+3)/4+pairs);
2646-
if (!unicode)
2647-
return NULL;
2648-
if (size == 0)
2649-
return (PyObject *)unicode;
2650-
2651-
/* Unpack UTF-32 encoded data */
2652-
p = unicode->str;
2636+
26532637
q = (unsigned char *)s;
26542638
e = q + size;
26552639

@@ -2701,6 +2685,24 @@ PyUnicode_DecodeUTF32Stateful(const char *s,
27012685
iorder[3] = 0;
27022686
}
27032687

2688+
/* On narrow builds we split characters outside the BMP into two
2689+
codepoints => count how much extra space we need. */
2690+
#ifndef Py_UNICODE_WIDE
2691+
for (qq = q; qq < e; qq += 4)
2692+
if (qq[iorder[2]] != 0 || qq[iorder[3]] != 0)
2693+
pairs++;
2694+
#endif
2695+
2696+
/* This might be one to much, because of a BOM */
2697+
unicode = _PyUnicode_New((size+3)/4+pairs);
2698+
if (!unicode)
2699+
return NULL;
2700+
if (size == 0)
2701+
return (PyObject *)unicode;
2702+
2703+
/* Unpack UTF-32 encoded data */
2704+
p = unicode->str;
2705+
27042706
while (q < e) {
27052707
Py_UCS4 ch;
27062708
/* remaining bytes at the end? (size should be divisible by 4) */

0 commit comments

Comments
 (0)