Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 64 additions & 80 deletions ext/uri/php_uri.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,11 @@ static zend_array uri_parsers;

static HashTable *uri_get_debug_properties(uri_object_t *object)
{
uri_internal_t *internal_uri = &object->internal;
ZEND_ASSERT(internal_uri != NULL);

const HashTable *std_properties = zend_std_get_properties(&object->std);
HashTable *result = zend_array_dup(std_properties);

const php_uri_parser * const parser = internal_uri->parser;
void * const uri = internal_uri->uri;
const php_uri_parser * const parser = object->parser;
void * const uri = object->uri;

if (UNEXPECTED(uri == NULL)) {
return result;
Expand Down Expand Up @@ -324,7 +321,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri(
uri_object_t *uri_object;
if (should_update_this_object) {
uri_object = Z_URI_OBJECT_P(ZEND_THIS);
if (uri_object->internal.uri != NULL) {
if (uri_object->uri != NULL) {
zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
RETURN_THROWS();
}
Expand All @@ -337,18 +334,17 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri(
uri_object = Z_URI_OBJECT_P(return_value);
}

const php_uri_parser *uri_parser = uri_object->internal.parser;
const php_uri_parser *uri_parser = uri_object->parser;

zval errors;
ZVAL_UNDEF(&errors);

void *base_url = NULL;
if (base_url_object != NULL) {
ZEND_ASSERT(base_url_object->std.ce == uri_object->std.ce);
const uri_internal_t *internal_base_url = &base_url_object->internal;
URI_ASSERT_INITIALIZATION(internal_base_url);
ZEND_ASSERT(internal_base_url->parser == uri_parser);
base_url = internal_base_url->uri;
ZEND_ASSERT(base_url_object->uri != NULL);
ZEND_ASSERT(base_url_object->parser == uri_parser);
base_url = base_url_object->uri;
Comment on lines -348 to +347
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the improvement is particularly visible here, since the assertions are no longer mixed with declarations.

}

void *uri = uri_parser->parse(ZSTR_VAL(uri_str), ZSTR_LEN(uri_str), base_url, errors_zv != NULL ? &errors : NULL, !should_throw);
Expand All @@ -370,7 +366,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri(
RETURN_THROWS();
}

uri_object->internal.uri = uri;
uri_object->uri = uri;
}

static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
Expand Down Expand Up @@ -531,10 +527,10 @@ static void rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAMETERS, php_uri_componen
{
ZEND_PARSE_PARAMETERS_NONE();

uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS);
URI_ASSERT_INITIALIZATION(internal_uri);
uri_object_t *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
ZEND_ASSERT(uri_object->uri != NULL);

if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_read(internal_uri->uri, read_mode, return_value) == FAILURE)) {
if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_read(uri_object->uri, read_mode, return_value) == FAILURE)) {
zend_throw_error(NULL, "The userinfo component cannot be retrieved");
RETURN_THROWS();
}
Expand Down Expand Up @@ -565,11 +561,10 @@ PHP_METHOD(Uri_Rfc3986_Uri, withUserInfo)
ZVAL_STR(&zv, value);
}

zend_object *old_object = Z_OBJ_P(ZEND_THIS);
uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS);
URI_ASSERT_INITIALIZATION(internal_uri);
uri_object_t *old_uri_object = uri_object_from_obj(Z_OBJ_P(ZEND_THIS));
ZEND_ASSERT(old_uri_object->uri != NULL);

zend_object *new_object = old_object->handlers->clone_obj(old_object);
zend_object *new_object = old_uri_object->std.handlers->clone_obj(&old_uri_object->std);
if (new_object == NULL) {
RETURN_THROWS();
}
Expand All @@ -578,10 +573,10 @@ PHP_METHOD(Uri_Rfc3986_Uri, withUserInfo)
* case of an exception being thrown. */
RETVAL_OBJ(new_object);

uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object);
URI_ASSERT_INITIALIZATION(new_internal_uri);
uri_object_t *new_uri_object = uri_object_from_obj(new_object);
ZEND_ASSERT(new_uri_object->uri != NULL);

