[PECL-CVS] [pecl-mail-mailparse] master: Fix leak and fixed-size buffer in get_structure_callback
[email protected] (Ilia Alshanetsky via Remi Collet) Fri, 12 Jun 2026 13:33:01 +0000
| Newsgroups | php.pecl.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: Ilia Alshanetsky (iliaal)
Committer: Remi Collet (remicollet)
Date: 2026-06-12T15:32:47+02:00
Commit: https://github.com/php/pecl-mail-mailparse/commit/156d6e6e92e67dff5ed1a49410d162095a01fc38
Raw diff: https://github.com/php/pecl-mail-mailparse/commit/156d6e6e92e67dff5ed1a49410d162095a01fc38.diff
Fix leak and fixed-size buffer in get_structure_callback
The callback emalloc'd a fixed 1KB buffer for every part and, on the
"too many sections" path, returned FAILURE without freeing it. That
grow-and-bail logic was also dead code: erealloc aborts rather than
returning NULL, and the size check could only fire after the doubling
realloc had already grown the buffer.
Replace the manual buffer with a smart_string that grows as needed and
is always released. The output (dot-joined section ids) is unchanged.
Changed paths:
M mailparse.c
Diff:
diff --git a/mailparse.c b/mailparse.c
index 371ec9b..1e23ebd 100644
--- a/mailparse.c
+++ b/mailparse.c
@@ -1149,34 +1149,19 @@ PHP_FUNCTION(mailparse_msg_create)
static int get_structure_callback(php_mimepart *part, php_mimepart_enumerator *id, void *ptr)
{
zval *return_value = (zval *)ptr;
- char intbuf[16];
- char *buf;
- int buf_size;
- int len, i = 0;
-
- buf_size = 1024;
- buf = emalloc(buf_size);
- while(id && i < buf_size) {
- sprintf(intbuf, "%d", id->id);
- len = strlen(intbuf);
- if (len > (buf_size-i)) {
- /* too many sections: bail */
- zend_error(E_WARNING, "%s(): too many nested sections in message", get_active_function_name());
- return FAILURE;
- }
- if ((i + len + 1) >= buf_size) {
- buf_size = buf_size << 1;
- buf = erealloc(buf, buf_size);
- if (!buf) {
- zend_error(E_ERROR, "The structure buffer has been exceeded (%d). Please try decreasing the nesting depth of messages and report this to the developers.", buf_size);
- }
+ smart_string buf = {0};
+
+ while (id) {
+ smart_string_append_long(&buf, id->id);
+ if (id->next) {
+ smart_string_appendc(&buf, '.');
}
- sprintf(&buf[i], "%s%c", intbuf, id->next ? '.' : '\0');
- i += len + (id->next ? 1 : 0);
id = id->next;
}
- add_next_index_string(return_value, buf);
- efree(buf);
+ smart_string_0(&buf);
+
+ add_next_index_string(return_value, buf.c ? buf.c : "");
+ smart_string_free(&buf);
return SUCCESS;
}