summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2014-05-23 13:15:06 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2014-05-23 13:15:06 (GMT)
commitc083537b8731c8f2ffe607a12f96a3eb95f788f7 (patch)
treec1687e6f23de98a1f0b8787a89af8516a9b5e60c
parenta7834d31c7cec6948f56d5f0b9c9a5ff29b5d05e (diff)
parent065266450ea5519a43bcc199e48d304f1e7038e8 (diff)
downloadcpython-c083537b8731c8f2ffe607a12f96a3eb95f788f7.zip
cpython-c083537b8731c8f2ffe607a12f96a3eb95f788f7.tar.gz
cpython-c083537b8731c8f2ffe607a12f96a3eb95f788f7.tar.bz2
Issue #21538: The plistlib module now supports loading of binary plist files
when reference or offset size is not a power of two.
-rw-r--r--Lib/plistlib.py16
-rw-r--r--Lib/test/test_plistlib.py12
-rw-r--r--Misc/NEWS3
3 files changed, 25 insertions, 6 deletions
diff --git a/Lib/plistlib.py b/Lib/plistlib.py
index dcb0f9c..8c148a8 100644
--- a/Lib/plistlib.py
+++ b/Lib/plistlib.py
@@ -619,10 +619,7 @@ class _BinaryPlistParser:
offset_table_offset
) = struct.unpack('>6xBBQQQ', trailer)
self._fp.seek(offset_table_offset)
- offset_format = '>' + _BINARY_FORMAT[offset_size] * num_objects
- self._ref_format = _BINARY_FORMAT[self._ref_size]
- self._object_offsets = struct.unpack(
- offset_format, self._fp.read(offset_size * num_objects))
+ self._object_offsets = self._read_ints(num_objects, offset_size)
return self._read_object(self._object_offsets[top_object])
except (OSError, IndexError, struct.error):
@@ -638,9 +635,16 @@ class _BinaryPlistParser:
return tokenL
+ def _read_ints(self, n, size):
+ data = self._fp.read(size * n)
+ if size in _BINARY_FORMAT:
+ return struct.unpack('>' + _BINARY_FORMAT[size] * n, data)
+ else:
+ return tuple(int.from_bytes(data[i: i + size], 'big')
+ for i in range(0, size * n, size))
+
def _read_refs(self, n):
- return struct.unpack(
- '>' + self._ref_format * n, self._fp.read(n * self._ref_size))
+ return self._read_ints(n, self._ref_size)
def _read_object(self, offset):
"""
diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py
index bb7cc15..dc2fdf6 100644
--- a/Lib/test/test_plistlib.py
+++ b/Lib/test/test_plistlib.py
@@ -411,6 +411,18 @@ class TestPlistlib(unittest.TestCase):
pl2 = plistlib.loads(data)
self.assertEqual(dict(pl), dict(pl2))
+ def test_nonstandard_refs_size(self):
+ # Issue #21538: Refs and offsets are 24-bit integers
+ data = (b'bplist00'
+ b'\xd1\x00\x00\x01\x00\x00\x02QaQb'
+ b'\x00\x00\x08\x00\x00\x0f\x00\x00\x11'
+ b'\x00\x00\x00\x00\x00\x00'
+ b'\x03\x03'
+ b'\x00\x00\x00\x00\x00\x00\x00\x03'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x13')
+ self.assertEqual(plistlib.loads(data), {'a': 'b'})
+
class TestPlistlibDeprecated(unittest.TestCase):
def test_io_deprecated(self):
diff --git a/Misc/NEWS b/Misc/NEWS
index 53abb67..dd6b8a3 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -89,6 +89,9 @@ Core and Builtins
Library
-------
+- Issue #21538: The plistlib module now supports loading of binary plist files
+ when reference or offset size is not a power of two.
+
- Issue #21455: Add a default backlog to socket.listen().
- Issue #21525: Most Tkinter methods which accepted tuples now accept lists too.