Skip to content

Fix PHP 8.5.12 ZTS build: patch ext/xml for Expat, skip rfc1867 OOM tests - #1

Merged
llupa merged 1 commit into
llupa:security/php-8.5.12-ztsfrom
rmetzler:fix/php-8.5.12-zts-tests
Oct 22, 2026
Merged

llupa merged 1 commit into
llupa:security/php-8.5.12-ztsfrom
rmetzler:fix/php-8.5.12-zts-tests

Conversation

@rmetzler

@rmetzler rmetzler commented Oct 21, 2026 •

Copy link
Copy Markdown

Fixes the build-base failures of Endava#145 (arm64, amd64). Both fail in abuild -r because check() reports 4 failing PHP tests:

  • ext/xml/tests/gh14637.phpt
  • ext/xml/tests/oom_xml_parse_ns.phpt
  • tests/basic/oom_rfc1867_mb_encoding.phpt
  • tests/basic/oom_rfc1867_upload_progress.phpt

The test diffs are missing from the CI log because BuildKit clips the output at 2 MiB, so I reproduced the build locally.

ext/xml with Expat: patched

8.5.12 added a hard memory limit (2x memory_limit). A non-fallible allocation that would cross it terminates the process with exit 137. ext/xml still hands Expat non-fallible allocators (emalloc/erealloc), so a document that makes Expat exceed memory_limit no longer raises "Allowed memory size exhausted". Instead it kills the whole process at the hard limit. With ZTS that takes down every request handled by that process, which is the setup of these images.

This only happens with --with-expat. With libxml2, which is what upstream CI and Alpine use, the same tests pass.

I reported it upstream in php/php-src#24492 (comment) and opened php/php-src#24516, which makes the Expat allocators fallible. This PR applies that fix as files/patches/php-xml-expat-fallible-alloc.patch instead of disabling the two tests. They stay enabled and cover the patch.

rfc1867 OOM tests: disabled

These two tests are new in 8.5.12. They post bodies of specific sizes and expect them to exceed an 8M memory_limit. In our musl/ZTS build the requests stay below the limit and succeed. That is not a crash or a leak: valgrind and a debug build are clean, and the tests fail with libxml as well. So they are disabled, not patched.

When to remove

Both are documented in the Dockerfile:

  • Patch: remove once a PHP 8.5 release contains the upstream fix. The patch then no longer applies and abuild prepare fails, which is the reminder. I verified that an already-applied patch makes patch exit 1.
  • rfc1867 tests: re-enable on the next PHP update and drop the lines if they pass.

Verification (local, arm64, builder stage)

  • Patch applied by abuild prepare (>>> phpzts85: php-xml-expat-fallible-alloc.patch)
  • ext/xml/tests: 60 passed, 0 failed, including gh14637.phpt and oom_xml_parse_ns.phpt
  • Repro script from #24492: Fatal error: Allowed memory size of 8388608 bytes exhausted, exit 255. Before the patch it ended with Hard memory limit … exhausted, exit 137.
  • hadolint: no new findings with .hadolint.yaml

Not run locally: the full test suite and the later stages. CI on Endava#145 will cover them.

🤖 Generated with Claude Code

…ests

8.5.12 added a hard memory limit (2x memory_limit) that terminates the
process with exit 137 when a non-fallible allocation would cross it.
ext/xml still hands Expat non-fallible allocators, so a document that
makes Expat exceed memory_limit kills the whole process instead of
raising the regular fatal error. With ZTS that is every request handled
by the process. This made ext/xml/tests/gh14637.phpt and
oom_xml_parse_ns.phpt fail and broke the build.

- Apply the upstream fix proposal for php/php-src#24492 as a patch,
  which makes the Expat allocators fallible. Both tests pass with it.
- Disable tests/basic/oom_rfc1867_mb_encoding.phpt and
  oom_rfc1867_upload_progress.phpt. They are new in 8.5.12 and expect
  specific body sizes to exceed an 8M memory_limit; in our musl/ZTS
  build the requests stay below the limit. No crash and no leak
  (checked with a debug build and valgrind), and they fail with libxml
  as well.

The Dockerfile comments describe when to remove both again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmetzler
rmetzler force-pushed the fix/php-8.5.12-zts-tests branch from f2e3eaa to bc229a1 Compare October 21, 2026 22:32
@llupa
llupa merged commit 5eb5e4b into llupa:security/php-8.5.12-zts Oct 22, 2026
@llupa

llupa commented Oct 22, 2026

Copy link
Copy Markdown
Owner

Thanks, merged 🙏 The Expat patch matches what I see in 8.5.12 (femalloc/ferealloc are new, ext/xml/xml.c still on emalloc/erealloc).

One data point on the rfc1867 tests, for whenever they get re-enabled: when I reproduced them yesterday, the cause looked like the test setup rather than the musl/ZTS build. tests/basic/oom_rfc1867.inc starts php-cgi -n and only passes the memory -d options, so in a build with shared extensions the child never loads mbstring / session. The conversion and upload-progress code paths then don't run, and the child prints post=1 files=0 instead of hitting the limit. The SKIPIF only checks the parent. With -d extension_dir=$builddir/modules -d extension=mbstring -d extension=session added to the helper's command, both tests passed for me (all cases, soft-limit fatal as expected). That would keep them enabled via a small patch to the helper instead of disabled-tests.list. Not blocking, disabling is fine for now.

@llupa

llupa commented Oct 22, 2026

Copy link
Copy Markdown
Owner

Follow-up: Endava#145 then failed in prepare() with rm: can't remove 'tests/basic/oom_rfc1867_mb_encoding.phpt': No such file or directory. Alpine disabled both rfc1867 tests itself in the php85 disabled-tests.list (alpinelinux/aports de33c51a6b on 3.24-stable/master, "disable oom_rfc1867 tests needing shared extensions", and 3.23-stable got the same with the 8.5.12 upgrade this morning), so our two extra lines listed them twice and the second rm failed. I dropped them in a4916ee on the branch. The Expat patch is unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants