General fix for issue #2278, #2006, ValueError with out of spec metadata

This commit is contained in:
Eric Soroos 2017-09-08 18:15:45 +00:00 committed by wiredfool
parent 1f4699ca5b
commit 488691bda4
3 changed files with 23 additions and 6 deletions

View File

@ -550,11 +550,28 @@ class ImageFileDirectory_v2(collections.MutableMapping):
dest = self._tags_v1 if legacy_api else self._tags_v2
if info.length == 1:
if legacy_api and self.tagtype[tag] in [5, 10]:
# Three branches:
# Spec'd length == 1, Actual length 1, store as element
# Spec'd length == 1, Actual > 1, Warn and truncate. Formerly barfed.
# No Spec, Actual length 1, Formerly (<4.2) returned a 1 element tuple.
# Don't mess with the legacy api, since it's frozen.
if ((info.length == 1) or
(info.length is None and len(values) == 1 and not legacy_api)):
# Don't mess with the legacy api, since it's frozen.
if legacy_api and self.tagtype[tag] in [5, 10]: # rationals
values = values,
dest[tag], = values
try:
dest[tag], = values
except ValueError:
# We've got a builtin tag with 1 expected entry
warnings.warn(
"Metadata Warning, tag %s had too many entries: %s, expected 1" % (
tag, len(values)))
dest[tag] = values[0]
else:
# Spec'd length > 1 or undefined
# Unspec'd, and length > 1
dest[tag] = values
def __delitem__(self, tag):

View File

@ -23,7 +23,7 @@ from collections import namedtuple
class TagInfo(namedtuple("_TagInfo", "value name type length enum")):
__slots__ = []
def __new__(cls, value=None, name="unknown", type=None, length=0, enum=None):
def __new__(cls, value=None, name="unknown", type=None, length=None, enum=None):
return super(TagInfo, cls).__new__(
cls, value, name, type, length, enum or {})

View File

@ -202,8 +202,8 @@ class TestFileTiffMetadata(PillowTestCase):
im.save(out, tiffinfo=info, compression='raw')
reloaded = Image.open(out)
self.assertEqual(0, reloaded.tag_v2[41988][0].numerator)
self.assertEqual(0, reloaded.tag_v2[41988][0].denominator)
self.assertEqual(0, reloaded.tag_v2[41988].numerator)
self.assertEqual(0, reloaded.tag_v2[41988].denominator)
def test_expty_values(self):
data = io.BytesIO(