[PECL-CVS] [pecl-mail-mailparse] master: Avoid double allocation when joining To/Cc headers
[email protected] (Ilia Alshanetsky via Remi Collet) Sat, 13 Jun 2026 04:59:38 +0000
| Newsgroups | php.pecl.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: Ilia Alshanetsky (iliaal)
Committer: Remi Collet (remicollet)
Date: 2026-06-13T06:59:18+02:00
Commit: https://github.com/php/pecl-mail-mailparse/commit/36ef73988881f499b172b89a04b5fda578bbb624
Raw diff: https://github.com/php/pecl-mail-mailparse/commit/36ef73988881f499b172b89a04b5fda578bbb624.diff
Avoid double allocation when joining To/Cc headers
Folding repeated To:/Cc: headers built a throwaway buffer with
emalloc + strcpy + two strcat calls, then handed it to
add_assoc_string, which copied it again into a zend_string before the
temporary was freed. That is two allocations and two copies per fold.
Build the joined value directly into a single zend_string with memcpy
and store it with add_assoc_str, which takes ownership. One allocation,
one copy. Output ("a, b, c") is unchanged.
Changed paths:
M php_mailparse_mime.c
Diff:
diff --git a/php_mailparse_mime.c b/php_mailparse_mime.c
index e7229ec..b634eec 100644
--- a/php_mailparse_mime.c
+++ b/php_mailparse_mime.c
@@ -435,17 +435,16 @@ static int php_mimepart_process_header(php_mimepart *part)
* join multiple To: or Cc: lines together */
header_zstring = zend_string_init(header_key, strlen(header_key), 0);
if ((strcmp(header_key, "to") == 0 || strcmp(header_key, "cc") == 0) && (zheaderval = zend_hash_find(Z_ARRVAL_P(&part->headerhash), header_zstring)) != NULL) {
- int newlen;
- char *newstr;
-
- newlen = strlen(header_val) + Z_STRLEN_P(zheaderval) + 3;
- newstr = emalloc(newlen);
-
- strcpy(newstr, Z_STRVAL_P(zheaderval));
- strcat(newstr, ", ");
- strcat(newstr, header_val);
- add_assoc_string(&part->headerhash, header_key, newstr);
- efree(newstr);
+ zend_string *existing = Z_STR_P(zheaderval);
+ size_t existing_len = ZSTR_LEN(existing);
+ size_t add_len = strlen(header_val);
+ zend_string *joined = zend_string_alloc(existing_len + 2 + add_len, 0);
+
+ memcpy(ZSTR_VAL(joined), ZSTR_VAL(existing), existing_len);
+ memcpy(ZSTR_VAL(joined) + existing_len, ", ", 2);
+ memcpy(ZSTR_VAL(joined) + existing_len + 2, header_val, add_len);
+ ZSTR_VAL(joined)[existing_len + 2 + add_len] = '\0';
+ add_assoc_str(&part->headerhash, header_key, joined);
} else {
if((zheaderval = zend_hash_find(Z_ARRVAL_P(&part->headerhash), header_zstring)) != NULL) {
if(Z_TYPE_P(zheaderval) == IS_ARRAY) {