Skip to content

Fix GH-23899: Handle bailout from ZipArchive cancel callback return v… - #23914

Merged
LamentXU123 merged 1 commit into
php:PHP-8.6from
LamentXU123:fix-gh23899
Sep 27, 2026
Merged

LamentXU123 merged 1 commit into
php:PHP-8.6from
LamentXU123:fix-gh23899

Conversation

@LamentXU123

Copy link
Copy Markdown
Member

…alidation

Now, PHP 8.6 moved archive closing from free_obj to dtor_obj as a result that callbacks can run before the executor shuts down.If a cancel callback returns an invalid type during shutdown, it can cause assertion error.

Well PHP 8.5 closes the archive in free_obj, which is already marked as called so it does not have this double-release path. Here, we just catch the bailout from return-type validation using the existing bailout_callback mechanism

Comment thread ext/zip/php_zip.c
@devnexen devnexen linked an issue Sep 27, 2026 that may be closed by this pull request
Comment thread ext/zip/php_zip.c Outdated
archive->bailout_callback = true;
retval = -1;
} zend_end_try();
zval_ptr_dtor(&cb_retval);

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 think you can push this up in the zend_catch part wdyt ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Do you mean moving zval_ptr_dtor(&cb_retval) into zend_catch? Mind that we also need to release the return value on the normal path including when validation throws a TypeError without bailing out.

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.

yes indeed that s the way to do it, bad phrasing from me

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.

just to be sure can this test being added ?

--TEST--
GH-23899 (Cancel callback return value whose destructor throws during shutdown)
--EXTENSIONS--
zip
--SKIPIF--
<?php
if (!method_exists(ZipArchive::class, 'registerCancelCallback')) {
    die('skip cancel callbacks are not supported');
}
?>
--FILE--
<?php
class ThrowingDestructor {
    public function __destruct() {
        throw new Exception('destructor');
    }
}

$zip = new ZipArchive;
$zip->open(__DIR__ . '/gh23899_destructor.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->registerCancelCallback(function () {
    return new ThrowingDestructor;
});
$zip->addFromString('test', 'test');
echo "Done", PHP_EOL;
?>
--CLEAN--
<?php
@unlink(__DIR__ . '/gh23899_destructor.zip');
?>
--EXPECTF--
Done

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.

seeing the nested approach, I wonder if putting the destructor inside zend_try instead would be better wdyt ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah no strong opinions but ok :)

@LamentXU123
LamentXU123 force-pushed the fix-gh23899 branch 2 times, most recently from bbde8d3 to 914c8a4 Compare September 27, 2026 11:34

@devnexen devnexen left a comment

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.

feels right now

…n validation

Co-authored-by: David Carlier <devnexen@gmail.com>
@LamentXU123
LamentXU123 merged commit f3db5d6 into php:PHP-8.6 Sep 27, 2026
11 of 18 checks passed
LamentXU123 added a commit that referenced this pull request Sep 27, 2026
* PHP-8.6:
  Fix GH-23899: Handle bailout from ZipArchive cancel callback return validation (#23914)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Assertion `archive->refcount > 0' failed in ext/zip/php_zip.c

2 participants