Skip to content

Commit cc20668

Browse files
committed
Merge branch 'master' into fix_19507
2 parents 09bda24 + c6f02a4 commit cc20668

File tree

15 files changed

+139
-27
lines changed

15 files changed

+139
-27
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ PHP NEWS
1515
. Added support for configuring the URI parser for the FTP/FTPS as well as
1616
the SSL/TLS stream wrappers as described in
1717
https://wiki.php.net/rfc/url_parsing_api#plugability. (kocsismate)
18+
. Fixed bug GH-19548 (Shared memory violation on property inheritance).
19+
(alexandre-daubois)
20+
. Fixed bug GH-19544 (GC treats ZEND_WEAKREF_TAG_MAP references as WeakMap
21+
references). (Arnaud, timwolla)
1822

1923
- Filter:
2024
. Added support for configuring the URI parser for FILTER_VALIDATE_URL

Zend/tests/gh19543-001.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
GH-19543 001: GC treats ZEND_WEAKREF_TAG_MAP references as WeakMap references
3+
--EXTENSIONS--
4+
zend_test
5+
--FILE--
6+
<?php
7+
8+
$e = new Exception();
9+
$a = new stdClass();
10+
zend_weakmap_attach($e, $a);
11+
unset($a);
12+
gc_collect_cycles();
13+
14+
?>
15+
==DONE==
16+
--EXPECT--
17+
==DONE==

Zend/tests/gh19543-002.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-19543 002: GC treats ZEND_WEAKREF_TAG_MAP references as WeakMap references
3+
--EXTENSIONS--
4+
zend_test
5+
--FILE--
6+
<?php
7+
8+
$e = new Exception();
9+
$a = new stdClass();
10+
zend_weakmap_attach($e, $a);
11+
unset($a);
12+
$e2 = $e;
13+
unset($e2); // add to roots
14+
gc_collect_cycles();
15+
16+
?>
17+
==DONE==
18+
--EXPECT--
19+
==DONE==
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-19548: Segfault when using inherited properties and opcache
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
public mixed $i { get; }
8+
}
9+
class P {
10+
public mixed $i;
11+
}
12+
13+
class C extends P implements I {}
14+
15+
echo "Test passed - no segmentation fault\n";
16+
17+
?>
18+
--EXPECT--
19+
Test passed - no segmentation fault
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
GH-19548: Segfault when using inherited properties and opcache (multiple properties)
3+
--FILE--
4+
<?php
5+
6+
interface I1 {
7+
public mixed $a { get; }
8+
public mixed $b { get; }
9+
}
10+
class P1 {
11+
public mixed $a;
12+
public mixed $b;
13+
}
14+
class C1 extends P1 implements I1 {}
15+
16+
interface I2 {
17+
public mixed $prop { get; }
18+
}
19+
class P2 {
20+
public mixed $prop;
21+
}
22+
class Q2 extends P2 {}
23+
class C2 extends Q2 implements I2 {}
24+
25+
echo "Multiple property test passed - no segmentation fault\n";
26+
27+
?>
28+
--EXPECT--
29+
Multiple property test passed - no segmentation fault

Zend/zend_inheritance.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1564,7 +1564,9 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
15641564
ZSTR_VAL(parent_info->ce->name));
15651565
}
15661566

1567-
child_info->flags &= ~ZEND_ACC_OVERRIDE;
1567+
if (child_info->ce == ce) {
1568+
child_info->flags &= ~ZEND_ACC_OVERRIDE;
1569+
}
15681570
}
15691571
} else {
15701572
zend_function **hooks = parent_info->hooks;

Zend/zend_language_scanner.l

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
926926
ZVAL_STRINGL(zendlval, yytext, yyleng); \
927927
}
928928

