Skip to content

Commit 79d8d24

Browse files
committed
Review fixes + optimize property reads + fix leak
1 parent f99c5ee commit 79d8d24

2 files changed

Lines changed: 39 additions & 37 deletions

File tree

ext/uri/php_uri.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ zend_class_entry *php_uri_ce_whatwg_url_validation_error;
4747
static zend_object_handlers object_handlers_rfc3986_uri;
4848
static zend_object_handlers object_handlers_whatwg_uri;
4949

50-
typedef bool (*php_uri_string_component_validator)(const zend_string *component);
51-
typedef bool (*php_uri_long_component_validator)(zend_long component);
50+
typedef bool (*php_uri_component_validator_string)(const zend_string *component);
51+
typedef bool (*php_uri_component_validator_long)(zend_long component);
5252

5353
static const zend_module_dep uri_deps[] = {
5454
ZEND_MOD_REQUIRED("lexbor")
@@ -1060,7 +1060,7 @@ PHP_METHOD(Uri_Rfc3986_UriBuilder, reset)
10601060
zend_update_property_null(php_uri_ce_rfc3986_uri_builder, Z_OBJ_P(ZEND_THIS), ZEND_STRL("scheme"));
10611061
zend_update_property_null(php_uri_ce_rfc3986_uri_builder, Z_OBJ_P(ZEND_THIS), ZEND_STRL("userinfo"));
10621062
zend_update_property_null(php_uri_ce_rfc3986_uri_builder, Z_OBJ_P(ZEND_THIS), ZEND_STRL("host"));
1063-
zend_update_property_stringl(php_uri_ce_rfc3986_uri_builder, Z_OBJ_P(ZEND_THIS), ZEND_STRL("path"), "", 0);
1063+
zend_update_property_str(php_uri_ce_rfc3986_uri_builder, Z_OBJ_P(ZEND_THIS), ZEND_STRL("path"), ZSTR_EMPTY_ALLOC());
10641064
zend_update_property_null(php_uri_ce_rfc3986_uri_builder, Z_OBJ_P(ZEND_THIS), ZEND_STRL("query"));
10651065
zend_update_property_null(php_uri_ce_rfc3986_uri_builder, Z_OBJ_P(ZEND_THIS), ZEND_STRL("fragment"));
10661066

@@ -1069,7 +1069,7 @@ PHP_METHOD(Uri_Rfc3986_UriBuilder, reset)
10691069

10701070
ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string(
10711071
INTERNAL_FUNCTION_PARAMETERS, const char *name, size_t name_length,
1072-
const php_uri_string_component_validator validator
1072+
const php_uri_component_validator_string validator
10731073
) {
10741074
zend_string *component;
10751075

@@ -1089,7 +1089,7 @@ ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string(
10891089

10901090
ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string_or_null(
10911091
INTERNAL_FUNCTION_PARAMETERS, const char *name, size_t name_length,
1092-
const php_uri_string_component_validator validator
1092+
const php_uri_component_validator_string validator
10931093
) {
10941094
zend_string *component;
10951095

@@ -1113,7 +1113,7 @@ ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string_or_null(
11131113

11141114
ZEND_ATTRIBUTE_NONNULL_ARGS(1) static void php_uri_builder_set_component_long_or_null(
11151115
INTERNAL_FUNCTION_PARAMETERS, const char *name, size_t name_length,
1116-
const php_uri_long_component_validator validator
1116+
const php_uri_component_validator_long validator
11171117
) {
11181118
zend_long component;
11191119
bool component_is_null;
@@ -1209,15 +1209,14 @@ PHP_METHOD(Uri_Rfc3986_UriBuilder, build)
12091209
ZEND_PARSE_PARAMETERS_END();
12101210

12111211
zend_object *obj = Z_OBJ_P(ZEND_THIS);
1212-
zval tmp;
12131212

1214-
const zval *scheme = zend_read_property(obj->ce, obj, ZEND_STRL("scheme"), false, &tmp);
1215-
const zval *userinfo = zend_read_property(obj->ce, obj, ZEND_STRL("userinfo"), false, &tmp);
1216-
const zval *host = zend_read_property(obj->ce, obj, ZEND_STRL("host"), false, &tmp);
1217-
const zval *port = zend_read_property(obj->ce, obj, ZEND_STRL("port"), false, &tmp);
1218-
const zval *path = zend_read_property(obj->ce, obj, ZEND_STRL("path"), false, &tmp);
1219-
const zval *query = zend_read_property(obj->ce, obj, ZEND_STRL("query"), false, &tmp);
1220-
const zval *fragment = zend_read_property(obj->ce, obj, ZEND_STRL("fragment"), false, &tmp);
1213+
const zval *scheme = OBJ_PROP_NUM(obj, 0);
1214+
const zval *userinfo = OBJ_PROP_NUM(obj, 1);
1215+
const zval *host = OBJ_PROP_NUM(obj, 2);
1216+
const zval *port = OBJ_PROP_NUM(obj, 3);
1217+
const zval *path = OBJ_PROP_NUM(obj, 4);
1218+
const zval *query = OBJ_PROP_NUM(obj, 5);
1219+
const zval *fragment = OBJ_PROP_NUM(obj, 6);
12211220

12221221
zend_string *uri_str = php_uri_parser_rfc3986_recompose_from_zval(scheme, userinfo, host, port, path, query, fragment);
12231222
if (uri_str == NULL) {

ext/uri/uri_parser_rfc3986.c

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -723,19 +723,20 @@ ZEND_ATTRIBUTE_NONNULL bool php_uri_parser_rfc3986_validate_port(zend_long port)
723723
const char *p = ZSTR_VAL(tmp);
724724
const size_t len = ZSTR_LEN(tmp);
725725

726-
return uriIsWellFormedPortA(p, p + len);
726+
bool result = uriIsWellFormedPortA(p, p + len);
727+
zend_string_release(tmp);
728+
729+
return result;
727730
}
728731

729732
ZEND_ATTRIBUTE_NONNULL bool php_uri_parser_rfc3986_validate_path(const zend_string *path)
730733
{
731734
const char *p = ZSTR_VAL(path);
732735
const size_t len = ZSTR_LEN(path);
733736

734-
/*
735-
It's checked during the build() method whether the path begins with a "/" when there's a host
736-
that's why a false hasHost argument is passed to uriIsWellFormedPathA() for now.
737-
*/
738-
return uriIsWellFormedPathA(p, p + len, false);
737+
/* The build() method checks whether the path begins with a "/" when there's a host.
738+
* In order to skip doing the same check, a false hasHost argument is passed to uriIsWellFormedPathA(). */
739+
return uriIsWellFormedPathA(p, p + len, /* hasHost */ false);
739740
}
740741

741742
ZEND_ATTRIBUTE_NONNULL bool php_uri_parser_rfc3986_validate_query(const zend_string *query)
@@ -756,18 +757,26 @@ ZEND_ATTRIBUTE_NONNULL bool php_uri_parser_rfc3986_validate_fragment(const zend_
756757

757758
ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_rfc3986_recompose_from_zval(
758759
const zval *scheme, const zval *userinfo, const zval *host, const zval *port,
759-
const zval *path, const zval *query, const zval *fragment)
760-
{
761-
/* The userinfo and port components can only ever be present if the host is present */
762-
if ((Z_TYPE_P(userinfo) != IS_NULL || Z_TYPE_P(port) != IS_NULL) && Z_TYPE_P(host) == IS_NULL) {
763-
zend_throw_exception(php_uri_ce_invalid_uri_exception, "The URI must contain a host if either the userinfo or the port component is present", 0);
764-
return NULL;
765-
}
760+
const zval *path, const zval *query, const zval *fragment
761+
) {
762+
if (Z_TYPE_P(host) == IS_NULL) {
763+
/* The path must not begin with "//" if the URI doesn't contain a host */
764+
if (zend_string_starts_with_literal(Z_STR_P(path), "//")) {
765+
zend_throw_exception(php_uri_ce_invalid_uri_exception, "The path must not begin with \"//\" when the URI doesn't contain a host", 0);
766+
return NULL;
767+
}
766768

767-
/* The path must be either empty or begin with a "/" if the URI contains a host */
768-
if (Z_TYPE_P(host) != IS_NULL && (Z_STRLEN_P(path) > 0 && Z_STRVAL_P(path)[0] != '/')) {
769-
zend_throw_exception(php_uri_ce_invalid_uri_exception, "A path must be either empty or begin with \"/\" when the URI contains a host", 0);
770-
return NULL;
769+
/* The userinfo and port components must not be present if the URI doesn't contain a host */
770+
if (Z_TYPE_P(userinfo) != IS_NULL || Z_TYPE_P(port) != IS_NULL) {
771+
zend_throw_exception(php_uri_ce_invalid_uri_exception, "The URI must contain a host if either the userinfo or the port component is present", 0);
772+
return NULL;
773+
}
774+
} else {
775+
/* The path must be either empty or begin with a "/" if the URI contains a host */
776+
if (Z_STRLEN_P(path) > 0 && Z_STRVAL_P(path)[0] != '/') {
777+
zend_throw_exception(php_uri_ce_invalid_uri_exception, "A path must be either empty or begin with \"/\" when the URI contains a host", 0);
778+
return NULL;
779+
}
771780
}
772781

773782
/* The first segment of the path must not contain ":" if the URI doesn't contain a scheme */
@@ -783,12 +792,6 @@ ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_rfc3986_recompose_from_zval(
783792
}
784793
}
785794

786-
/* The path must not begin with "//" if the URI doesn't contain a host */
787-
if (Z_TYPE_P(host) == IS_NULL && Z_STRLEN_P(path) >= 2 && Z_STRVAL_P(path)[0] == '/' && Z_STRVAL_P(path)[1] == '/') {
788-
zend_throw_exception(php_uri_ce_invalid_uri_exception, "The path must not begin with \"//\" when the URI doesn't contain a host", 0);
789-
return NULL;
790-
}
791-
792795
/* result = "" */
793796
smart_str uri_str = {0};
794797

0 commit comments

Comments
 (0)