diff options
author | Ned Deily <nad@acm.org> | 2011-05-28 09:19:19 (GMT) |
---|---|---|
committer | Ned Deily <nad@acm.org> | 2011-05-28 09:19:19 (GMT) |
commit | b8e59f77e65ba4caeda8d910bd66df01a468cbea (patch) | |
tree | fac7e3f59b617ce67aefd954f0fd67abf099b094 /Lib/plistlib.py | |
parent | 9a7c524dc613595e0d88b3e22b0e49b69467ffc4 (diff) | |
download | cpython-b8e59f77e65ba4caeda8d910bd66df01a468cbea.zip cpython-b8e59f77e65ba4caeda8d910bd66df01a468cbea.tar.gz cpython-b8e59f77e65ba4caeda8d910bd66df01a468cbea.tar.bz2 |
Issue #985064: Make plistlib more resilient to faulty input plists.
Patch by Mher Movsisyan.
Diffstat (limited to 'Lib/plistlib.py')
-rw-r--r-- | Lib/plistlib.py | 59 |
1 files changed, 37 insertions, 22 deletions
diff --git a/Lib/plistlib.py b/Lib/plistlib.py index fbba791..fe622ad 100644 --- a/Lib/plistlib.py +++ b/Lib/plistlib.py @@ -68,13 +68,15 @@ def readPlist(pathOrFile): usually is a dictionary). """ didOpen = False - if isinstance(pathOrFile, str): - pathOrFile = open(pathOrFile, 'rb') - didOpen = True - p = PlistParser() - rootObject = p.parse(pathOrFile) - if didOpen: - pathOrFile.close() + try: + if isinstance(pathOrFile, str): + pathOrFile = open(pathOrFile, 'rb') + didOpen = True + p = PlistParser() + rootObject = p.parse(pathOrFile) + finally: + if didOpen: + pathOrFile.close() return rootObject @@ -83,15 +85,17 @@ def writePlist(rootObject, pathOrFile): file name or a (writable) file object. """ didOpen = False - if isinstance(pathOrFile, str): - pathOrFile = open(pathOrFile, 'wb') - didOpen = True - writer = PlistWriter(pathOrFile) - writer.writeln("<plist version=\"1.0\">") - writer.writeValue(rootObject) - writer.writeln("</plist>") - if didOpen: - pathOrFile.close() + try: + if isinstance(pathOrFile, str): + pathOrFile = open(pathOrFile, 'wb') + didOpen = True + writer = PlistWriter(pathOrFile) + writer.writeln("<plist version=\"1.0\">") + writer.writeValue(rootObject) + writer.writeln("</plist>") + finally: + if didOpen: + pathOrFile.close() def readPlistFromBytes(data): @@ -352,7 +356,6 @@ class Data: def __repr__(self): return "%s(%s)" % (self.__class__.__name__, repr(self.data)) - class PlistParser: def __init__(self): @@ -362,11 +365,11 @@ class PlistParser: def parse(self, fileobj): from xml.parsers.expat import ParserCreate - parser = ParserCreate() - parser.StartElementHandler = self.handleBeginElement - parser.EndElementHandler = self.handleEndElement - parser.CharacterDataHandler = self.handleData - parser.ParseFile(fileobj) + self.parser = ParserCreate() + self.parser.StartElementHandler = self.handleBeginElement + self.parser.EndElementHandler = self.handleEndElement + self.parser.CharacterDataHandler = self.handleData + self.parser.ParseFile(fileobj) return self.root def handleBeginElement(self, element, attrs): @@ -385,12 +388,18 @@ class PlistParser: def addObject(self, value): if self.currentKey is not None: + if not isinstance(self.stack[-1], type({})): + raise ValueError("unexpected element at line %d" % + self.parser.CurrentLineNumber) self.stack[-1][self.currentKey] = value self.currentKey = None elif not self.stack: # this is the root object self.root = value else: + if not isinstance(self.stack[-1], type([])): + raise ValueError("unexpected element at line %d" % + self.parser.CurrentLineNumber) self.stack[-1].append(value) def getData(self): @@ -405,9 +414,15 @@ class PlistParser: self.addObject(d) self.stack.append(d) def end_dict(self): + if self.currentKey: + raise ValueError("missing value for key '%s' at line %d" % + (self.currentKey,self.parser.CurrentLineNumber)) self.stack.pop() def end_key(self): + if self.currentKey or not isinstance(self.stack[-1], type({})): + raise ValueError("unexpected key at line %d" % + self.parser.CurrentLineNumber) self.currentKey = self.getData() def begin_array(self, attrs): |