[PECL-CVS] [pecl-mail-mailparse] master: Fix memory leaks in mailparse_uudecode_all

[email protected] (Ilia Alshanetsky via Remi Collet) Wed, 24 Jun 2026 08:15:46 +0000
Newsgroups php.pecl.cvs
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Committer: Remi Collet (remicollet)
Date: 2026-06-24T10:14:27+02:00

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

Fix memory leaks in mailparse_uudecode_all

Changed paths:
  A  tests/uudecode_all_no_begin.phpt
  M  mailparse.c


Diff:

diff --git a/mailparse.c b/mailparse.c
index 6210be0..b6f973b 100644
--- a/mailparse.c
+++ b/mailparse.c
@@ -794,7 +794,7 @@ PHP_FUNCTION(mailparse_uudecode_all)
 {
 	zval *file, item;
 	char *buffer = NULL;
-	zend_string *outpath;
+	zend_string *outpath, *partpath = NULL;
 	int nparts = 0;
 	php_stream *instream, *outstream = NULL, *partstream = NULL;
 
@@ -839,6 +839,7 @@ PHP_FUNCTION(mailparse_uudecode_all)
 				add_assoc_string(&item, "filename", ZSTR_VAL(outpath));
 				add_next_index_zval(return_value, &item);
 				zend_string_release(outpath);
+				outpath = NULL;
 			}
 
 			/* add an item */
@@ -846,16 +847,19 @@ PHP_FUNCTION(mailparse_uudecode_all)
 			add_assoc_string(&item, "origfilename", origfilename);
 
 			/* create a temp file for the data */
-			partstream = _mailparse_create_stream(&outpath);
+			partstream = _mailparse_create_stream(&partpath);
 			if (partstream)	{
 				nparts++;
-				add_assoc_string(&item, "filename", ZSTR_VAL(outpath));
+				add_assoc_string(&item, "filename", ZSTR_VAL(partpath));
 				add_next_index_zval(return_value, &item);
 
 				/* decode it */
 				mailparse_do_uudecode(instream, partstream);
 				php_stream_close(partstream);
-				zend_string_release(outpath);
+				zend_string_release(partpath);
+			} else {
+				/* temp-file creation failed: drop the half-built item */
+				zval_ptr_dtor(&item);
 			}
 		} else {
 			/* write to the output file */
@@ -867,7 +871,14 @@ PHP_FUNCTION(mailparse_uudecode_all)
 	efree(buffer);
 
 	if (nparts == 0) {
-		/* delete temporary file */
+		/* no uuencoded part decoded: release the unused initial temp-file
+		 * path, or discard the partially-built array if a begin line was seen
+		 * but every part failed to decode */
+		if (outpath) {
+			zend_string_release(outpath);
+		} else {
+			zval_ptr_dtor(return_value);
+		}
 		RETURN_FALSE;
 	}
 }
diff --git a/tests/uudecode_all_no_begin.phpt b/tests/uudecode_all_no_begin.phpt
new file mode 100644
index 0000000..94520f4
--- /dev/null
+++ b/tests/uudecode_all_no_begin.phpt
@@ -0,0 +1,17 @@
+--TEST--
+mailparse_uudecode_all on input without a "begin" line does not leak
+--SKIPIF--
+<?php if (!extension_loaded("mailparse")) print "skip"; ?>
+--FILE--
+<?php
+/* With no "begin" line the temp-file path string was never released. */
+$fp = fopen("php://memory", "r+");
+fwrite($fp, "plain text\nno uuencoded data here\n");
+rewind($fp);
+var_dump(mailparse_uudecode_all($fp));
+fclose($fp);
+echo "done\n";
+?>
+--EXPECT--
+bool(false)
+done