if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_write(new_internal_uri->uri, &zv, NULL) == FAILURE)) {
if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_write(new_uri_object->uri, &zv, NULL) == FAILURE)) {
RETURN_THROWS();
}
}
Expand Down Expand Up @@ -684,11 +679,8 @@ static void throw_cannot_recompose_uri_to_string(uri_object_t *object)
static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, uri_object_t *that_object, zend_object *comparison_mode)
{
uri_object_t *this_object = Z_URI_OBJECT_P(ZEND_THIS);
uri_internal_t *this_internal_uri = &this_object->internal;
URI_ASSERT_INITIALIZATION(this_internal_uri);

uri_internal_t *that_internal_uri = &that_object->internal;
URI_ASSERT_INITIALIZATION(that_internal_uri);
ZEND_ASSERT(this_object->uri != NULL);
ZEND_ASSERT(that_object->uri != NULL);

if (this_object->std.ce != that_object->std.ce &&
!instanceof_function(this_object->std.ce, that_object->std.ce) &&
Expand All @@ -703,15 +695,15 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, uri_object_t *that_object,
exclude_fragment = zend_string_equals_literal(Z_STR_P(case_name), "ExcludeFragment");
}

zend_string *this_str = this_internal_uri->parser->to_string(
this_internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment);
zend_string *this_str = this_object->parser->to_string(
this_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment);
if (this_str == NULL) {
throw_cannot_recompose_uri_to_string(this_object);
RETURN_THROWS();
}

zend_string *that_str = that_internal_uri->parser->to_string(
that_internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment);
zend_string *that_str = that_object->parser->to_string(
that_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment);
if (that_str == NULL) {
zend_string_release(this_str);
throw_cannot_recompose_uri_to_string(that_object);
Expand Down Expand Up @@ -742,13 +734,12 @@ PHP_METHOD(Uri_Rfc3986_Uri, toRawString)
{
ZEND_PARSE_PARAMETERS_NONE();

uri_object_t *this_object = Z_URI_OBJECT_P(ZEND_THIS);
uri_internal_t *internal_uri = &this_object->internal;
URI_ASSERT_INITIALIZATION(internal_uri);
uri_object_t *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
ZEND_ASSERT(uri_object->uri != NULL);

zend_string *uri_str = internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
if (uri_str == NULL) {
throw_cannot_recompose_uri_to_string(this_object);
throw_cannot_recompose_uri_to_string(uri_object);
RETURN_THROWS();
}

Expand All @@ -759,13 +750,12 @@ PHP_METHOD(Uri_Rfc3986_Uri, toString)
{
ZEND_PARSE_PARAMETERS_NONE();

uri_object_t *this_object = Z_URI_OBJECT_P(ZEND_THIS);
uri_internal_t *internal_uri = &this_object->internal;
URI_ASSERT_INITIALIZATION(internal_uri);
uri_object_t *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
ZEND_ASSERT(uri_object->uri != NULL);

zend_string *uri_str = internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, false);
zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, false);
if (uri_str == NULL) {
throw_cannot_recompose_uri_to_string(this_object);
throw_cannot_recompose_uri_to_string(uri_object);
RETURN_THROWS();
}

Expand All @@ -788,14 +778,13 @@ PHP_METHOD(Uri_Rfc3986_Uri, __serialize)
{
ZEND_PARSE_PARAMETERS_NONE();

uri_object_t *this_object = Z_URI_OBJECT_P(ZEND_THIS);
uri_internal_t *internal_uri = &this_object->internal;
URI_ASSERT_INITIALIZATION(internal_uri);
uri_object_t *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
ZEND_ASSERT(uri_object->uri != NULL);

/* Serialize state: "uri" key in the first array */
zend_string *uri_str = internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
if (uri_str == NULL) {
throw_cannot_recompose_uri_to_string(this_object);
throw_cannot_recompose_uri_to_string(uri_object);
RETURN_THROWS();
}
zval tmp;
Expand All @@ -809,7 +798,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, __serialize)
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);

/* Serialize regular properties: second array */
ZVAL_ARR(&arr, this_object->std.handlers->get_properties(&this_object->std));
ZVAL_ARR(&arr, uri_object->std.handlers->get_properties(&uri_object->std));
Z_TRY_ADDREF(arr);
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
}
Expand All @@ -822,56 +811,55 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS)
Z_PARAM_ARRAY_HT(data)
ZEND_PARSE_PARAMETERS_END();

zend_object *object = Z_OBJ_P(ZEND_THIS);
uri_internal_t *internal_uri = uri_internal_from_obj(object);
if (internal_uri->uri != NULL) {
uri_object_t *uri_object = uri_object_from_obj(Z_OBJ_P(ZEND_THIS));
if (uri_object->uri != NULL) {
/* Intentionally throw two exceptions for proper chaining. */
zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(object->ce->name));
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(uri_object->std.ce->name));
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
RETURN_THROWS();
}

/* Verify the expected number of elements, this implicitly ensures that no additional elements are present. */
if (zend_hash_num_elements(data) != 2) {
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
RETURN_THROWS();
}

/* Unserialize state: "uri" key in the first array */
zval *arr = zend_hash_index_find(data, 0);
if (arr == NULL || Z_TYPE_P(arr) != IS_ARRAY) {
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
RETURN_THROWS();
}

/* Verify the expected number of elements inside the first array, this implicitly ensures that no additional elements are present. */
if (zend_hash_num_elements(Z_ARRVAL_P(arr)) != 1) {
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
RETURN_THROWS();
}

