[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);
}