From acf318b87c63cba1ac58b6dad96810a07bff1001 Mon Sep 17 00:00:00 2001 From: VincentGuinaudeau Date: Thu, 14 Nov 2019 12:08:04 +0100 Subject: [PATCH] comments, test and changelog entry for fix when a character is too bigger than the width of the text. --- CHANGELOG.md | 1 + lib/line_wrapper.js | 1 + tests/unit/text.spec.js | 123 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e12a683..9bef297 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## pdfkit changelog ### Unreleased + - Fix infinite loop when an individual character is bigger than the width of the text. - Fix infinite loop when text is positioned after page right margin - Allow links in continued text to be stopped by setting link to null diff --git a/lib/line_wrapper.js b/lib/line_wrapper.js index e44bba0..16494a5 100644 --- a/lib/line_wrapper.js +++ b/lib/line_wrapper.js @@ -123,6 +123,7 @@ class LineWrapper extends EventEmitter { } } + // check for the edge case where a single character cannot fit into a line. if (l === 0 && this.spaceLeft === this.lineWidth) { l = 1; } diff --git a/tests/unit/text.spec.js b/tests/unit/text.spec.js index f8902e9..dcf181e 100644 --- a/tests/unit/text.spec.js +++ b/tests/unit/text.spec.js @@ -15,7 +15,7 @@ describe('Text', () => { test('with simple content', () => { const docData = logData(document); - const textStream = new Buffer( + const textStream = Buffer.from( `1 0 0 -1 0 792 cm q 1 0 0 -1 0 792 cm @@ -47,7 +47,7 @@ Q test('with content ending after page right margin', () => { const docData = logData(document); - const textStream = new Buffer( + const textStream = Buffer.from( `1 0 0 -1 0 792 cm q 1 0 0 -1 0 792 cm @@ -68,6 +68,125 @@ Q `5 0 obj`, `<< /Length 117 +>>`, + `stream`, + textStream, + `\nendstream`, + `endobj` + ]); + }); + + test('with line too thin to contain a single character', () => { + const docData = logData(document); + + const text = 'simple text'; + const textStream = Buffer.from( + `1 0 0 -1 0 792 cm +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 773.384 Tm +/F1 12 Tf +[<73> 0] TJ +ET +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 759.512 Tm +/F1 12 Tf +[<69> 0] TJ +ET +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 745.64 Tm +/F1 12 Tf +[<6d> 0] TJ +ET +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 731.768 Tm +/F1 12 Tf +[<70> 0] TJ +ET +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 717.896 Tm +/F1 12 Tf +[<6c> 0] TJ +ET +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 704.024 Tm +/F1 12 Tf +[<65> 0] TJ +ET +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 690.152 Tm +/F1 12 Tf +[<2074> 0] TJ +ET +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 676.28 Tm +/F1 12 Tf +[<65> 0] TJ +ET +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 662.408 Tm +/F1 12 Tf +[<78> 0] TJ +ET +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 10 648.536 Tm +/F1 12 Tf +[<74> 0] TJ +ET +Q +`, + 'binary' + ); + + // before this test, this case used to make the code run into an infinite loop. + // To handle regresion gracefully and avoid stucking this test into an infinite loop, + // we look out for a side effect of this infinite loop, witch is adding and infinite number of pages. + // Nomaly, there should not be any page added to the document. + + document.on("pageAdded", () => { + const pageRange = document.bufferedPageRange(); + const newPageIndex = pageRange.start + pageRange.count; + // We try restrict the fail condition to only infinite loop, so we wait for several pages to be added. + if (newPageIndex > 10) { + throw new Error("Infinite loop detected"); + } + }); + + document.text(text, 10, 10, {width: 2}); + document.end(); + + expect(docData).toContainChunk([ + `5 0 obj`, + `<< +/Length 738 >>`, `stream`, textStream,