Skip to content

Media: Fix wp_show_heic_upload_error() assigning to an undeclared variable. - #12830

Closed
softglazee wants to merge 4 commits into
WordPress:trunkfrom
softglazee:fix/65802-heic-upload-error-variable
Closed

Media: Fix wp_show_heic_upload_error() assigning to an undeclared variable.#12830
softglazee wants to merge 4 commits into
WordPress:trunkfrom
softglazee:fix/65802-heic-upload-error-variable

Conversation

@softglazee

Copy link
Copy Markdown

The wp_show_heic_upload_error() function assigned the HEIC upload error flag to an undeclared $plupload_init variable instead of the $plupload_settings parameter. As a result, the flag never reached the returned array. This behavior was introduced in [58849] and shipped in WordPress 6.7.0.

This patch updates the variable name to $plupload_settings so the flag is properly appended, and adds unit tests covering both the supported and unsupported HEIC editor cases.

Testing Instructions

These tests were run on trunk 8c3c976c25 using PHP 8.3.32 and PHPUnit 9.6.35.

  1. Run the newly added tests:
    npm run test:php -- --filter test_wp_show_heic_upload_error
  2. Confirm the tests pass with the fix:
    OK (2 tests, 7 assertions)
  3. Revert the change in src/wp-includes/media.php to test the baseline failure:
    git stash push src/wp-includes/media.php
  4. Re-run the tests:
    npm run test:php -- --filter test_wp_show_heic_upload_error
  5. Confirm the expected failure occurs without the patch:
    1) Tests_Media::test_wp_show_heic_upload_error_adds_flag_when_not_supported
    Failed asserting that an array has the key 'heic_upload_error'.
  6. Restore the change:
    git stash pop

Trac ticket: https://core.trac.wordpress.org/ticket/65802

Use of AI Tools

Used for: Investigating the underlying code paths, structuring the PHPUnit test scaffolding, and generating shell commands for the environment. The initial finding, manual measurements, Trac ticket description, and commit message are my own work.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props softglaze, westonruter, irozum.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

…iable.

The function assigned the error flag to an undeclared $plupload_init variable instead of the $plupload_settings parameter, preventing the flag from reaching the returned array.

This behavior was introduced in [58849] and shipped in WordPress 6.7.0.

Adds unit tests covering both the supported and unsupported cases.

See #65802.
irozum

This comment was marked as low quality.

@softglazee

Copy link
Copy Markdown
Author

Thanks @irozum for checking out the branch and running the red-green proof independently and appreciated.

Comment thread src/wp-includes/media.php
// Check if HEIC images can be edited.
if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/heic' ) ) ) {
$plupload_init['heic_upload_error'] = true;
$plupload_settings['heic_upload_error'] = true;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm quite surprised that PHPStan didn't flag this as an error. It seems that it will be implemented at some point. See phpstan/phpstan#8192.

@westonruter

Copy link
Copy Markdown
Member

Since this was dead code, I was surprised that it hadn't been noticed before.

Here's a test plugin that Claude Code (Opus 5) made so I can reproduce the issue by disabling HEIC: heic-upload-error-repro.zip

When attempting to upload an HEIC file from the Media > Add Media File screen in the admn. When I upload the HEIC test file included in the PHPUnit test data:

Before After
Screenshot 2026-08-21 at 13 08 39 Screenshot 2026-08-21 at 13 09 13

The changes here successfully cause the error to show up.

@westonruter

Copy link
Copy Markdown
Member

🤖 Comment from Claude Opus 5:

On the surprise that this went unnoticed: the changeset that broke this path also made the other path self-sufficient in the same commit, so nothing observable regressed on the screens most people use.

Timeline

r48288 (5.5) introduced wp_show_heic_upload_error() and hooked it to two filters — plupload_init in wp-admin/includes/admin-filters.php and plupload_default_settings in wp-includes/default-filters.php. The assignment was unconditional and correct, so both paths carried the flag.

r58849 (6.7.0) then made two changes at once. The callback was wrapped in a wp_image_editor_supports() check and its assignment target was mistyped as $plupload_init — the bug fixed here. In the same changeset, an equivalent assignment was added directly to wp_plupload_default_settings(), immediately before the filter it feeds:

// Check if HEIC images can be edited.
if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/heic' ) ) ) {
	$defaults['heic_upload_error'] = true;
}

/**
 * Filters the Plupload default settings.
 * ...
 */
$defaults = apply_filters( 'plupload_default_settings', $defaults );

Because that direct assignment runs first, the plupload_default_settings hookup has contributed nothing since 6.7.0. Losing the callback's output was therefore invisible on every screen fed by _wpPluploadSettings, and only the plupload_init consumer actually regressed.