929-
static zend_result zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type)
929+
static zend_result zend_scan_escape_string(zval *zendlval, char *str, size_t len, char quote_type)
930930
{
931931
char *s, *t;
932932
char *end;

Zend/zend_weakrefs.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,21 @@ typedef struct _zend_weakmap_iterator {
3636
uint32_t ht_iter;
3737
} zend_weakmap_iterator;
3838

39-
/* EG(weakrefs) is a map from a key corresponding to a zend_object pointer to all the WeakReference and/or WeakMap entries relating to that pointer.
39+
/* EG(weakrefs) is a map from a key corresponding to a zend_object pointer to all the WeakReference, WeakMap, and/or bare HashTable entries relating to that pointer.
4040
*
4141
* 1. For a single WeakReference,
4242
* the HashTable's corresponding value's tag is a ZEND_WEAKREF_TAG_REF and the pointer is a singleton WeakReference instance (zend_weakref *) for that zend_object pointer (from WeakReference::create()).
4343
* 2. For a single WeakMap, the HashTable's corresponding value's tag is a ZEND_WEAKREF_TAG_MAP and the pointer is a WeakMap instance (zend_weakmap *).
44-
* 3. For multiple values associated with the same zend_object pointer, the HashTable entry's tag is a ZEND_WEAKREF_TAG_HT with a HashTable mapping
45-
* tagged pointers of at most 1 WeakReference and 1 or more WeakMaps to the same tagged pointer.
44+
* 3. For a single bare HashTable, the HashTable's corresponding value's tag is a ZEND_WEAKREF_TAG_BARE_HT and the pointer is a HashTable*.
45+
* 4. For multiple values associated with the same zend_object pointer, the HashTable entry's tag is a ZEND_WEAKREF_TAG_HT with a HashTable mapping
46+
* tagged pointers of at most 1 WeakReference and 1 or more WeakMap or bare HashTable to the same tagged pointer.
4647
*
4748
* ZEND_MM_ALIGNED_OFFSET_LOG2 is at least 2 on supported architectures (pointers to the objects in question are aligned to 4 bytes (1<<2) even on 32-bit systems),
4849
* i.e. the least two significant bits of the pointer can be used as a tag (ZEND_WEAKREF_TAG_*). */
49-
#define ZEND_WEAKREF_TAG_REF 0
50-
#define ZEND_WEAKREF_TAG_MAP 1
51-
#define ZEND_WEAKREF_TAG_HT 2
50+
#define ZEND_WEAKREF_TAG_REF 0
51+
#define ZEND_WEAKREF_TAG_MAP 1
52+
#define ZEND_WEAKREF_TAG_HT 2
53+
#define ZEND_WEAKREF_TAG_BARE_HT 3
5254
#define ZEND_WEAKREF_GET_TAG(p) (((uintptr_t) (p)) & 3)
5355
#define ZEND_WEAKREF_GET_PTR(p) ((void *) (((uintptr_t) (p)) & ~3))
5456
#define ZEND_WEAKREF_ENCODE(p, t) ((void *) (((uintptr_t) (p)) | (t)))
@@ -72,8 +74,8 @@ static inline void zend_weakref_unref_single(
7274
zend_weakref *wr = ptr;
7375
wr->referent = NULL;
7476
} else {
75-
/* unreferencing WeakMap entry (at ptr) with a key of object. */
76-
ZEND_ASSERT(tag == ZEND_WEAKREF_TAG_MAP);
77+
/* unreferencing WeakMap or bare HashTable entry (at ptr) with a key of object. */
78+
ZEND_ASSERT(tag == ZEND_WEAKREF_TAG_MAP || tag == ZEND_WEAKREF_TAG_BARE_HT);
7779
zend_hash_index_del((HashTable *) ptr, zend_object_to_weakref_key(object));
7880
}
7981
}
@@ -166,18 +168,20 @@ static void zend_weakref_unregister(zend_object *object, void *payload, bool wea
166168
}
167169
}
168170

171+
/* Insert 'pData' into bare HashTable 'ht', with the given 'key'. 'key' is
172+
* weakly referenced. 'ht' is considered to be a bare HashTable, not a WeakMap. */
169173
ZEND_API zval *zend_weakrefs_hash_add(HashTable *ht, zend_object *key, zval *pData) {
170174
zval *zv = zend_hash_index_add(ht, zend_object_to_weakref_key(key), pData);
171175
if (zv) {
172-
zend_weakref_register(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_MAP));
176+
zend_weakref_register(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_BARE_HT));
173177
}
174178
return zv;
175179
}
176180

