summaryrefslogtreecommitdiffstats
path: root/Lib/plistlib.py
diff options
context:
space:
mode:
authorMiss Skeleton (bot) <31488909+miss-islington@users.noreply.github.com>2020-11-02 21:34:46 (GMT)
committerGitHub <noreply@github.com>2020-11-02 21:34:46 (GMT)
commite277cb76989958fdbc092bf0b2cb55c43e86610a (patch)
tree8d698547371d7b995e7200ff469fb8411891fd2c /Lib/plistlib.py
parent723e21a8e79815ae77474d1f21b9847b9c9bdbeb (diff)
downloadcpython-e277cb76989958fdbc092bf0b2cb55c43e86610a.zip
cpython-e277cb76989958fdbc092bf0b2cb55c43e86610a.tar.gz
cpython-e277cb76989958fdbc092bf0b2cb55c43e86610a.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. (cherry picked from commit 34637a0ce21e7261b952fbd9d006474cc29b681f) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
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()