Merge pull request #1742 from fonttools/name-handle-duplicate-name-records-different-string-types

[name] Handle duplicate name records with different `string` types
This commit is contained in:
Nikolaus Waxweiler 2019-10-11 18:53:45 +02:00 committed by GitHub
commit cea5abd676
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 16 deletions

View File

@ -459,22 +459,32 @@ class NameRecord(object):
if type(self) != type(other):
return NotImplemented
# implemented so that list.sort() sorts according to the spec.
selfTuple = (
getattr(self, "platformID", None),
getattr(self, "platEncID", None),
getattr(self, "langID", None),
getattr(self, "nameID", None),
getattr(self, "string", None),
)
otherTuple = (
getattr(other, "platformID", None),
getattr(other, "platEncID", None),
getattr(other, "langID", None),
getattr(other, "nameID", None),
getattr(other, "string", None),
)
return selfTuple < otherTuple
try:
# implemented so that list.sort() sorts according to the spec.
selfTuple = (
self.platformID,
self.platEncID,
self.langID,
self.nameID,
self.toBytes(),
)
otherTuple = (
other.platformID,
other.platEncID,
other.langID,
other.nameID,
other.toBytes(),
)
return selfTuple < otherTuple
except (UnicodeEncodeError, AttributeError):
# This can only happen for
# 1) an object that is not a NameRecord, or
# 2) an unlikely incomplete NameRecord object which has not been
# fully populated, or
# 3) when all IDs are identical but the strings can't be encoded
# for their platform encoding.
# In all cases it is best to return NotImplemented.
return NotImplemented
def __repr__(self):
return "<NameRecord NameID=%d; PlatformID=%d; LanguageID=%d>" % (

View File

@ -53,6 +53,26 @@ class NameTableTest(unittest.TestCase):
with self.assertRaises(TypeError):
table.setName(1.000, 5, 1, 0, 0)
def test_names_sort_bytes_str(self):
# Corner case: If a user appends a name record directly to `names`, the
# `__lt__` method on NameRecord may run into duplicate name records where
# one `string` is a str and the other one bytes, leading to an exception.
table = table__n_a_m_e()
table.names = [
makeName("Test", 25, 3, 1, 0x409),
makeName("Test".encode("utf-16be"), 25, 3, 1, 0x409),
]
table.compile(None)
def test_names_sort_bytes_str_encoding_error(self):
table = table__n_a_m_e()
table.names = [
makeName("Test寬", 25, 1, 0, 0),
makeName("Test鬆鬆", 25, 1, 0, 0),
]
with self.assertRaises(TypeError):
table.names.sort()
def test_addName(self):
table = table__n_a_m_e()
nameIDs = []