From 5cdcba36d5678d67eaa7b84e70ca51353c521bbd Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sun, 19 Jul 2026 19:46:37 +0300 Subject: [PATCH] Reject input that spans multiple paragraphs raqm expects the text to be a single paragraph. Inputting multiple paragraphs at once is undefined behaviour. Enforce this by making raqm_layout() fail when the text contains a paragraph separator, and use stronger words about this requirement on raqm_set_text() docs. Also drop the disabled cursor-position-GB3 test, at it contains CR+LF. --- src/raqm.c | 20 ++++++++++++--- tests/cursor-position-GB3.test | 45 ---------------------------------- tests/meson.build | 1 - 3 files changed, 17 insertions(+), 49 deletions(-) delete mode 100644 tests/cursor-position-GB3.test diff --git a/src/raqm.c b/src/raqm.c index 05685afd..07eb2da9 100644 --- a/src/raqm.c +++ b/src/raqm.c @@ -512,8 +512,8 @@ raqm_clear_contents (raqm_t *rq) * @len: the length of @text. * * Adds @text to @rq to be used for layout. It must be a valid UTF-32 text, any - * invalid characters will be replaced with U+FFFD. The text should typically - * represent a full paragraph, since doing the layout of chunks of text + * invalid characters will be replaced with U+FFFD. The text must + * represent a single full paragraph, since doing the layout of chunks of text * separately can give improper output. * * Return value: @@ -1300,6 +1300,15 @@ _raqm_itemize (raqm_t *rq); static bool _raqm_shape (raqm_t *rq); +static bool +_raqm_is_paragraph_separator (uint32_t ch) +{ + /* Unicode characters with Bidi class B (Paragraph_Separator). */ + return ch == 0x000A || ch == 0x000D || + ch == 0x001C || ch == 0x001D || ch == 0x001E || + ch == 0x0085 || ch == 0x2029; +} + /** * raqm_layout: * @rq: a #raqm_t. @@ -1309,7 +1318,8 @@ _raqm_shape (raqm_t *rq); * text shaping, and any other part of the layout process. * * Return value: - * `true` if the layout process was successful, `false` otherwise. + * `true` if the layout process was successful, `false` otherwise. It also fails + * if the text is not a single paragraph (see raqm_set_text()). * * Since: 0.1 */ @@ -1329,6 +1339,10 @@ raqm_layout (raqm_t *rq) { if (!rq->text_info[i].ftface) return false; + + /* The text must be a single paragraph. */ + if (_raqm_is_paragraph_separator (rq->text[i])) + return false; } if (!_raqm_itemize (rq)) diff --git a/tests/cursor-position-GB3.test b/tests/cursor-position-GB3.test deleted file mode 100644 index f35d867b..00000000 --- a/tests/cursor-position-GB3.test +++ /dev/null @@ -1,45 +0,0 @@ -fonts/sha1sum/bcb3b98eb67ece19b8b709f77143d91bcb3d95eb.ttf -om\r\nan ---cluster 2 --position 3000 -Direction is: DEFAULT - -Before script detection: -script for ch[0] Latn -script for ch[1] Latn -script for ch[2] Zyyy -script for ch[3] Zyyy -script for ch[4] Latn -script for ch[5] Latn - -After script detection: -script for ch[0] Latn -script for ch[1] Latn -script for ch[2] Latn -script for ch[3] Latn -script for ch[4] Latn -script for ch[5] Latn - -Number of runs before script itemization: 1 - -BiDi Runs: -run[0]: start: 0 length: 6 level: 0 - -Number of runs after script itemization: 1 - -Final Runs: -run[0]: start: 0 length: 6 direction: ltr script: Latn font: Amiri - -Glyph information: -glyph [82] x_offset: 0 y_offset: 0 x_advance: 1018 font: Amiri -glyph [80] x_offset: 0 y_offset: 0 x_advance: 1580 font: Amiri -glyph [0] x_offset: 0 y_offset: 0 x_advance: 748 font: Amiri -glyph [0] x_offset: 0 y_offset: 0 x_advance: 748 font: Amiri -glyph [68] x_offset: 0 y_offset: 0 x_advance: 862 font: Amiri -glyph [81] x_offset: 0 y_offset: 0 x_advance: 1064 font: Amiri - -UTF-32 clusters: 00 01 02 03 04 05 -UTF-8 clusters: 00 01 02 03 04 05 - -The position is 4094 at index 3 - -The start-index is 3 at position 3000 diff --git a/tests/meson.build b/tests/meson.build index 4316f2e8..c6b35b88 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -16,7 +16,6 @@ tests = [ 'cursor-position-2.test', 'cursor-position-3.test', 'cursor-position-4.test', - #'cursor-position-GB3.test', 'cursor-position-GB4.test', 'cursor-position-GB5.test', 'cursor-position-GB8a.test',