Skip to content

Commit 0e87ea3

Browse files
committed
ext/zip: memory leak when zip cancel callback bails out.
Fix #22176 A cancel callback that throws during the implicit zip_close() in the shutdown destructor triggers a zend_bailout that longjmps through libzip, skipping its free(filelist). Wrap the call in zend_try/zend_catch and cancel on bailout so libzip can unwind and clean up. While at it, apply the same guard to the progress callback, which is invoked from libzip the same way and is prone to the identical leak.
1 parent 9596ab1 commit 0e87ea3

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

ext/zip/php_zip.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2910,7 +2910,10 @@ static void php_zip_progress_callback(zip_t *arch, double state, void *ptr)
29102910
ze_zip_object *obj = ptr;
29112911

29122912
ZVAL_DOUBLE(&cb_args[0], state);
2913-
zend_call_known_fcc(&obj->progress_callback, NULL, 1, cb_args, NULL);
2913+
2914+
zend_try {
2915+
zend_call_known_fcc(&obj->progress_callback, NULL, 1, cb_args, NULL);
2916+
} zend_end_try();
29142917
}
29152918

29162919
/* {{{ register a progression callback: void callback(double state); */
@@ -2957,7 +2960,13 @@ static int php_zip_cancel_callback(zip_t *arch, void *ptr)
29572960
return 0;
29582961
}
29592962

2960-
zend_call_known_fcc(&obj->cancel_callback, &cb_retval, 0, NULL, NULL);
2963+
zend_try {
2964+
zend_call_known_fcc(&obj->cancel_callback, &cb_retval, 0, NULL, NULL);
2965+
} zend_catch {
2966+
/* Cancel if a bailout occurs to allow cleanup to happen */
2967+
return -1;
2968+
} zend_end_try();
2969+
29612970
if (Z_ISUNDEF(cb_retval)) {
29622971
/* Cancel if an exception has been thrown */
29632972
return -1;

0 commit comments

Comments
 (0)