zval *uri_zv = zend_hash_str_find_ind(Z_ARRVAL_P(arr), ZEND_STRL(URI_SERIALIZED_PROPERTY_NAME));
if (uri_zv == NULL || Z_TYPE_P(uri_zv) != IS_STRING) {
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
RETURN_THROWS();
}

internal_uri->uri = internal_uri->parser->parse(Z_STRVAL_P(uri_zv), Z_STRLEN_P(uri_zv), NULL, NULL, true);
if (internal_uri->uri == NULL) {
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
uri_object->uri = uri_object->parser->parse(Z_STRVAL_P(uri_zv), Z_STRLEN_P(uri_zv), NULL, NULL, true);
if (uri_object->uri == NULL) {
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
RETURN_THROWS();
}

/* Unserialize regular properties: second array */
arr = zend_hash_index_find(data, 1);
if (arr == NULL || Z_TYPE_P(arr) != IS_ARRAY) {
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
RETURN_THROWS();
}

/* Verify that there is no regular property in the second array, because the URI classes have no properties and they are final. */
if (zend_hash_num_elements(Z_ARRVAL_P(arr)) > 0) {
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
RETURN_THROWS();
}
}
Expand Down Expand Up @@ -944,21 +932,21 @@ PHP_METHOD(Uri_WhatWg_Url, toUnicodeString)
ZEND_PARSE_PARAMETERS_NONE();

zend_object *this_object = Z_OBJ_P(ZEND_THIS);
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
URI_ASSERT_INITIALIZATION(internal_uri);
uri_object_t *uri_object = uri_object_from_obj(this_object);
ZEND_ASSERT(uri_object->uri != NULL);

RETURN_STR(internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE, false));
RETURN_STR(uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE, false));
}

PHP_METHOD(Uri_WhatWg_Url, toAsciiString)
{
ZEND_PARSE_PARAMETERS_NONE();

zend_object *this_object = Z_OBJ_P(ZEND_THIS);
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
URI_ASSERT_INITIALIZATION(internal_uri);
uri_object_t *uri_object = uri_object_from_obj(this_object);
ZEND_ASSERT(uri_object->uri != NULL);

RETURN_STR(internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false));
RETURN_STR(uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false));
}

PHP_METHOD(Uri_WhatWg_Url, resolve)
Expand All @@ -981,11 +969,10 @@ PHP_METHOD(Uri_WhatWg_Url, __serialize)
ZEND_PARSE_PARAMETERS_NONE();

uri_object_t *this_object = Z_URI_OBJECT_P(ZEND_THIS);
uri_internal_t *internal_uri = &this_object->internal;
URI_ASSERT_INITIALIZATION(internal_uri);
ZEND_ASSERT(this_object->uri != NULL);

/* Serialize state: "uri" key in the first array */
zend_string *uri_str = internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
zend_string *uri_str = this_object->parser->to_string(this_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
if (uri_str == NULL) {
throw_cannot_recompose_uri_to_string(this_object);
RETURN_THROWS();
Expand Down Expand Up @@ -1027,10 +1014,8 @@ PHPAPI uri_object_t *php_uri_object_create(zend_class_entry *class_type, const p
zend_object_std_init(&uri_object->std, class_type);
object_properties_init(&uri_object->std, class_type);

uri_object->internal = (uri_internal_t){
.parser = parser,
.uri = NULL,
};
uri_object->parser = parser;
uri_object->uri = NULL;

return uri_object;
}
Expand All @@ -1049,24 +1034,23 @@ PHPAPI void php_uri_object_handler_free(zend_object *object)
{
uri_object_t *uri_object = uri_object_from_obj(object);

uri_object->internal.parser->destroy(uri_object->internal.uri);
uri_object->parser->destroy(uri_object->uri);
zend_object_std_dtor(&uri_object->std);
}

PHPAPI zend_object *php_uri_object_handler_clone(zend_object *object)
{
uri_object_t *uri_object = uri_object_from_obj(object);
uri_internal_t *internal_uri = uri_internal_from_obj(object);

URI_ASSERT_INITIALIZATION(internal_uri);
ZEND_ASSERT(uri_object->uri != NULL);

uri_object_t *new_uri_object = uri_object_from_obj(object->ce->create_object(object->ce));
ZEND_ASSERT(new_uri_object->internal.parser == internal_uri->parser);
ZEND_ASSERT(new_uri_object->parser == uri_object->parser);

void *uri = internal_uri->parser->clone(internal_uri->uri);
void *uri = uri_object->parser->clone(uri_object->uri);
ZEND_ASSERT(uri != NULL);

new_uri_object->internal.uri = uri;
new_uri_object->uri = uri;

zend_objects_clone_members(&new_uri_object->std, &uri_object->std);

Expand Down
Loading