Skip to content

Commit d4f5c84

Browse files
authored
uri: Throw when trying to modify URI objects after creation (php#19768)
This will also fix a memory leak, since the constructor did not free any pre-existing `->uri`.
1 parent ab808ea commit d4f5c84

File tree

2 files changed

+127
-1
lines changed

2 files changed

+127
-1
lines changed

ext/uri/php_uri.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,10 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri(
323323
uri_object_t *uri_object;
324324
if (should_update_this_object) {
325325
uri_object = Z_URI_OBJECT_P(ZEND_THIS);
326+
if (uri_object->internal.uri != NULL) {
327+
zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
328+
RETURN_THROWS();
329+
}
326330
} else {
327331
if (EX(func)->common.fn_flags & ZEND_ACC_STATIC) {
328332
object_init_ex(return_value, Z_CE_P(ZEND_THIS));
@@ -842,7 +846,12 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS)
842846
}
843847

844848
uri_internal_t *internal_uri = uri_internal_from_obj(object);
845-
internal_uri->parser->free(internal_uri->uri);
849+
if (internal_uri->uri != NULL) {
850+
/* Intentionally throw two exceptions for proper chaining. */
851+
zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
852+
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
853+
RETURN_THROWS();
854+
}
846855
internal_uri->uri = internal_uri->parser->parse(Z_STRVAL_P(uri_zv), Z_STRLEN_P(uri_zv), NULL, NULL, true);
847856
if (internal_uri->uri == NULL) {
848857
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));

ext/uri/tests/065.phpt

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
--TEST--
2+
Test that overwriting the URI is not possible
3+
--EXTENSIONS--
4+
uri
5+
--FILE--
6+
<?php
7+
8+
$uri = new Uri\WhatWg\Url('https://example.com');
9+
try {
10+
$uri->__construct('ftp://example.org');
11+
} catch (Throwable $e) {
12+
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
13+
}
14+
var_dump($uri);
15+
16+
$uri = new Uri\WhatWg\Url('https://example.com');
17+
try {
18+
$uri->__unserialize([['uri' => 'ftp://example.org'], []]);
19+
} catch (Throwable $e) {
20+
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
21+
}
22+
var_dump($uri);
23+
24+
$uri = new Uri\Rfc3986\Uri('https://example.com');
25+
try {
26+
$uri->__construct('ftp://example.org');
27+
} catch (Throwable $e) {
28+
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
29+
}
30+
var_dump($uri);
31+
32+
$uri = new Uri\Rfc3986\Uri('https://example.com');
33+
try {
34+
$uri->__unserialize([['uri' => 'ftp://example.org'], []]);
35+
} catch (Throwable $e) {
36+
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
37+
}
38+
var_dump($uri);
39+
40+
?>
41+
--EXPECTF--
42+
Error: Cannot modify readonly object of class Uri\WhatWg\Url
43+
object(Uri\WhatWg\Url)#%d (8) {
44+
["scheme"]=>
45+
string(5) "https"
46+
["username"]=>
47+
NULL
48+
["password"]=>
49+
NULL
50+
["host"]=>
51+
string(11) "example.com"
52+
["port"]=>
53+
NULL
54+
["path"]=>
55+
string(1) "/"
56+
["query"]=>
57+
NULL
58+
["fragment"]=>
59+
NULL
60+
}
61+
Exception: Invalid serialization data for Uri\WhatWg\Url object
62+
object(Uri\WhatWg\Url)#%d (8) {
63+
["scheme"]=>
64+
string(5) "https"
65+
["username"]=>
66+
NULL
67+
["password"]=>
68+
NULL
69+
["host"]=>
70+
string(11) "example.com"
71+
["port"]=>
72+
NULL
73+
["path"]=>
74+
string(1) "/"
75+
["query"]=>
76+
NULL
77+
["fragment"]=>
78+
NULL
79+
}
80+
Error: Cannot modify readonly object of class Uri\Rfc3986\Uri
81+
object(Uri\Rfc3986\Uri)#%d (8) {
82+
["scheme"]=>
83+
string(5) "https"
84+
["username"]=>
85+
NULL
86+
["password"]=>
87+
NULL
88+
["host"]=>
89+
string(11) "example.com"
90+
["port"]=>
91+
NULL
92+
["path"]=>
93+
string(0) ""
94+
["query"]=>
95+
NULL
96+
["fragment"]=>
97+
NULL
98+
}
99+
Exception: Invalid serialization data for Uri\Rfc3986\Uri object
100+
object(Uri\Rfc3986\Uri)#%d (8) {
101+
["scheme"]=>
102+
string(5) "https"
103+
["username"]=>
104+
NULL
105+
["password"]=>
106+
NULL
107+
["host"]=>
108+
string(11) "example.com"
109+
["port"]=>
110+
NULL
111+
["path"]=>
112+
string(0) ""
113+
["query"]=>
114+
NULL
115+
["fragment"]=>
116+
NULL
117+
}

0 commit comments

Comments
 (0)