diff --git a/.gitattributes b/.gitattributes index d45604f98..b3b2b25ed 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,3 +4,8 @@ # Explicitly declare text files you want to always be normalized and converted # to native line endings on checkout. *.py text + +# Font files are binary (so that autocrlf doesn't muck with them) +*.lwfn binary +*.pfa binary +*.pfb binary diff --git a/Lib/fontTools/t1Lib/__init__.py b/Lib/fontTools/t1Lib/__init__.py index db5189a59..9106f34a1 100644 --- a/Lib/fontTools/t1Lib/__init__.py +++ b/Lib/fontTools/t1Lib/__init__.py @@ -273,7 +273,9 @@ def writeOther(path, data, dohex=False): # decryption tools EEXECBEGIN = b"currentfile eexec" -EEXECEND = b'0' * 64 +# The spec allows for 512 ASCII zeros interrupted by arbitrary whitespace to +# follow eexec +EEXECEND = re.compile(b'(0[ \t\r\n]*){512}', flags=re.M) EEXECINTERNALEND = b"currentfile closefile" EEXECBEGINMARKER = b"%-- eexec start\r" EEXECENDMARKER = b"%-- eexec end\r" @@ -312,9 +314,10 @@ def findEncryptedChunks(data): if eBegin < 0: break eBegin = eBegin + len(EEXECBEGIN) + 1 - eEnd = data.find(EEXECEND, eBegin) - if eEnd < 0: + endMatch = EEXECEND.search(data, eBegin) + if not endMatch: raise T1Error("can't find end of eexec part") + eEnd = endMatch.start() cypherText = data[eBegin:eEnd + 2] if isHex(cypherText[:4]): cypherText = deHexString(cypherText) diff --git a/Tests/t1Lib/data/TestT1-weird-zeros.pfa b/Tests/t1Lib/data/TestT1-weird-zeros.pfa new file mode 100644 index 000000000..666b36bcc --- /dev/null +++ b/Tests/t1Lib/data/TestT1-weird-zeros.pfa @@ -0,0 +1,63 @@ +%!FontType1-1.1: TestT1-Regular 1.0 +%%BeginResource: font TestT1-Regular +12 dict dup begin +/FontType 1 def +/FontName /TestT1-Regular def +/FontInfo 14 dict dup begin +/version (1.0) def +/Notice (Test T1 is not a trademark of FontTools.) def +/Copyright (Copyright c 2015 by FontTools. No rights reserved.) def +/FullName (Test T1) def +/FamilyName (Test T1) def +/Weight (Regular) def +/ItalicAngle 0.000000 def +/isFixedPitch false def +/UnderlinePosition -75.000000 def +/UnderlineThickness 50.000000 def +/FSType 0 def +end def +/PaintType 0 def +/FontMatrix [0.001 0 0 0.001 0 0] def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +def +/FontBBox {50.000000 0.000000 668.000000 750.000000} def +end +currentfile eexec bab431ea06bb0a1031e1aa11919e714ac1ac5197cb08b39a4d7e746fca0af12d89ac0ebd1bc11ab1 +b3887b922efcec739534242d2fd22e7c30e3edce24b93798627e1ac3387816a8c4b84d76047dada8 +28b2ad27c5603046fecbc2a97adc5c37a68912324d2d435f2ee0ccc38df10ba1271a1c9af8897a6d +6e425cd7d18fd6bd64c2adadb74365bc101a850841669886291e158cbfa7f204b3fe0ba49ffe0c80 +4f6795d32eb770c5fcd38a3879c06a4bb87b2d3ab100d8c2b5f89e9be99248575575025c66381446 +e4d9183674880aef57fb2032a1e00431133b16f6d758de7c3d0c48a0fada1d40034742a69fb3a6f9 +450d2251e659158a04697cbfa70907346d27d37ef683284385c44a1b5089bd29b4629b6483122dc8 +cbce7327bdc33dd30e6fcdb346c0ddaf433a5ac740423aa35639b2386673832f5ae8cc380e9703ba +d3369533bfa85af9f56a090c9d97f5fc26ed102c07b647137e83632be51a65a532bd26430b59a31c +3cb037ded351c1d4e944733feb30a3e6f81c1a7b74ac4e0eadbe705412d47991c246e8820876bbc6 +1f6a3e264ae6b2ad4b864b0d7abee289308bea26eb15d00d2b9103861386e0a5f1802ba06f916810 +62110d2b1c3641806f78eea365614f440b580185e84bac6f87bee36108d95174c786600cf0e9dc4a +5545d1a84cfe8392115c0b7027c17fd460481d21f684af32204085690946327bfded992852645149 +8d44150d2495bd2efe0db6a450c6e28d0a52ca234e252129d5095596b0d8de096682d2eb00bc8320 +f257fd653b05a22eab7a193ccc315a6ee274a03ff1fdf443b310157a02656ca4b06c581dca8ced72 +c6ddcab26eb856ad1093452c587438b7f8408c1311e19254955914612c09828fd4d4fc2b8b0406ea +2ee38348a8bdab88a77b8033366b2e469834c01b7bd73207b7c67756937c7a9232947fde2e0ea327 +7b7d610e601b91389ccbcdd813c87db5333c0c723e48d3ef69285f246327978ce68ae9081076a227 +1a962a2a10e2b1147ec40b0f6553a00c8b329118569d16fe04a4fa195caf1b04c52c9a562b72e0cd +e411d747af796b9d2fb086ed927efb0e5fc9f50aa18aaf4949cba0de0805210620a19eec4319dfef +a74d9d13d16f8ad793323a231347e6b40022a1100c1e064b8679c1da63a26dfb217a6037096ad796 +320da5a9d0526eed51d7d64d3223e285c1a8c70780c59ecc9dd9bc90a0f84ffa038834918cebe247 +f6e8fa4ca0654019196388f2df008e63bc32c8e5e686dbb69193b7749638c22b389fb1f090fbb007 +fdb8a6ee4e4b29e123fe1652fe72239bd2c8 +00000000000 00000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000 000000000000000000000000000000000 +00000000000000000000000 +00000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 000000000000000000000000 +00 +00000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000 00000000000 +00000000000000000000 00000000000000000000000000000000000000000000 +00000000000000000000 +00000000000000000000000000000000000000000000 +cleartomark +%%EndResource +%%EOF diff --git a/Tests/t1Lib/t1Lib_test.py b/Tests/t1Lib/t1Lib_test.py index 385dad0d9..153254d6e 100644 --- a/Tests/t1Lib/t1Lib_test.py +++ b/Tests/t1Lib/t1Lib_test.py @@ -14,6 +14,7 @@ DATADIR = os.path.join(CWD, 'data') LWFN = os.path.join(DATADIR, 'TestT1-Regular.lwfn') PFA = os.path.join(DATADIR, 'TestT1-Regular.pfa') PFB = os.path.join(DATADIR, 'TestT1-Regular.pfb') +WEIRD_ZEROS = os.path.join(DATADIR, 'TestT1-weird-zeros.pfa') class FindEncryptedChunksTest(unittest.TestCase): @@ -28,6 +29,14 @@ class FindEncryptedChunksTest(unittest.TestCase): self.assertTrue(chunks[1][0]) self.assertFalse(chunks[2][0]) + def test_findEncryptedChunks_weird_zeros(self): + with open(WEIRD_ZEROS, 'rb') as f: + data = f.read() + + # Just assert that this doesn't raise any exception for not finding the + # end of eexec + t1Lib.findEncryptedChunks(data) + class DecryptType1Test(unittest.TestCase):