10000 bpo-31897: Convert unexpected errors when read bogus binary plists in… · miss-islington/cpython@ec04d00 · GitHub
[go: up one dir, main page]

Skip to content

Commit ec04d00

Browse files
serhiy-storchakamiss-islington
authored andcommitted
bpo-31897: Convert unexpected errors when read bogus binary plists into InvalidFileException. (pythonGH-4171)
(cherry picked from commit db91e0f)
1 parent 41efc40 commit ec04d00

File tree

3 files changed

+70
-5
lines changed

3 files changed

+70
-5
lines changed

Lib/plistlib.py

Lines changed: 4 additions & 1 deletion
< 10000 td data-grid-cell-id="diff-54b4dbba1851f4da677aa12b528d553b094558645daf343b01abd0c1280ba011-628-629-2" data-line-anchor="diff-54b4dbba1851f4da677aa12b528d553b094558645daf343b01abd0c1280ba011R629" data-selected="false" role="gridcell" style="background-color:var(--bgColor-default);padding-right:24px" tabindex="-1" valign="top" class="focusable-grid-cell diff-text-cell right-side-diff-cell left-side">
def _get_size(self, tokenL):
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,8 @@ def parse(self, fp):
622622
self._object_offsets = self._read_ints(num_objects, offset_size)
623623
return self._read_object(self._object_offsets[top_object])
624624

625-
except (OSError, IndexError, struct.error):
625+
except (OSError, IndexError, struct.error, OverflowError,
626+
UnicodeDecodeError):
626627
raise InvalidFileException()
627628

628629
@@ -640,6 +641,8 @@ def _read_ints(self, n, size):
640641
if size in _BINARY_FORMAT:
641642
return struct.unpack('>' + _BINARY_FORMAT[size] * n, data)
642643
else:
644+
if not size or len(data) != size * n:
645+
raise InvalidFileException()
643646
return tuple(int.from_bytes(data[i: i + size], 'big')
644647
for i in range(0, size * n, size))
645648

Lib/test/test_plistlib.py

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,13 @@ def test_controlcharacters(self):
354354
testString = "string containing %s" % c
355355
if i >= 32 or c in "\r\n\t":
356356
# \r, \n and \t are the only legal control chars in XML
357-
plistlib.dumps(testString, fmt=plistlib.FMT_XML)
357+
data = plistlib.dumps(testString, fmt=plistlib.FMT_XML)
358+
if c != "\r":
359+
self.assertEqual(plistlib.loads(data), testString)
358360
else:
359-
self.assertRaises(ValueError,
360-
plistlib.dumps,
361-
testString)
361+
with self.assertRaises(ValueError):
362+
plistlib.dumps(testString, fmt=plistlib.FMT_XML)
363+
plistlib.dumps(testString, fmt=plistlib.FMT_BINARY)
362364

363365
def test_non_bmp_characters(self):
364366
pl = {'python': '\U0001f40d'}
@@ -367,6 +369,14 @@ def test_non_bmp_characters(self):
367369
data = plistlib.dumps(pl, fmt=fmt)
368370
self.assertEqual(plistlib.loads(data), pl)
369371

372+
def test_lone_surrogates(self):
373+
for fmt in ALL_FORMATS:
374+
with self.subTest(fmt=fmt):
375+
with self.assertRaises(UnicodeEncodeError):
376+
plistlib.dumps('\ud8ff', fmt=fmt)
377+
with self.assertRaises(UnicodeEncodeError):
378+
plistlib.dumps('\udcff', fmt= 10000 fmt)
379+
370380
def test_nondictroot(self):
371381
for fmt in ALL_FORMATS:
372382
with self.subTest(fmt=fmt):
@@ -443,6 +453,56 @@ def test_large_timestamp(self):
443453
data = plistlib.dumps(d, fmt=plistlib.FMT_BINARY)
444454
self.assertEqual(plistlib.loads(data), d)
445455

456+
def test_invalid_binary(self):
457+
for data in [
458+
# too short data
459+
b'',
460+
# too large offset_table_offset and nonstandard offset_size
461+
b'\x00\x08'
462+
b'\x00\x00\x00\x00\x00\x00\x03\x01'
463+
b'\x00\x00\x00\x00\x00\x00\x00\x01'
464+
b'\x00\x00\x00\x00\x00\x00\x00\x00'
465+
b'\x00\x00\x00\x00\x00\x00\x00\x2a',
466+
# integer overflow in offset_table_offset
467+
b'\x00\x08'
468+
b'\x00\x00\x00\x00\x00\x00\x01\x01'
469+
b'\x00\x00\x00\x00\x00\x00\x00\x01'
470+
b'\x00\x00\x00\x00\x00\x00\x00\x00'
471+
b'\xff\xff\xff\xff\xff\xff\xff\xff',
472+
# offset_size = 0
473+
b'\x00\x08'
474+
b'\x00\x00\x00\x00\x00\x00\x00\x01'
475+
b'\x00\x00\x00\x00\x00\x00\x00\x01'
476+
b'\x00\x00\x00\x00\x00\x00\x00\x00'
477+
b'\x00\x00\x00\x00\x00\x00\x00\x09',
478+
# ref_size = 0
479+
b'\xa1\x01\x00\x08\x0a'
480+
b'\x00\x00\x00\x00\x00\x00\x01\x00'
481+
b'\x00\x00\x00\x00\x00\x00\x00\x02'
482+
b'\x00\x00\x00\x00\x00\x00\x00\x00'
483+
b'\x00\x00\x00\x00\x00\x00\x00\x0b',
484+
# integer overflow in offset
485+
b'\x00\xff\xff\xff\xff\xff\xff\xff\xff'
486+
b'\x00\x00\x00\x00\x00\x00\x08\x01'
487+
b'\x00\x00\x00\x00\x00\x00\x00\x01'
488+
b'\x00\x00\x00\x00\x00\x00\x00\x00'
489+
b'\x00\x00\x00\x00\x00\x00\x00\x09',
490+
# invalid ASCII
491+
b'\x51\xff\x08'
492+
b'\x00\x00\x00\x00\x00\x00\x01\x01'
493+
b'\x00\x00\x00\x00\x00\x00\x00\x01'
494+
b'\x00\x00\x00\x00\x00\x00\x00\x00'
495+
b'\x00\x00\x00\x00\x00\x00\x00\x0a',
496+
# invalid UTF-16
497+
b'\x61\xd8\x00\x08'
498+
b'\x00\x00\x00\x00\x00\x00\x01\x01'
499+
b'\x00\x00\x00\x00\x00\x00\x00\x01'
500+
b'\x00\x00\x00\x00\x00\x00\x00\x00'
501+
b'\x00\x00\x00\x00\x00\x00\x00\x0b',
502+
]:
503+
with self.assertRaises(plistlib.InvalidFileException):
504+
plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY)
505+
446506

447507
class TestPlistlibDeprecated(unittest.TestCase):
448508
def test_io_deprecated(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
plistlib now catches more errors when read binary plists and raises
2+
InvalidFileException instead of unexpected exceptions.

0 commit comments

Comments
 (0)
0