Where the error was still being shown

Consumer Settings global Client-side check Flag supplied by 6.7 → now
wp_enqueue_media() — media library grid, the media modal in the block and classic editors, Customizer media controls _wpPluploadSettings.defaults wp-includes/js/plupload/wp-plupload.js wp_plupload_default_settings(), directly works
media_upload_form()media-new.php, and the legacy media-upload.php iframe via media_upload_type_form() wpUploaderInit wp-includes/js/plupload/handlers.js wp_show_heic_upload_error() via plupload_init, and nothing else broken

That split was verified by inspecting the rendered admin markup with HEIC editing unavailable on the server:

State Screen Emitted settings
Before media-new.php heic_upload_error absent from wpUploaderInit
Before upload.php "heic_upload_error":true present in _wpPluploadSettings
After media-new.php "heic_upload_error":true present in wpUploaderInit

A further reason the regression stayed quiet: HEIC is treated differently from WebP and AVIF on the client. WebP and AVIF call up.removeFile() and abort the upload, whereas HEIC only queues a warning and lets the upload proceed. Without the flag, media-new.php produced a silent success rather than a visibly failed upload, so there was nothing for a user to report beyond a missing advisory.

Two possible follow-ups, both out of scope here

  1. media_upload_form() sets webp_upload_error and avif_upload_error inline, gated behind wp_prevent_unsupported_mime_type_uploads, but leaves HEIC entirely to the filter and ungated. Setting HEIC inline alongside its siblings would remove both the asymmetry and the single point of failure that this bug depended on.
  2. Given the direct assignment in wp_plupload_default_settings(), add_filter( 'plupload_default_settings', 'wp_show_heic_upload_error' ) is now dead weight. Removing it would be behaviour-neutral, though it does remain a documented extension point that plugins may call remove_filter() against.

@softglazee

Copy link
Copy Markdown
Author

@westonruter That issue is the control flow graph work, and detecting a variable that's written but never read is one of the items listed on it. Sounds like the readonly property false positives come first, so this class of bug isn't catchable yet.

pento pushed a commit that referenced this pull request Aug 21, 2026
The `wp_show_heic_upload_error()` function assigned the `heic_upload_error` flag to an undeclared `$plupload_init` variable rather than to its `$plupload_settings` parameter, so the callback returned the settings untouched and the flag never reached Plupload.

Only the `plupload_init` path was affected: the `wp_plupload_default_settings()` function sets the same flag inline before applying `plupload_default_settings`, so screens fed by `_wpPluploadSettings` kept warning correctly. The regression was confined to `media-new.php` and the `media-upload.php` iframe, where `media_upload_form()` relies on this callback alone for HEIC.

Also correct the documented types for the settings array from `array[]` to `array<string, mixed>`, both on the function and on the `plupload_init` hook, and add regression tests for the callback.

Developed in #12830.
Follow-up to r48288, r58849.

Props softglaze, westonruter, khokansardar, irozum.
See #53645.
Fixes #65802.


git-svn-id: https://develop.svn.wordpress.org/trunk@63338 602fd350-edb4-49c9-b593-d223f7449a82
@github-actions

Copy link
Copy Markdown

A commit was made that fixes the Trac ticket referenced in the description of this pull request.

SVN changeset: 63338
GitHub commit: 9563942

This PR will be closed, but please confirm the accuracy of this and reopen if there is more work to be done.

@github-actions github-actions Bot closed this Aug 21, 2026
markjaquith pushed a commit to markjaquith/WordPress that referenced this pull request Aug 21, 2026
The `wp_show_heic_upload_error()` function assigned the `heic_upload_error` flag to an undeclared `$plupload_init` variable rather than to its `$plupload_settings` parameter, so the callback returned the settings untouched and the flag never reached Plupload.

Only the `plupload_init` path was affected: the `wp_plupload_default_settings()` function sets the same flag inline before applying `plupload_default_settings`, so screens fed by `_wpPluploadSettings` kept warning correctly. The regression was confined to `media-new.php` and the `media-upload.php` iframe, where `media_upload_form()` relies on this callback alone for HEIC.

Also correct the documented types for the settings array from `array[]` to `array<string, mixed>`, both on the function and on the `plupload_init` hook, and add regression tests for the callback.

Developed in WordPress/wordpress-develop#12830.
Follow-up to r48288, r58849.

Props softglaze, westonruter, khokansardar, irozum.
See #53645.
Fixes #65802.

Built from https://develop.svn.wordpress.org/trunk@63338


git-svn-id: http://core.svn.wordpress.org/trunk@62531 1a063a9b-81f0-0310-95a4-ce76da25c4cd
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.

3 participants