-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add support for Uri\Rfc3986\Uri withers #19636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_writing(uri_internal_t *internal_uri) | ||
{ | ||
php_uri_parser_rfc3986_uris *uriparser_uris = internal_uri->uri; | ||
|
||
return &uriparser_uris->uri; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I see, the implementation now has exactly the bug that #19588 was supposed to avoid: You are not resetting the normalized URI when writing and during cloning the normalized URI is cloned.
Consider this test case:
<?php
$uri = \Uri\Rfc3986\Uri::parse('https://example.com/path-%65xample/');
var_dump($uri->getPath());
var_dump($uri->getRawPath());
$newUri = $uri->withPath('/updated-path');
var_dump($newUri->getPath());
var_dump($newUri->getRawPath());
ZVAL_STR(value, zend_long_to_str(Z_LVAL_P(value))); | ||
result = uriSetPortTextMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Storing the stringified long into the zval, just to pull it out of the zval sounds like a needless layer of indirection. You can just store it as a zend_string *
directly. You are also modifying the value of the zval which can have unintended consequences.
This is also leaking memory. See this example:
<?php
$uri = \Uri\Rfc3986\Uri::parse('https://example.com/');
$port = 123;
$newUri = $uri->withPort($port);
var_dump($newUri, $port);
} | ||
|
||
if (result != URI_SUCCESS) { | ||
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified port is malformed", 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is URI_ERROR_SETPORT_HOST_NOT_SET
as a port-specific error code, that we should handle to output a better message:
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified port is malformed", 0); | |
switch (result) { | |
case URI_SUCCESS: | |
return SUCCESS; | |
case URI_ERROR_SETPORT_HOST_NOT_SET: | |
zend_throw_exception(uri_invalid_uri_exception_ce, "Cannot set a port without having a host", 0); | |
return FAILURE; | |
default: | |
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified port is malformed", 0); | |
return FAILURE; | |
} |
The same applies for the other error codes that have a special meaning.
return &uriparser_uris->uri; | ||
} | ||
|
||
ZEND_ATTRIBUTE_NONNULL static void reset_normalized_uri_after_writing(uri_internal_t *internal_uri) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having a separate method for this is risky (it's easy to forget to call it). I would suggest one of two options:
- Do not clone the normalized URI, as I did in uri: Do not copy the normalized URI when cloning RFC 3986 URIs #19588: This is likely the most performant solution when expecting that most URIs are modified after being cloned.
- Reset the normalized URI in
get_uri_for_writing()
: We expect the modification to succeed in most cases, in the worst case we're needlessly invalidating the normalized URI and it will just get renormalized.
Both options would reliably fix the issue and leave little room for human error in the implementation.
It's probably best to commit the uriparser changes separately and base the PHP changes off on top of that. |
No description provided.