[issue14455] plistlib unable to read json and binary plist files

Serhiy Storchaka report at bugs.python.org
Wed Jan 15 14:41:07 CET 2014


Serhiy Storchaka added the comment:

> However, I have no idea how to write that file using Apple's APIs.

Look in CFBinaryPList.c. It have a code for creating 128-bit integers:

	    CFSInt128Struct val;
	    val.high = 0;
	    val.low = bigint;
	    *plist = CFNumberCreate(allocator, kCFNumberSInt128Type, &val);

And I suppose that you have at least one way to create such file -- just 
convert plist file in XML format to binary format.

> Keep in mind that this module is intended for interop with Apple's data
> format.

Apple's tool can read and write integers from 2**63 to 2**64-1.

Here is a patch against current sources.

----------
Added file: http://bugs.python.org/file33481/plistlib_big_ints.patch

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue14455>
_______________________________________
-------------- next part --------------
diff -r 1a8149ba3000 Doc/library/plistlib.rst
--- a/Doc/library/plistlib.rst	Wed Jan 15 11:32:35 2014 +0100
+++ b/Doc/library/plistlib.rst	Wed Jan 15 15:22:29 2014 +0200
@@ -107,13 +107,6 @@
    An :exc:`OverflowError` will be raised for integer values that cannot
    be represented in (binary) plist files.
 
-   .. warning::
-
-      For compatibility with Apple's libraries it is possible to write
-      an integer in the range from 2 ** 63 upto (and including) 2 ** 64
-      to binary plists, even though these will be read back as negative
-      values.
-
    .. versionadded: 3.4
 
 
diff -r 1a8149ba3000 Lib/plistlib.py
--- a/Lib/plistlib.py	Wed Jan 15 11:32:35 2014 +0100
+++ b/Lib/plistlib.py	Wed Jan 15 15:22:29 2014 +0200
@@ -879,18 +879,19 @@
                 try:
                     self._fp.write(struct.pack('>Bq', 0x13, value))
                 except struct.error:
-                    raise OverflowError(value)
+                    raise OverflowError(value) from None
             elif value < 1 << 8:
                 self._fp.write(struct.pack('>BB', 0x10, value))
             elif value < 1 << 16:
                 self._fp.write(struct.pack('>BH', 0x11, value))
             elif value < 1 << 32:
                 self._fp.write(struct.pack('>BL', 0x12, value))
+            elif value < 1 << 63:
+                self._fp.write(struct.pack('>Bq', 0x13, value))
+            elif value < 1 << 64:
+                self._fp.write(b'\x14' + value.to_bytes(16, 'big', signed=True))
             else:
-                try:
-                    self._fp.write(struct.pack('>BQ', 0x13, value))
-                except struct.error:
-                    raise OverflowError(value)
+                raise OverflowError(value)
 
         elif isinstance(value, float):
             self._fp.write(struct.pack('>Bd', 0x23, value))
diff -r 1a8149ba3000 Lib/test/test_plistlib.py
--- a/Lib/test/test_plistlib.py	Wed Jan 15 11:32:35 2014 +0100
+++ b/Lib/test/test_plistlib.py	Wed Jan 15 15:22:29 2014 +0200
@@ -152,7 +152,7 @@
 
     def test_int(self):
         for pl in [0, 2**8-1, 2**8, 2**16-1, 2**16, 2**32-1, 2**32,
-                   2**63-1, 1, -2**63]:
+                   2**63-1, 2**64-1, 1, -2**63]:
             for fmt in ALL_FORMATS:
                 with self.subTest(pl=pl, fmt=fmt):
                     data = plistlib.dumps(pl, fmt=fmt)
@@ -163,7 +163,7 @@
                     self.assertEqual(data, data2)
 
         for fmt in ALL_FORMATS:
-            for pl in (2 ** 64 + 1, 2 ** 127-1, -2**64, -2 ** 127):
+            for pl in (2**64, 2**127-1, -2**63-1, -2**127):
                 with self.subTest(pl=pl, fmt=fmt):
                     self.assertRaises(OverflowError, plistlib.dumps,
                                       pl, fmt=fmt)


More information about the Python-bugs-list mailing list