177181
ZEND_API zend_result zend_weakrefs_hash_del(HashTable *ht, zend_object *key) {
178182
zval *zv = zend_hash_index_find(ht, zend_object_to_weakref_key(key));
179183
if (zv) {
180-
zend_weakref_unregister(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_MAP), 1);
184+
zend_weakref_unregister(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_BARE_HT), 1);
181185
return SUCCESS;
182186
}
183187
return FAILURE;
@@ -547,6 +551,10 @@ HashTable *zend_weakmap_get_object_key_entry_gc(zend_object *object, zval **tabl
547551
ZEND_ASSERT(zv);
548552
zend_get_gc_buffer_add_ptr(gc_buffer, zv);
549553
zend_get_gc_buffer_add_obj(gc_buffer, &wm->std);
554+
} else if (ZEND_WEAKREF_GET_TAG(tagged_ptr) == ZEND_WEAKREF_TAG_BARE_HT) {
555+
/* Bare HashTables are intentionally ignored, since they are
556+
* intended for internal usage by extensions and might not be
557+
* collectable. */
550558
}
551559
} ZEND_HASH_FOREACH_END();
552560
} else if (tag == ZEND_WEAKREF_TAG_MAP) {
@@ -555,6 +563,8 @@ HashTable *zend_weakmap_get_object_key_entry_gc(zend_object *object, zval **tabl
555563
ZEND_ASSERT(zv);
556564
zend_get_gc_buffer_add_ptr(gc_buffer, zv);
557565
zend_get_gc_buffer_add_obj(gc_buffer, &wm->std);
566+
} else if (tag == ZEND_WEAKREF_TAG_BARE_HT) {
567+
/* Bare HashTables are intentionally ignored (see above) */
558568
}
559569

560570
zend_get_gc_buffer_use(gc_buffer, table, n);
@@ -581,13 +591,19 @@ HashTable *zend_weakmap_get_object_entry_gc(zend_object *object, zval **table, i
581591
zval *zv = zend_hash_index_find(&wm->ht, obj_key);
582592
ZEND_ASSERT(zv);
583593
zend_get_gc_buffer_add_ptr(gc_buffer, zv);
594+
} else if (ZEND_WEAKREF_GET_TAG(tagged_ptr) == ZEND_WEAKREF_TAG_BARE_HT) {
595+
/* Bare HashTables are intentionally ignored
596+
* (see zend_weakmap_get_object_key_entry_gc) */
584597
}
585598
} ZEND_HASH_FOREACH_END();
586599
} else if (tag == ZEND_WEAKREF_TAG_MAP) {
587600
zend_weakmap *wm = (zend_weakmap*) ptr;
588601
zval *zv = zend_hash_index_find(&wm->ht, obj_key);
589602
ZEND_ASSERT(zv);
590603
zend_get_gc_buffer_add_ptr(gc_buffer, zv);
604+
} else if (tag == ZEND_WEAKREF_TAG_BARE_HT) {
605+
/* Bare HashTables are intentionally ignored
606+
* (see zend_weakmap_get_object_key_entry_gc) */
591607
}
592608

593609
zend_get_gc_buffer_use(gc_buffer, table, n);

ext/uri/php_uri.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ static PHP_MSHUTDOWN_FUNCTION(uri)
10771077

10781078
PHP_RINIT_FUNCTION(uri)
10791079
{
1080-
if (lexbor_request_init() == FAILURE) {
1080+
if (PHP_RINIT(uri_parser_whatwg)(INIT_FUNC_ARGS_PASSTHRU) == FAILURE) {
10811081
return FAILURE;
10821082
}
10831083

@@ -1086,7 +1086,9 @@ PHP_RINIT_FUNCTION(uri)
10861086

10871087
PHP_RSHUTDOWN_FUNCTION(uri)
10881088
{
1089-
lexbor_request_shutdown();
1089+
if (PHP_RSHUTDOWN(uri_parser_whatwg)(INIT_FUNC_ARGS_PASSTHRU) == FAILURE) {
1090+
return FAILURE;
1091+
}
10901092

10911093
return SUCCESS;
10921094
}

ext/uri/uri_parser_rfc3986.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ static uriparser_uris_t *uriparser_create_uris(void)
283283
return uriparser_uris;
284284
}
285285

286-
void *uriparser_parse_uri_ex(const char *uri_str, size_t uri_str_len, const uriparser_uris_t *uriparser_base_urls, bool silent)
286+
uriparser_uris_t *uriparser_parse_uri_ex(const char *uri_str, size_t uri_str_len, const uriparser_uris_t *uriparser_base_urls, bool silent)
287287
{
288288
UriUriA uri = {0};
289289

0 commit comments

Comments
 (0)