Raise UnicodeDecodeError for structurally invalid names

This will make it impossible to process fonts with super-broken
name tables. But we do not handle arbitrary broken fonts anyway,
so this is arguably better than silently ignoring junk content.
Resolves a review comment in #235.

In the unit test, replace calls of deprecated unittest.assertEquals()
by calls of unittest.assertEqual().
This commit is contained in:
Sascha Brawer 2015-04-15 23:54:01 -07:00 committed by Behdad Esfahbod
parent 3f36721d87
commit b82b50cbfb
2 changed files with 29 additions and 14 deletions

View File

@ -174,10 +174,7 @@ class NameRecord(object):
encoding = self.getEncoding() encoding = self.getEncoding()
if encoding == None: if encoding == None:
return None return None
try:
return tounicode(self.string, encoding=encoding) return tounicode(self.string, encoding=encoding)
except UnicodeDecodeError:
return None
def toBytes(self): def toBytes(self):
return tobytes(self.string, encoding=self.getEncoding()) return tobytes(self.string, encoding=self.getEncoding())

View File

@ -6,6 +6,28 @@ from ._n_a_m_e import NameRecord
class NameRecordTest(unittest.TestCase): class NameRecordTest(unittest.TestCase):
def makeName(self, text, nameID, platformID, platEncID, langID):
name = NameRecord()
name.nameID, name.platformID, name.platEncID, name.langID = (nameID, platformID, platEncID, langID)
name.string = text.encode(name.getEncoding())
return name
def test_toUnicode_utf16be(self):
name = self.makeName("Foo Bold", 111, 0, 2, 7)
self.assertEqual("utf-16be", name.getEncoding())
self.assertEqual("Foo Bold", name.toUnicode())
def test_toUnicode_macroman(self):
name = self.makeName("Foo Italic", 222, 1, 0, 7) # MacRoman
self.assertEqual("macroman", name.getEncoding())
self.assertEqual("Foo Italic", name.toUnicode())
def test_toUnicode_UnicodeDecodeError(self):
name = self.makeName("Foo Bold", 111, 0, 2, 7)
self.assertEqual("utf-16be", name.getEncoding())
name.string = b"X" # invalid utf-16be sequence
self.assertRaises(UnicodeDecodeError, name.toUnicode)
def toXML(self, name): def toXML(self, name):
writer = XMLWriter(StringIO()) writer = XMLWriter(StringIO())
name.toXML(writer, ttFont=None) name.toXML(writer, ttFont=None)
@ -13,20 +35,16 @@ class NameRecordTest(unittest.TestCase):
return xml.split(writer.newlinestr.decode("utf-8"))[1:] return xml.split(writer.newlinestr.decode("utf-8"))[1:]
def test_toXML_utf16be(self): def test_toXML_utf16be(self):
name = NameRecord() name = self.makeName("Foo Bold", 111, 0, 2, 7)
name.string = "Foo Bold".encode("utf-16be") self.assertEqual([
name.nameID, name.platformID, name.platEncID, name.langID = (111, 0, 2, 7)
self.assertEquals([
'<namerecord nameID="111" platformID="0" platEncID="2" langID="0x7">', '<namerecord nameID="111" platformID="0" platEncID="2" langID="0x7">',
' Foo Bold', ' Foo Bold',
'</namerecord>' '</namerecord>'
], self.toXML(name)) ], self.toXML(name))
def test_toXML_macroman(self): def test_toXML_macroman(self):
name = NameRecord() name = self.makeName("Foo Italic", 222, 1, 0, 7) # MacRoman
name.string = "Foo Italic".encode("macroman") self.assertEqual([
name.nameID, name.platformID, name.platEncID, name.langID = (222, 1, 0, 7)
self.assertEquals([
'<namerecord nameID="222" platformID="1" platEncID="0" langID="0x7" unicode="True">', '<namerecord nameID="222" platformID="1" platEncID="0" langID="0x7" unicode="True">',
' Foo Italic', ' Foo Italic',
'</namerecord>' '</namerecord>'
@ -36,7 +54,7 @@ class NameRecordTest(unittest.TestCase):
name = NameRecord() name = NameRecord()
name.string = b"B\x8arli" name.string = b"B\x8arli"
name.nameID, name.platformID, name.platEncID, name.langID = (333, 1, 9876, 7) name.nameID, name.platformID, name.platEncID, name.langID = (333, 1, 9876, 7)
self.assertEquals([ self.assertEqual([
'<namerecord nameID="333" platformID="1" platEncID="9876" langID="0x7" unicode="False">', '<namerecord nameID="333" platformID="1" platEncID="9876" langID="0x7" unicode="False">',
' B&#138;rli', ' B&#138;rli',
'</namerecord>' '</namerecord>'
@ -57,5 +75,5 @@ class NameRecordTest(unittest.TestCase):
name.nameID, name.platformID, name.platEncID, name.langID = (123, 1, 1, 0) name.nameID, name.platformID, name.platEncID, name.langID = (123, 1, 1, 0)
self.assertEqual(name.toUnicode(), unichr(0x2122)) self.assertEqual(name.toUnicode(), unichr(0x2122))
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()