Make WordPress Core

Opened 2 months ago

Closed 6 weeks ago

#65320 closed defect (bug) (reported-upstream)

WordPress 7 core update silently truncates filenames longer than 100 characters during extraction (wp-includes/php-ai-client/ affected)

Reported by: arakelxvi Owned by:
Priority: normal Milestone:
Component: General Version: 7.0
Severity: major Keywords:
Cc: Focuses:

Description

Description

When updating to WordPress 7 — either via the admin dashboard or WP-CLI — files whose path within the archive exceeds 100 characters are extracted with silently truncated
filenames. No error is reported. WordPress 7 introduced wp-includes/php-ai-client/, a new AI client library containing many files with archive-internal paths of 101–131
characters. Every file exceeding the 100-char boundary is extracted with a truncated name, causing every WordPress 7 installation to immediately fail wp core verify-checksums.


Environment

  • WordPress version: 7.0
  • PHP version: multiple tested — issue is not PHP version specific
  • OS: Ubuntu Linux
  • Reproduction: 100% reproducible on every fresh install or update to WP7

Steps to Reproduce

  1. Update to WordPress 7 via admin dashboard or wp core update --allow-root
  2. Run wp core verify-checksums --allow-root

Expected Behavior

All files extracted with correct full filenames. wp core verify-checksums passes.

Actual Behavior


Files with archive-internal paths exceeding 100 characters are extracted with silently truncated names. wp core verify-checksums reports each affected file twice:

Warning: File doesn't exist: wp-includes/php-ai-client/third-party/Http/Discovery/Exception/PuliUnavailableException.php
Warning: File should not exist: wp-includes/php-ai-client/third-party/Http/Discovery/Exception/PuliUnavailableException.ph
Warning: File doesn't exist: wp-includes/php-ai-client/third-party/Http/Discovery/Exception/StrategyUnavailableException.php
Warning: File should not exist: wp-includes/php-ai-client/third-party/Http/Discovery/Exception/StrategyUnavailableExceptio
Warning: File doesn't exist: wp-includes/php-ai-client/src/Providers/OpenAiCompatibleImplementation/AbstractOpenAiCompatibleModelMetadataDirectory.php
Warning: File should not exist: wp-includes/php-ai-client/src/Providers/OpenAiCompatibleImplementation/AbstractOpenAiCompa

The truncation point is exactly 100 characters of the archive-internal path in every case. All files with archive-internal paths ≤ 100 chars extract correctly. All files exceeding

100 chars are affected.

Root Cause

PHP's PharData (used for tar.gz extraction) reads only the 100-byte name field from tar headers, ignoring the prefix field and PAX extended headers that carry the full path for
entries exceeding 100 characters. This is a known limitation of PHP's libphar implementation.

Confirmed: PHP reads filenames truncated via PharData, while system tools extract correctly:

PharData  truncated at 100 chars

php -r "
$phar = new PharData('/tmp/wp7.tar.gz');
foreach (new RecursiveIteratorIterator($phar) as $f) {
    if (strpos($f->getPathName(), 'PuliUnavailable') !== false)
        echo $f->getPathName() . PHP_EOL;
}
"
Result: phar:///tmp/wp7.tar.gz/wordpress/.../PuliUnavailableException.ph  (truncated)

system tar  correct

tar -tvf /tmp/wp7.tar.gz | grep PuliUnavailable
Result: wordpress/.../PuliUnavailableException.php  (correct)

ZipArchive (.zip)  correct

php -r "
$z = new ZipArchive();
$z->open('/tmp/wp7.zip');
for ($i = 0; $i < $z->numFiles; $i++) {
    $name = $z->getNameIndex($i);
    if (strpos($name, 'PuliUnavailable') !== false)
        echo strlen($name) . ' ' . $name . PHP_EOL;
}
$z->close();
"
Result: 101 wordpress/.../PuliUnavailableException.php  (correct)

phar:///tmp/wp7.tar.gz/ = 23 chars + 100-char tar name field = 123 chars total. The character at position 101 of the internal path is silently dropped.

Change History (5)

#1 @arakelxvi
2 months ago

After further investigation, the issue is specific to wp core download — wp core update is not affected as it downloads a .zip archive and uses ZipArchive, which handles

long paths correctly.


wp core download downloads a .tar.gz and extracts it via PHP's PharData, which silently truncates any archive-internal path exceeding 100 characters (the tar format's name field
size). Confirmed:

PharData  truncated at 100 chars

php -r "
$phar = new PharData('/tmp/wp7.tar.gz');
foreach (new RecursiveIteratorIterator($phar) as $f) {
    if (strpos($f->getPathName(), 'PuliUnavailable') !== false)
        echo $f->getPathName() . PHP_EOL;
}
"
Result: phar:///tmp/wp7.tar.gz/wordpress/.../PuliUnavailableException.ph  (truncated)

system tar  correct

tar -tvf /tmp/wp7.tar.gz | grep PuliUnavailable
Result: wordpress/.../PuliUnavailableException.php  (correct)

ZipArchive (.zip, same as wp core update uses)  correct

php -r "
$z = new ZipArchive();
$z->open('/tmp/wp7.zip');
for ($i = 0; $i < $z->numFiles; $i++) {
    $name = $z->getNameIndex($i);
    if (strpos($name, 'PuliUnavailable') !== false) echo $name . PHP_EOL;
}
$z->close();
"
Result: wordpress/.../PuliUnavailableException.php  (correct)

The fix should be in wp core download — either switch to downloading .zip (same as wp core update) or replace PharData extraction with system tar.

#2 follow-up: @johnbillion
2 months ago

  • Milestone Awaiting Review7.0.1

WP-CLI issue: https://github.com/wp-cli/wp-cli/issues/6320

CC @swissspidy

Leaving this open for visibility and in case anything in core needs to change.

#3 in reply to: ↑ 2 @khokansardar
2 months ago

Replying to johnbillion:

WP-CLI issue: https://github.com/wp-cli/wp-cli/issues/6320

CC @swissspidy

Leaving this open for visibility and in case anything in core needs to change.

I've added the fixes here - https://github.com/wp-cli/wp-cli/pull/6321
cc: @swissspidy

#4 @jorbin
8 weeks ago

  • Keywords close added

With this issue being in wp-cli and a fix there having been committed, I think this can be closed as reported-upstream.

#5 @wildworks
6 weeks ago

  • Keywords close removed
  • Milestone 7.0.1
  • Resolutionreported-upstream
  • Status newclosed

Closing this as the issue has been fixed upstream.

Note: See TracTickets for help on using tickets.