[PECL-CVS] [pecl-mail-mailparse] master: Use memchr for end-of-line scan in php_mimepart_parse

[email protected] (Ilia Alshanetsky via Remi Collet) Fri, 12 Jun 2026 13:43:37 +0000
Newsgroups php.pecl.cvs
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Committer: Remi Collet (remicollet)
Date: 2026-06-12T15:43:23+02:00

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

Use memchr for end-of-line scan in php_mimepart_parse

The per-chunk newline search was a hand-rolled byte-at-a-time loop.
memchr lets libc scan a word at a time, which matters because this is
the inner loop of all message parsing. Behaviour is unchanged: a chunk
with a newline is appended up to and including the '\n' and handed to
php_mimepart_process_line; a chunk without one is buffered for the next
call.

Changed paths:
  M  php_mailparse_mime.c


Diff:

diff --git a/php_mailparse_mime.c b/php_mailparse_mime.c
index e71bfec..e7229ec 100644
--- a/php_mailparse_mime.c
+++ b/php_mailparse_mime.c
@@ -743,12 +743,9 @@ PHP_MAILPARSE_API int php_mimepart_parse(php_mimepart *part, const char *buf, si
 
 	while(bufsize > 0) {
 		/* look for EOL */
-		for (len = 0; len < bufsize; len++)
-			if (buf[len] == '\n') {
-				break;
-			}
-		if (len < bufsize && buf[len] == '\n') {
-			++len;
+		const char *eol = memchr(buf, '\n', bufsize);
+		if (eol != NULL) {
+			len = (size_t)(eol - buf) + 1; /* include the '\n' */
 			smart_string_appendl(&part->parsedata.workbuf, buf, len);
 			if (php_mimepart_process_line(part) == FAILURE) {
 				/* php_mimepart_process_line() only returns FAILURE in case the count of children
@@ -765,6 +762,8 @@ PHP_MAILPARSE_API int php_mimepart_parse(php_mimepart *part, const char *buf, si
 			};
 			part->parsedata.workbuf.len = 0;
 		} else {
+			/* no EOL in this chunk: buffer the remainder for the next call */
+			len = bufsize;
 			smart_string_appendl(&part->parsedata.workbuf, buf, len);
 		}