Skip to content

Commit a42d498

Browse files
Merge branch 'php:master' into master
2 parents 9d5d563 + 60102c3 commit a42d498

File tree

9 files changed

+105
-41
lines changed

9 files changed

+105
-41
lines changed

Zend/tests/gh10251.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
GH-10251 (Assertion `(flag & (1<<3)) == 0' failed.)
3+
--FILE--
4+
<?php
5+
#[\AllowDynamicProperties]
6+
class A
7+
{
8+
function __set($o, $l)
9+
{
10+
$this->$p = $v;
11+
}
12+
}
13+
$a = new A();
14+
$pp = "";
15+
$op = $pp & "";
16+
// Bitwise operators on strings don't compute the hash.
17+
// The code below previously assumed a hash was actually computed, leading to a crash.
18+
$a->$op = 0;
19+
echo "Done\n";
20+
?>
21+
--EXPECTF--
22+
Warning: Undefined variable $v in %s on line %d
23+
24+
Warning: Undefined variable $p in %s on line %d
25+
Done

Zend/zend_object_handlers.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -553,9 +553,8 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe
553553
if (EXPECTED(Z_TYPE_P(zv) == IS_STRING)) {
554554
zend_string *str = Z_STR_P(zv);
555555
if (EXPECTED(str == member) ||
556-
/* "str" always has a pre-calculated hash value here */
557-
(EXPECTED(ZSTR_H(str) == zend_string_hash_val(member)) &&
558-
EXPECTED(zend_string_equal_content(str, member)))) {
556+
/* str and member don't necessarily have a pre-calculated hash value here */
557+
EXPECTED(zend_string_equal_content(str, member))) {
559558
return &Z_PROPERTY_GUARD_P(zv);
560559
} else if (EXPECTED(Z_PROPERTY_GUARD_P(zv) == 0)) {
561560
zval_ptr_dtor_str(zv);

ext/gd/gd.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3987,9 +3987,7 @@ static int _php_image_output_putbuf(struct gdIOCtx *ctx, const void* buf, int l)
39873987

39883988
static void _php_image_output_ctxfree(struct gdIOCtx *ctx) /* {{{ */
39893989
{
3990-
if(ctx) {
3991-
efree(ctx);
3992-
}
3990+
efree(ctx);
39933991
} /* }}} */
39943992

39953993
static void _php_image_stream_putc(struct gdIOCtx *ctx, int c) /* {{{ */ {
@@ -4009,21 +4007,16 @@ static void _php_image_stream_ctxfree(struct gdIOCtx *ctx) /* {{{ */
40094007
if(ctx->data) {
40104008
ctx->data = NULL;
40114009
}
4012-
if(ctx) {
4013-
efree(ctx);
4014-
}
4010+
efree(ctx);
40154011
} /* }}} */
40164012

40174013
static void _php_image_stream_ctxfreeandclose(struct gdIOCtx *ctx) /* {{{ */
40184014
{
4019-
40204015
if(ctx->data) {
40214016
php_stream_close((php_stream *) ctx->data);
40224017
ctx->data = NULL;
40234018
}
4024-
if(ctx) {
4025-
efree(ctx);
4026-
}
4019+
efree(ctx);
40274020
} /* }}} */
40284021

40294022
static gdIOCtx *create_stream_context_from_zval(zval *to_zval) {

ext/mbstring/libmbfl/filters/mbfilter_utf8.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,9 @@ static size_t mb_utf8_to_wchar(unsigned char **in, size_t *in_len, uint32_t *buf
225225

226226
if (c < 0x80) {
227227
*out++ = c;
228-
} else if (c >= 0xC2 && c <= 0xDF) { /* 2 byte character */
228+
} else if (c < 0xC2) {
229+
*out++ = MBFL_BAD_INPUT;
230+
} else if (c <= 0xDF) { /* 2 byte character */
229231
if (p < e) {
230232
unsigned char c2 = *p++;
231233
if ((c2 & 0xC0) != 0x80) {
@@ -237,7 +239,7 @@ static size_t mb_utf8_to_wchar(unsigned char **in, size_t *in_len, uint32_t *buf
237239
} else {
238240
*out++ = MBFL_BAD_INPUT;
239241
}
240-
} else if (c >= 0xE0 && c <= 0xEF) { /* 3 byte character */
242+
} else if (c <= 0xEF) { /* 3 byte character */
241243
if ((e - p) >= 2) {
242244
unsigned char c2 = *p++;
243245
unsigned char c3 = *p++;
@@ -262,7 +264,7 @@ static size_t mb_utf8_to_wchar(unsigned char **in, size_t *in_len, uint32_t *buf
262264
}
263265
}
264266
}
265-
} else if (c >= 0xF0 && c <= 0xF4) { /* 4 byte character */
267+
} else if (c <= 0xF4) { /* 4 byte character */
266268
if ((e - p) >= 3) {
267269
unsigned char c2 = *p++;
268270
unsigned char c3 = *p++;

ext/mbstring/mbstring.c

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,30 +1717,19 @@ PHP_FUNCTION(mb_str_split)
17171717

17181718
static size_t mb_get_strlen(zend_string *string, const mbfl_encoding *encoding)
17191719
{
1720-
size_t len = 0;
1720+
unsigned int char_len = encoding->flag & (MBFL_ENCTYPE_SBCS | MBFL_ENCTYPE_WCS2 | MBFL_ENCTYPE_WCS4);
1721+
if (char_len) {
1722+
return ZSTR_LEN(string) / char_len;
1723+
}
17211724

1722-
if (encoding->flag & MBFL_ENCTYPE_SBCS) {
1723-
return ZSTR_LEN(string);
1724-
} else if (encoding->flag & MBFL_ENCTYPE_WCS2) {
1725-
return ZSTR_LEN(string) / 2;
1726-
} else if (encoding->flag & MBFL_ENCTYPE_WCS4) {
1727-
return ZSTR_LEN(string) / 4;
1728-
} else if (encoding->mblen_table) {
1729-
const unsigned char *mbtab = encoding->mblen_table;
1730-
unsigned char *p = (unsigned char*)ZSTR_VAL(string), *e = p + ZSTR_LEN(string);
1731-
while (p < e) {
1732-
p += mbtab[*p];
1733-
len++;
1734-
}
1735-
} else {
1736-
uint32_t wchar_buf[128];
1737-
unsigned char *in = (unsigned char*)ZSTR_VAL(string);
1738-
size_t in_len = ZSTR_LEN(string);
1739-
unsigned int state = 0;
1725+
uint32_t wchar_buf[128];
1726+
unsigned char *in = (unsigned char*)ZSTR_VAL(string);
1727+
size_t in_len = ZSTR_LEN(string);
1728+
unsigned int state = 0;
1729+
size_t len = 0;
17401730

1741-
while (in_len) {
1742-
len += encoding->to_wchar(&in, &in_len, wchar_buf, 128, &state);
1743-
}
1731+
while (in_len) {
1732+
len += encoding->to_wchar(&in, &in_len, wchar_buf, 128, &state);
17441733
}
17451734

17461735
return len;
@@ -2052,7 +2041,10 @@ static zend_string* mb_get_substr(zend_string *input, size_t from, size_t len, c
20522041
len = in_len;
20532042
}
20542043
return zend_string_init_fast((const char*)in, len);
2055-
} else if (enc->mblen_table != NULL) {
2044+
} else if (enc->mblen_table) {
2045+
/* The use of the `mblen_table` means that for encodings like MacJapanese,
2046+
* we treat each character in its native charset as "1 character", even if it
2047+
* maps to a sequence of several codepoints */
20562048
const unsigned char *mbtab = enc->mblen_table;
20572049
unsigned char *limit = in + in_len;
20582050
while (from && in < limit) {
@@ -2265,7 +2257,21 @@ PHP_FUNCTION(mb_substr)
22652257

22662258
size_t mblen = 0;
22672259
if (from < 0 || (!len_is_null && len < 0)) {
2268-
mblen = mb_get_strlen(str, enc);
2260+
if (enc->mblen_table) {
2261+
/* Because we use the `mblen_table` when iterating over the string and
2262+
* extracting the requested part, we also need to use it here for counting
2263+
* the "length" of the string
2264+
* Otherwise, we can get wrong results for text encodings like MacJapanese,
2265+
* where one native 'character' can map to a sequence of several codepoints */
2266+
const unsigned char *mbtab = enc->mblen_table;
2267+
unsigned char *p = (unsigned char*)ZSTR_VAL(str), *e = p + ZSTR_LEN(str);
2268+
while (p < e) {
2269+
p += mbtab[*p];
2270+
mblen++;
2271+
}
2272+
} else {
2273+
mblen = mb_get_strlen(str, enc);
2274+
}
22692275
}
22702276

22712277
/* if "from" position is negative, count start position from the end

ext/mbstring/tests/mb_str_split_jp.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,23 @@ foreach (['SJIS', 'SJIS-2004', 'MacJapanese', 'SJIS-Mobile#DOCOMO', 'SJIS-Mobile
8080
echo "$encoding: [" . implode(', ', array_map('bin2hex', $array)) . "]\n";
8181
}
8282

83+
/*
84+
Some MacJapanese characters map to a sequence of several Unicode codepoints. Examples:
85+
86+
0x85AB 0xF862+0x0058+0x0049+0x0049+0x0049 # roman numeral thirteen
87+
0x85AC 0xF861+0x0058+0x0049+0x0056 # roman numeral fourteen
88+
0x85AD 0xF860+0x0058+0x0056 # roman numeral fifteen
89+
0x85BF 0xF862+0x0078+0x0069+0x0069+0x0069 # small roman numeral thirteen
90+
0x85C0 0xF861+0x0078+0x0069+0x0076 # small roman numeral fourteen
91+
0x85C1 0xF860+0x0078+0x0076 # small roman numeral fifteen
92+
93+
Even though they map to multiple codepoints, mb_str_split treats these as ONE character each
94+
*/
95+
96+
echo "== MacJapanese characters which map to 3-5 codepoints each ==\n";
97+
echo "[", implode(', ', array_map('bin2hex', mb_str_split("abc\x85\xAB\x85\xAC\x85\xAD", 1, 'MacJapanese'))), "]\n";
98+
echo "[", implode(', ', array_map('bin2hex', mb_str_split("abc\x85\xBF\x85\xC0\x85\xC1", 2, 'MacJapanese'))), "]\n";
99+
83100
?>
84101
--EXPECT--
85102
BIG-5: a4e9 a5bb
@@ -104,3 +121,6 @@ SJIS-Mobile#KDDI: [80a1, 6162, 6380, a1]
104121
SJIS-Mobile#KDDI: [6162, 63fd, feff, 6162, fdfe, ff]
105122
SJIS-Mobile#SoftBank: [80a1, 6162, 6380, a1]
106123
SJIS-Mobile#SoftBank: [6162, 63fd, feff, 6162, fdfe, ff]
124+
== MacJapanese characters which map to 3-5 codepoints each ==
125+
[61, 62, 63, 85ab, 85ac, 85ad]
126+
[6162, 6385bf, 85c085c1]

ext/mbstring/tests/mb_strlen.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ try {
9393
6
9494
== MacJapanese ==
9595
2
96-
6
96+
7
9797
== SJIS-2004 ==
9898
2
9999
6

ext/mbstring/tests/mb_substr.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ echo "SJIS-Mobile#SoftBank:\n";
6464
print bin2hex(mb_substr("\x80abc\x80\xA1", 3, 2, 'SJIS-Mobile#SoftBank')) . "\n";
6565
print bin2hex(mb_substr("\x80abc\x80\xA1", 0, 3, 'SJIS-Mobile#SoftBank')) . "\n";
6666

67+
echo "-- Testing MacJapanese characters which map to 3-5 codepoints each --\n";
68+
69+
/* There are many characters in MacJapanese which map to sequences of several codepoints */
70+
print bin2hex(mb_substr("abc\x85\xAB\x85\xAC\x85\xAD", 0, 3, 'MacJapanese')) . "\n";
71+
print bin2hex(mb_substr("abc\x85\xAB\x85\xAC\x85\xAD", 3, 2, 'MacJapanese')) . "\n";
72+
print bin2hex(mb_substr("abc\x85\xAB\x85\xAC\x85\xAD", -2, 1, 'MacJapanese')) . "\n";
73+
print bin2hex(mb_substr("abc\x85\xBF\x85\xC0\x85\xC1", 0, 3, 'MacJapanese')) . "\n";
74+
print bin2hex(mb_substr("abc\x85\xBF\x85\xC0\x85\xC1", 3, 2, 'MacJapanese')) . "\n";
75+
print bin2hex(mb_substr("abc\x85\xBF\x85\xC0\x85\xC1", -2, 1, 'MacJapanese')) . "\n";
76+
6777
echo "ISO-2022-JP:\n";
6878
print "1: " . bin2hex(mb_substr($iso2022jp, 0, 3, 'ISO-2022-JP')) . "\n";
6979
print "2: " . bin2hex(mb_substr($iso2022jp, -1, null, 'ISO-2022-JP')) . "\n";
@@ -145,6 +155,13 @@ SJIS-Mobile#KDDI:
145155
SJIS-Mobile#SoftBank:
146156
6380
147157
806162
158+
-- Testing MacJapanese characters which map to 3-5 codepoints each --
159+
616263
160+
85ab85ac
161+
85ac
162+
616263
163+
85bf85c0
164+
85c0
148165
ISO-2022-JP:
149166
1: 1b2442212121721b284241
150167
2: 43

sapi/phpdbg/phpdbg.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,8 @@ int main(int argc, char **argv) /* {{{ */
13781378
get_zend_version()
13791379
);
13801380
}
1381+
PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
1382+
php_module_shutdown();
13811383
sapi_deactivate();
13821384
sapi_shutdown();
13831385
php_ini_builder_deinit(&ini_builder);

0 commit comments

Comments
 (0)