[PECL-CVS] [pecl-mail-mailparse] master: Fix arg zval leak in extract_callback_user_func
[email protected] (Ilia Alshanetsky via Remi Collet) Fri, 12 Jun 2026 13:40:02 +0000
| Newsgroups | php.pecl.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: Ilia Alshanetsky (iliaal)
Committer: Remi Collet (remicollet)
Date: 2026-06-12T15:39:47+02:00
Commit: https://github.com/php/pecl-mail-mailparse/commit/696d40f8691b3b8d2a36f17eeedba65aa98d9f48
Raw diff: https://github.com/php/pecl-mail-mailparse/commit/696d40f8691b3b8d2a36f17eeedba65aa98d9f48.diff
Fix arg zval leak in extract_callback_user_func
The callback ZVAL_STRINGL's the chunk into `arg` but only released it on
the success path. Both early returns — when zend_fcall_info_init() fails
and when zend_call_function() fails — returned without dtoring `arg`,
leaking one zend_string per chunk. The init-failure path is reachable
from userland by passing a non-callable as the extract callback.
zend_fcall_info_argn() ZVAL_COPYs the argument into fci.params (its own
ref), so the original `arg` always needs exactly one zval_ptr_dtor.
Release it on every path; dtor `retval` only on success, where the
engine has actually written it.
Changed paths:
M mailparse.c
Diff:
diff --git a/mailparse.c b/mailparse.c
index 7d8d218..25553f3 100644
--- a/mailparse.c
+++ b/mailparse.c
@@ -1206,19 +1206,19 @@ static int extract_callback_user_func(php_mimepart *part, zval *userfunc, const
if (zend_fcall_info_init(userfunc, 0, &fci, &fcc, NULL, NULL) == FAILURE) {
zend_error(E_WARNING, "%s(): unable to call user function", get_active_function_name());
+ zval_ptr_dtor(&arg);
return 0;
}
zend_fcall_info_argn(&fci, 1, &arg);
fci.retval = &retval;
- if (zend_call_function(&fci, &fcc)) {
- zend_fcall_info_args_clear(&fci, 1);
+ if (zend_call_function(&fci, &fcc) == SUCCESS) {
+ zval_ptr_dtor(&retval);
+ } else {
zend_error(E_WARNING, "%s(): unable to call user function", get_active_function_name());
- return 0;
}
zend_fcall_info_args_clear(&fci, 1);
- zval_ptr_dtor(&retval);
zval_ptr_dtor(&arg);
return 0;