From f7c1407703fd9bfc45a13f3e5b7024b74eb034c7 Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Mon, 22 May 2023 12:15:30 +0100 Subject: [PATCH 1/2] Add test to reproduce DSIG split by XML buffered parser --- ...ip_DSIG_split_at_XML_parse_buffer_size.ttx | 224 ++++++++++++++++++ Tests/ttx/ttx_test.py | 33 +++ 2 files changed, 257 insertions(+) create mode 100644 Tests/ttx/data/roundtrip_DSIG_split_at_XML_parse_buffer_size.ttx diff --git a/Tests/ttx/data/roundtrip_DSIG_split_at_XML_parse_buffer_size.ttx b/Tests/ttx/data/roundtrip_DSIG_split_at_XML_parse_buffer_size.ttx new file mode 100644 index 000000000..cbab6111d --- /dev/null +++ b/Tests/ttx/data/roundtrip_DSIG_split_at_XML_parse_buffer_size.ttx @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HelloTestFont + + + TotallyNormal + + + HelloTestFont-TotallyNormal + + + HalloTestFont + + + TotaalNormaal + + + HelloTestFont + + + TotallyNormal + + + HelloTestFont-TotallyNormal + + + HalloTestFont + + + TotaalNormaal + + + + + + + + + + + + + + + + + + + + + + + + + +-----BEGIN PKCS7----- +0000000100000000 +-----END PKCS7----- + + + + diff --git a/Tests/ttx/ttx_test.py b/Tests/ttx/ttx_test.py index d4a27f36b..be009b8aa 100644 --- a/Tests/ttx/ttx_test.py +++ b/Tests/ttx/ttx_test.py @@ -1,7 +1,9 @@ from fontTools.misc.testTools import parseXML from fontTools.misc.timeTools import timestampSinceEpoch from fontTools.ttLib import TTFont, TTLibError +from fontTools.ttLib.tables.DefaultTable import DefaultTable from fontTools import ttx +import base64 import getopt import logging import os @@ -1016,6 +1018,37 @@ def test_main_ttx_compile_stdin_to_stdout(tmp_path): assert outpath.is_file() +def test_roundtrip_DSIG_split_at_XML_parse_buffer_size(tmp_path): + inpath = Path("Tests").joinpath( + "ttx", "data", "roundtrip_DSIG_split_at_XML_parse_buffer_size.ttx" + ) + font = TTFont() + font.importXML(inpath) + font["DMMY"] = DefaultTable(tag="DMMY") + # just enough dummy bytes to hit the cut off point whereby DSIG data gets + # split into two chunks and triggers the bug from + # https://github.com/fonttools/fonttools/issues/2614 + font["DMMY"].data = b"\x01\x02\x03\x04" * 2438 + font.saveXML(tmp_path / "roundtrip_DSIG_split_at_XML_parse_buffer_size.ttx") + + outpath = tmp_path / "font.ttf" + args = [ + sys.executable, + "-m", + "fontTools.ttx", + "-q", + "-o", + str(outpath), + str(tmp_path / "roundtrip_DSIG_split_at_XML_parse_buffer_size.ttx"), + ] + subprocess.run(args, check=True) + + assert outpath.is_file() + assert TTFont(outpath)["DSIG"].signatureRecords[0].pkcs7 == base64.b64decode( + b"0000000100000000" + ) + + # --------------------------- # support functions for tests # --------------------------- From e8f8a6c40df288c2e5dddf913c03f08c913d9ee0 Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Mon, 22 May 2023 11:57:46 +0100 Subject: [PATCH 2/2] xmlReader: join consecutive text data that had been cut by buffered parser Fixes https://github.com/fonttools/fonttools/issues/2614 --- Lib/fontTools/misc/xmlReader.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Lib/fontTools/misc/xmlReader.py b/Lib/fontTools/misc/xmlReader.py index ce9de579b..d8e502f14 100644 --- a/Lib/fontTools/misc/xmlReader.py +++ b/Lib/fontTools/misc/xmlReader.py @@ -148,7 +148,19 @@ class XMLReader(object): def _characterDataHandler(self, data): if self.stackSize > 1: - self.contentStack[-1].append(data) + # parser parses in chunks, so we may get multiple calls + # for the same text node; thus we need to append the data + # to the last item in the content stack: + # https://github.com/fonttools/fonttools/issues/2614 + if ( + data != "\n" + and self.contentStack[-1] + and isinstance(self.contentStack[-1][-1], str) + and self.contentStack[-1][-1] != "\n" + ): + self.contentStack[-1][-1] += data + else: + self.contentStack[-1].append(data) def _endElementHandler(self, name): self.stackSize = self.stackSize - 1