summaryrefslogtreecommitdiffstats
path: root/Lib/plistlib.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2020-11-02 21:01:40 (GMT)
committerGitHub <noreply@github.com>2020-11-02 21:01:40 (GMT)
commit34637a0ce21e7261b952fbd9d006474cc29b681f (patch)
tree39914654a8ddafa8a95822ae5d180b154ef1105d /Lib/plistlib.py
parent6fdfcec5b11f44f27aae3d53ddeb004150ae1f61 (diff)
downloadcpython-34637a0ce21e7261b952fbd9d006474cc29b681f.zip
cpython-34637a0ce21e7261b952fbd9d006474cc29b681f.tar.gz
cpython-34637a0ce21e7261b952fbd9d006474cc29b681f.tar.bz2
bpo-42103: Improve validation of Plist files. (GH-22882)
* Prevent some possible DoS attacks via providing invalid Plist files with extremely large number of objects or collection sizes. * Raise InvalidFileException for too large bytes and string size instead of returning garbage. * Raise InvalidFileException instead of ValueError for specific invalid datetime (NaN). * Raise InvalidFileException instead of TypeError for non-hashable dict keys. * Add more tests for invalid Plist files.
Diffstat (limited to 'Lib/plistlib.py')
-rw-r--r--Lib/plistlib.py26
1 files changed, 18 insertions, 8 deletions
diff --git a/Lib/plistlib.py b/Lib/plistlib.py
index a740351..83b214e 100644
--- a/Lib/plistlib.py
+++ b/Lib/plistlib.py
@@ -477,7 +477,7 @@ class _BinaryPlistParser:
return self._read_object(top_object)
except (OSError, IndexError, struct.error, OverflowError,
- UnicodeDecodeError):
+ ValueError):
raise InvalidFileException()
def _get_size(self, tokenL):
@@ -493,7 +493,7 @@ class _BinaryPlistParser:
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)
+ return struct.unpack(f'>{n}{_BINARY_FORMAT[size]}', data)
else:
if not size or len(data) != size * n:
raise InvalidFileException()
@@ -553,14 +553,22 @@ class _BinaryPlistParser:
elif tokenH == 0x40: # data
s = self._get_size(tokenL)
result = self._fp.read(s)
+ if len(result) != s:
+ raise InvalidFileException()
elif tokenH == 0x50: # ascii string
s = self._get_size(tokenL)
- result = self._fp.read(s).decode('ascii')
+ data = self._fp.read(s)
+ if len(data) != s:
+ raise InvalidFileException()
+ result = data.decode('ascii')
elif tokenH == 0x60: # unicode string
- s = self._get_size(tokenL)
- result = self._fp.read(s * 2).decode('utf-16be')
+ s = self._get_size(tokenL) * 2
+ data = self._fp.read(s)
+ if len(data) != s:
+ raise InvalidFileException()
+ result = data.decode('utf-16be')
elif tokenH == 0x80: # UID
# used by Key-Archiver plist files
@@ -585,9 +593,11 @@ class _BinaryPlistParser:
obj_refs = self._read_refs(s)
result = self._dict_type()
self._objects[ref] = result
- for k, o in zip(key_refs, obj_refs):
- result[self._read_object(k)] = self._read_object(o)
-
+ try:
+ for k, o in zip(key_refs, obj_refs):
+ result[self._read_object(k)] = self._read_object(o)
+ except TypeError:
+ raise InvalidFileException()
else:
raise InvalidFileException()