[PECL-CVS] [pecl-mail-mailparse] fix/gh44-segfault-mimepart-dtor: actually fix the double-free this time
[email protected] (Rasmus Lerdorf) Sun, 5 Apr 2026 10:18:42 +0000
| Newsgroups | php.pecl.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: Rasmus Lerdorf (rlerdorf)
Date: 2026-04-05T06:18:33-04:00
Commit: https://github.com/php/pecl-mail-mailparse/commit/a78df77a4562dd4428e166682069aa4f64ee89fb
Raw diff: https://github.com/php/pecl-mail-mailparse/commit/a78df77a4562dd4428e166682069aa4f64ee89fb.diff
actually fix the double-free this time
Changed paths:
M php_mailparse_mime.c
Diff:
diff --git a/php_mailparse_mime.c b/php_mailparse_mime.c
index 2d8a846..2fed283 100644
--- a/php_mailparse_mime.c
+++ b/php_mailparse_mime.c
@@ -321,8 +321,14 @@ PHP_MAILPARSE_API void php_mimepart_free(php_mimepart *part)
zval *childpart_z;
HashPosition pos;
- /* Recursively free children, NULLing their resource pointers
- * to prevent double-free from the resource list cleanup */
+ /* Prevent the resource destructor from freeing this part again */
+ if (part->rsrc && part->rsrc->ptr == part) {
+ part->rsrc->ptr = NULL;
+ }
+
+ /* Recursively free children, NULLing their resource pointers to prevent
+ * double-free from the resource list cleanup, and releasing the resource
+ * list entry so the refcount doesn't leak */
zend_hash_internal_pointer_reset_ex(&part->children, &pos);
while ((childpart_z = zend_hash_get_current_data_ex(&part->children, &pos)) != NULL) {
zend_resource *child_res = Z_RES_P(childpart_z);
@@ -331,6 +337,7 @@ PHP_MAILPARSE_API void php_mimepart_free(php_mimepart *part)
child_res->ptr = NULL;
php_mimepart_free(child);
}
+ zend_list_delete(child_res);
zend_hash_move_forward_ex(&part->children, &pos);
}