Commit 9002df8a413 for php.net

commit 9002df8a4133cff51bcf2051e48a1beec9fc2f12
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Mon Aug 17 20:40:08 2026 -0400

    Stop grapheme_str_split from using UBRK_DONE as a byte index (#23349)

    When the last grapheme_str_split() group is short, ubrk_next() returns
    UBRK_DONE and the loop still advanced pstr by -1 - current. Skip that
    update when the iterator is done, matching the grapheme_strrev() fix.

    Other ubrk_next() loops in grapheme_string.c and grapheme_util.c were
    audited and already guard UBRK_DONE before using the position as an
    offset.

    Closes #23349

diff --git a/NEWS b/NEWS
index 4cafbbd5a90..f65c07cf4a7 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,7 @@ PHP                                                                        NEWS
     for UTF-8 strings). (ColumbusLabs)
   . Fixed Locale::parseLocale() reading past a trailing '-' or '_'.
     (iliaal, Xuyang Zhang)
+  . Fixed grapheme_str_split() treating UBRK_DONE as a byte index. (iliaal)

 - Opcache:
   . Fixed opcache.protect_memory race under ZTS. (realFlowControl)
diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c
index fe80e06adce..6b418e65cff 100644
--- a/ext/intl/grapheme/grapheme_string.c
+++ b/ext/intl/grapheme/grapheme_string.c
@@ -896,9 +896,9 @@ PHP_FUNCTION(grapheme_str_split)
 				add_next_index_stringl(return_value, pstr, pos - current);
 				end = pstr + pos - current;
 				i = 0;
+				pstr += pos - current;
+				current = pos;
 			}
-			pstr += pos - current;
-			current = pos;
 		} else {
 			i += 1;
 		}