Skip to content

DOMDocument::xinclude() crash #14702

Closed
Closed

Description

@DerekRoth

Description

The following code:

<?php
$doc = new DOMDocument();
$doc->load('xinclude-fail-original.xml');
$xi = $doc->createElementNS('http://www.w3.org/2001/XInclude', 'xi:include');
$xi->setAttribute('href', $_SERVER['DOCUMENT_ROOT'] . '/xinclude-included.xml');

$fallback = $doc->createElementNS('http://www.w3.org/2001/XInclude', 'xi:fallback');
$xi->appendChild($fallback);

$xpath = new DOMXPath($doc);
$toReplace = $xpath->query('//child')->item(0);
$toReplace->parentNode->replaceChild($xi, $toReplace);

$doc->xinclude();
echo "No crash!";

With the following 2 XML files:

xinclude-fail-original.xml

<?xml version="1.0"?>
<root>
<child/>
</root>

xinclude-included.xml

<replaced>
  <somechild></somechild>
</replaced>

Resulted in this output:
Crash of the php-fpm child process, about 50% of the time. In the logs i could see 3 different errors depending on how i alter the XML files. The most common is:

  • corrupted size vs. prev_size in fastbins

I also encountered:

  • malloc_consolidate(): invalid chunk size
  • free(): double free detected in tcache 2

Followed by:

  • [28-Jun-2024 12:06:20] WARNING: [pool www] child 1088 exited on signal 6 (SIGABRT) after 475.706249 seconds from start
  • [28-Jun-2024 12:06:20] NOTICE: [pool www] child 1100 started

But I expected this output instead:

No crash!

I was able to isolate this issue on PHP 8.2 in Docker Desktop on Apple Silicon (base image php:8.2-fpm). However we encountered the same error on different servers running our XML-based CMS on PHP 7.4. We switched from SLES (SUSE Support # 00520126: PHP-FPM process crash after SLES 15 SP4 upgrade) to CentOS thinking it was a distribution bug but could not fix it. PHP 7.4 in Docker (Desktop, Mac, WSL2 or SLES) however didn't seem to be affected by the issue.

PHP Version

PHP 8.2.20

Operating System

Docker image php:8.2-fpm

Activity

  1. devnexen commented on Jun 28, 2024

    @devnexen
    Member

    reproducible even w/o FPM.

  2. ndossche commented on Jun 28, 2024

    @ndossche
    Member

    What ends up happening is that the xinclude code from libxml removes the fallback node, but the fallback node is still reference via $fallback. You can workaround this issue by doing unset($fallback); right before the call to xinclude.
    A possible solution is to perform an in-tree walk and detach our node proxy in case we encounter an xinclude fallback.

  3. added a commit that references this issue on Jun 28, 2024
    ca9d774
  4. added 3 commits that reference this issue on Jun 28, 2024
    0a1f51d
    bcdba83
    42908f9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions