Skip to content

Tolerate empty OTL data when slicing a line of text (mirrors mpdf/mpdf#2197) - #15

Merged
jakejackson1 merged 1 commit into
gravitypdffrom
mirror/2197-otl-slice-empty
Sep 7, 2026
Merged

Tolerate empty OTL data when slicing a line of text (mirrors mpdf/mpdf#2197)#15
jakejackson1 merged 1 commit into
gravitypdffrom
mirror/2197-otl-slice-empty

Conversation

@jakejackson1

Copy link
Copy Markdown
Member

Summary

This mirrors mpdf#2197, which fixes mpdf#2158, so the fork carries the fix while the upstream PR sits open.

Otl::applyOTL() opens by resetting $this->OTLdata to [] and returning early when the string is blank. MultiCell() then does $OTLdata = $this->otl->OTLdata, and every later isset($OTLdata) is satisfied by that empty array — so the empty array travels on into sliceOTLdata(), which reads $OTLdata['group'] and $OTLdata['GPOSinfo'] without checking. On PHP 8 that is two Undefined array key warnings and a Passing null to substr() deprecation for every MultiCell() call with an empty or whitespace-only string, on any non-core font.

sliceOTLdata() already guards char_data. This guards the other two the same way.

Try it

$mpdf = new \Mpdf\Mpdf(['default_font' => 'dejavusans']);
$mpdf->AddPage();
$mpdf->MultiCell(0, 5, '');
$mpdf->Output();

On gravitypdf, with display_errors on:

Warning: Undefined array key "group" in src/Otl.php on line 5751
Deprecated: substr(): Passing null to parameter #1 ($string) of type string is deprecated
Warning: Undefined array key "GPOSinfo" in src/Otl.php on line 5753

On this branch, nothing.

Test plan

  • composer test1052 tests, 2538 assertions, green (gravitypdf is at 1048).
  • composer cs — clean.
  • PHPStan — same 33 findings as gravitypdf, none new.
  • Both new test files fail on gravitypdf and pass here. PHPUnit already turns PHP warnings into test errors, so the assertions are the plain ones the repo uses elsewhere.
More info

Where it differs from upstream

Upstream Here
Writes the defaults into the $OTLdata parameter, then reads it back Guards the two reads inline, so the function does not mutate a copy of its argument on the way past
tests/Issues/Issue2158Test.php installs a set_error_handler to catch the warning Dropped. PHPUnit 9 converts PHP warnings to errors already, so the handler only suppresses the very thing the test is checking; the assertion is assertStringStartsWith('%PDF-', …), as in the ~100 other tests/Issues cases
One test, empty string Adds a whitespace-only case, which reaches a different sliceOTLdata() call site (Mpdf.php:6109, the explicit-line-break branch, rather than Mpdf.php:6350, the last-chunk branch)
Adds tests/Mpdf/OtlTest.php, pinning sliceOTLdata() directly: one populated slice, and one empty-input case
Touches CHANGELOG.md Left alone; the fork's earlier mirrors do the same, so the file stays as upstream has it

Why the guard, not the root cause

The tidier-looking fix is to have applyOTL() leave a complete-but-empty structure (['group' => '', 'GPOSinfo' => [], 'char_data' => []]) instead of []. Ten call sites read $this->otl->OTLdataMpdf::MultiCell(), Mpdf::Cell(), DirectWrite, Form twice, Svg — and several test it for truthiness. Making it non-empty flips those branches for every blank string in the document. Not worth it for a warning.

sliceOTLdata() is a public method that already treats char_data as optional; treating the whole structure as optional is consistent, and it is the only place that reads these keys unguarded.

applyOTL() resets $this->OTLdata to [] and returns early for a blank
string, but MultiCell() takes that empty array as "there is OTL data
here" and hands it to sliceOTLdata(), which reads 'group' and
'GPOSinfo' unconditionally. On PHP 8 that is two "Undefined array key"
warnings plus a null-to-substr() deprecation, for every MultiCell()
call with an empty or whitespace-only string.

Guard the two reads the way 'char_data' is already guarded, rather than
changing what applyOTL() leaves behind — ten call sites read
$this->otl->OTLdata and most test it for truthiness.

Mirrors mpdf#2197 (mpdf#2158).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jakejackson1 jakejackson1 added bug Something isn't working fork-only labels Sep 7, 2026
@jakejackson1
jakejackson1 merged commit dab4db8 into gravitypdf Sep 7, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working fork-only

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant