[PECL-CVS] [pecl-mail-mailparse] fix/gh44-segfault-mimepart-dtor: potential fix for #44

[email protected] (Rasmus Lerdorf) Sun, 5 Apr 2026 04:38:09 +0000
Newsgroups php.pecl.cvs
Message-ID <[email protected]>
Author: Rasmus Lerdorf (rlerdorf)
Date: 2026-04-05T00:37:55-04:00

Commit: https://github.com/php/pecl-mail-mailparse/commit/ec3a0708f874cbb1aaabd494eb94823737ea4eb0
Raw diff: https://github.com/php/pecl-mail-mailparse/commit/ec3a0708f874cbb1aaabd494eb94823737ea4eb0.diff

potential fix for #44

Changed paths:
  M  mailparse.c
  M  php_mailparse_mime.c


Diff:

diff --git a/mailparse.c b/mailparse.c
index 5dac132..4210650 100644
--- a/mailparse.c
+++ b/mailparse.c
@@ -122,7 +122,10 @@ ZEND_RSRC_DTOR_FUNC(mimepart_dtor)
 {
 	php_mimepart *part = res->ptr;
 
-	php_mimepart_free(part);
+	if (part != NULL) {
+		res->ptr = NULL;
+		php_mimepart_free(part);
+	}
 }
 
 PHP_INI_BEGIN()
diff --git a/php_mailparse_mime.c b/php_mailparse_mime.c
index 87794b0..2d8a846 100644
--- a/php_mailparse_mime.c
+++ b/php_mailparse_mime.c
@@ -321,10 +321,16 @@ PHP_MAILPARSE_API void php_mimepart_free(php_mimepart *part)
 	zval *childpart_z;
 	HashPosition pos;
 
-	/* free contained parts */
+	/* Recursively free children, NULLing their resource pointers
+	 * to prevent double-free from the resource list cleanup */
 	zend_hash_internal_pointer_reset_ex(&part->children, &pos);
 	while ((childpart_z = zend_hash_get_current_data_ex(&part->children, &pos)) != NULL) {
-		zval_ptr_dtor(childpart_z);
+		zend_resource *child_res = Z_RES_P(childpart_z);
+		php_mimepart *child = (php_mimepart *)child_res->ptr;
+		if (child != NULL) {
+			child_res->ptr = NULL;
+			php_mimepart_free(child);
+		}
 		zend_hash_move_forward_ex(&part->children, &pos);
 	}