[php-src] master: Merge branch 'PHP-8.5'
Alex Dowad <[email protected]> Thu, 23 Jul 2026 05:54:32 +0000
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Alex Dowad (alexdowad)
Date: 2026-07-23T14:54:14+09:00
Commit: https://github.com/php/php-src/commit/4983e8bb4426c7a2a4c025bac6a93d6d9312eac3
Raw diff: https://github.com/php/php-src/commit/4983e8bb4426c7a2a4c025bac6a93d6d9312eac3.diff
Merge branch 'PHP-8.5'
Changed paths:
A ext/mbstring/tests/gh22779.phpt
M NEWS
M ext/mbstring/mbstring.c
Diff:
diff --git a/NEWS b/NEWS
index 3c5101c096cb..8c12e62f7c0b 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,10 @@ PHP NEWS
. Fixed header injection through the Content-Type context option, the
soapaction and the cookie names and values. (David Carlier)
+- MBString:
+ . Fixed bug GH-22779 (mb_strrpos() returns the wrong position for a negative
+ offset in a non-UTF-8 encoding). (Eyüp Can Akman)
+
- Sockets:
. Fixed socket_set_option() validation error messages for UDP_SEGMENT and
TCP_USER_TIMEOUT, and SO_LINGER options. (Weilin Du)
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index 23420f87131f..b475b83e02f3 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -1942,7 +1942,7 @@ static size_t mb_find_strpos(zend_string *haystack, zend_string *needle, const m
} else if (offset >= 0) {
found_pos = zend_memnrstr((const char*)offset_pointer, ZSTR_VAL(needle_u8), ZSTR_LEN(needle_u8), ZSTR_VAL(haystack_u8) + ZSTR_LEN(haystack_u8));
} else {
- size_t needle_len = pointer_to_offset_utf8((unsigned char*)ZSTR_VAL(needle), (unsigned char*)ZSTR_VAL(needle) + ZSTR_LEN(needle));
+ size_t needle_len = pointer_to_offset_utf8((unsigned char*)ZSTR_VAL(needle_u8), (unsigned char*)ZSTR_VAL(needle_u8) + ZSTR_LEN(needle_u8));
offset_pointer = offset_to_pointer_utf8(offset_pointer, (unsigned char*)ZSTR_VAL(haystack_u8) + ZSTR_LEN(haystack_u8), needle_len);
if (!offset_pointer) {
offset_pointer = (unsigned char*)ZSTR_VAL(haystack_u8) + ZSTR_LEN(haystack_u8);
diff --git a/ext/mbstring/tests/gh22779.phpt b/ext/mbstring/tests/gh22779.phpt
new file mode 100644
index 000000000000..2983f4e1194a
--- /dev/null
+++ b/ext/mbstring/tests/gh22779.phpt
@@ -0,0 +1,34 @@
+--TEST--
+GH-22779: mb_strrpos() wrong result for a negative offset in a non-UTF-8 encoding
+--EXTENSIONS--
+mbstring
+--FILE--
+<?php
+/* mb_strrpos() with a negative offset must return the correct position in non-UTF-8 encodings. */
+$haystack = "\xA9\xA9X";
+$needle = "\xA9";
+foreach ([-1, -2, -3] as $offset) {
+ var_dump(mb_strrpos($haystack, $needle, $offset, 'ISO-8859-1'));
+}
+var_dump(mb_strrpos("X\xA9", "\xA9", -1, 'ISO-8859-1'));
+var_dump(mb_strrpos("\x95Z\x95Z", "\x95", -1, 'Windows-1252'));
+var_dump(mb_strrpos("\x95Z\x95Z", "\x95", -2, 'Windows-1252'));
+// Two-byte needle in a single-byte encoding.
+var_dump(mb_strrpos("\xA9\xB0\xA9\xB0Z", "\xA9\xB0", -2, 'ISO-8859-1'));
+// Multibyte: "ああA" in Shift_JIS, needle "あ" (\x82\xA0).
+var_dump(mb_strrpos("\x82\xA0\x82\xA0A", "\x82\xA0", -2, 'SJIS'));
+var_dump(mb_strrpos("\x82\xA0\x82\xA0A", "\x82\xA0", -3, 'SJIS'));
+// UTF-16: an ASCII needle miscounts the other way.
+var_dump(mb_strrpos("\x00A\x00X\x00A", "\x00A", -2, 'UTF-16BE'));
+?>
+--EXPECT--
+int(1)
+int(1)
+int(0)
+int(1)
+int(2)
+int(2)
+int(2)
+int(1)
+int(0)
+int(0)