Skip to content

Commit d03e740

Browse files
committed
uri: Stop touching the lxb_url_parser_t.idna field
Looking at the Lexbor implementation, the `lxb_url_parser_t.idna` field is private and must not be touched from the outside. Lexbor expects to be able to manage it by itself when destroying a parser object. Fix the issue by putting the `lxb_unicode_idna_t` into a thread-local variable that we own. This also avoids one level of dynamic allocation. The same is done for the mraw.
1 parent 5d5305d commit d03e740

File tree

1 file changed

+36
-31
lines changed

1 file changed

+36
-31
lines changed

ext/uri/uri_parser_whatwg.c

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
#include <arpa/inet.h>
2525
#endif
2626

27-
ZEND_TLS lxb_url_parser_t lexbor_parser;
27+
ZEND_TLS lexbor_mraw_t lexbor_mraw = {0};
28+
ZEND_TLS lxb_url_parser_t lexbor_parser = {0};
29+
ZEND_TLS lxb_unicode_idna_t lexbor_idna = {0};
2830
ZEND_TLS unsigned short int parsed_urls;
2931

3032
static const unsigned short int maximum_parses_before_cleanup = 500;
@@ -333,17 +335,6 @@ static zend_result php_uri_parser_whatwg_password_write(struct uri_internal_t *i
333335
return SUCCESS;
334336
}
335337

336-
static zend_result init_idna(void)
337-
{
338-
if (lexbor_parser.idna != NULL) {
339-
return SUCCESS;
340-
}
341-
342-
lexbor_parser.idna = lxb_unicode_idna_create();
343-
344-
return lxb_unicode_idna_init(lexbor_parser.idna) == LXB_STATUS_OK ? SUCCESS : FAILURE;
345-
}
346-
347338
static zend_result php_uri_parser_whatwg_host_read(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
348339
{
349340
const lxb_url_t *lexbor_uri = internal_uri->uri;
@@ -368,11 +359,8 @@ static zend_result php_uri_parser_whatwg_host_read(const struct uri_internal_t *
368359
switch (read_mode) {
369360
case URI_COMPONENT_READ_NORMALIZED_UNICODE: {
370361
smart_str host_str = {0};
371-
if (init_idna() == FAILURE) {
372-
return FAILURE;
373-
}
374-
lxb_url_serialize_host_unicode(lexbor_parser.idna, &lexbor_uri->host, serialize_to_smart_str_callback, &host_str);
375-
lxb_unicode_idna_clean(lexbor_parser.idna);
362+
lxb_url_serialize_host_unicode(&lexbor_idna, &lexbor_uri->host, serialize_to_smart_str_callback, &host_str);
363+
lxb_unicode_idna_clean(&lexbor_idna);
376364

377365
ZVAL_NEW_STR(retval, smart_str_extract(&host_str));
378366
break;
@@ -525,29 +513,49 @@ static zend_result php_uri_parser_whatwg_fragment_write(struct uri_internal_t *i
525513

526514
PHP_RINIT_FUNCTION(uri_parser_whatwg)
527515
{
528-
lexbor_mraw_t *mraw = lexbor_mraw_create();
529-
lxb_status_t status = lexbor_mraw_init(mraw, lexbor_mraw_byte_size);
516+
lxb_status_t status;
517+
518+
status = lexbor_mraw_init(&lexbor_mraw, lexbor_mraw_byte_size);
530519
if (status != LXB_STATUS_OK) {
531-
lexbor_mraw_destroy(mraw, true);
532-
return FAILURE;
520+
goto fail;
533521
}
534522

535-
status = lxb_url_parser_init(&lexbor_parser, mraw);
523+
status = lxb_url_parser_init(&lexbor_parser, &lexbor_mraw);
536524
if (status != LXB_STATUS_OK) {
537-
lxb_url_parser_destroy(&lexbor_parser, false);
538-
lexbor_mraw_destroy(mraw, true);
539-
return FAILURE;
525+
goto fail;
526+
}
527+
528+
status = lxb_unicode_idna_init(&lexbor_idna);
529+
if (status != LXB_STATUS_OK) {
530+
goto fail;
540531
}
541532

542533
parsed_urls = 0;
543534

544535
return SUCCESS;
536+
537+
fail:
538+
539+
/* Unconditionally calling the _destroy() functions is
540+
* safe on a zeroed structure. */
541+
lxb_unicode_idna_destroy(&lexbor_idna, false);
542+
memset(&lexbor_idna, 0, sizeof(lexbor_idna));
543+
lxb_url_parser_destroy(&lexbor_parser, false);
544+
memset(&lexbor_parser, 0, sizeof(lexbor_parser));
545+
lexbor_mraw_destroy(&lexbor_mraw, false);
546+
memset(&lexbor_mraw, 0, sizeof(lexbor_mraw));
547+
548+
return FAILURE;
545549
}
546550

547551
PHP_RSHUTDOWN_FUNCTION(uri_parser_whatwg)
548552
{
549-
lxb_url_parser_memory_destroy(&lexbor_parser);
553+
lxb_unicode_idna_destroy(&lexbor_idna, false);
554+
memset(&lexbor_idna, 0, sizeof(lexbor_idna));
550555
lxb_url_parser_destroy(&lexbor_parser, false);
556+
memset(&lexbor_parser, 0, sizeof(lexbor_parser));
557+
lexbor_mraw_destroy(&lexbor_mraw, false);
558+
memset(&lexbor_mraw, 0, sizeof(lexbor_mraw));
551559

552560
parsed_urls = 0;
553561

@@ -600,11 +608,8 @@ static zend_string *php_uri_parser_whatwg_to_string(void *uri, uri_recomposition
600608
case URI_RECOMPOSITION_RAW_UNICODE:
601609
ZEND_FALLTHROUGH;
602610
case URI_RECOMPOSITION_NORMALIZED_UNICODE:
603-
if (init_idna() == FAILURE) {
604-
return NULL;
605-
}
606-
lxb_url_serialize_idna(lexbor_parser.idna, lexbor_uri, serialize_to_smart_str_callback, &uri_str, exclude_fragment);
607-
lxb_unicode_idna_clean(lexbor_parser.idna);
611+
lxb_url_serialize_idna(&lexbor_idna, lexbor_uri, serialize_to_smart_str_callback, &uri_str, exclude_fragment);
612+
lxb_unicode_idna_clean(&lexbor_idna);
608613
break;
609614
case URI_RECOMPOSITION_RAW_ASCII:
610615
ZEND_FALLTHROUGH;

0 commit comments

Comments
 (0)