Coverage Report

Created: 2026-09-14 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/ext/uri/php_uri_common.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Copyright © The PHP Group and Contributors.                          |
4
   +----------------------------------------------------------------------+
5
   | This source file is subject to the Modified BSD License that is      |
6
   | bundled with this package in the file LICENSE, and is available      |
7
   | through the World Wide Web at <https://www.php.net/license/>.        |
8
   |                                                                      |
9
   | SPDX-License-Identifier: BSD-3-Clause                                |
10
   +----------------------------------------------------------------------+
11
   | Authors: Máté Kocsis <kocsismate@php.net>                            |
12
   +----------------------------------------------------------------------+
13
*/
14
15
#include "php.h"
16
#include "Zend/zend_interfaces.h"
17
#include "Zend/zend_exceptions.h"
18
#include "php_uri_common.h"
19
20
static zend_string *get_known_string_by_property_name(php_uri_property_name property_name)
21
0
{
22
0
  switch (property_name) {
23
0
    case PHP_URI_PROPERTY_NAME_SCHEME:
24
0
      return ZSTR_KNOWN(ZEND_STR_SCHEME);
25
0
    case PHP_URI_PROPERTY_NAME_USERNAME:
26
0
      return ZSTR_KNOWN(ZEND_STR_USERNAME);
27
0
    case PHP_URI_PROPERTY_NAME_PASSWORD:
28
0
      return ZSTR_KNOWN(ZEND_STR_PASSWORD);
29
0
    case PHP_URI_PROPERTY_NAME_HOST:
30
0
      return ZSTR_KNOWN(ZEND_STR_HOST);
31
0
    case PHP_URI_PROPERTY_NAME_PORT:
32
0
      return ZSTR_KNOWN(ZEND_STR_PORT);
33
0
    case PHP_URI_PROPERTY_NAME_PATH:
34
0
      return ZSTR_KNOWN(ZEND_STR_PATH);
35
0
    case PHP_URI_PROPERTY_NAME_QUERY:
36
0
      return ZSTR_KNOWN(ZEND_STR_QUERY);
37
0
    case PHP_URI_PROPERTY_NAME_FRAGMENT:
38
0
      return ZSTR_KNOWN(ZEND_STR_FRAGMENT);
39
0
    default: ZEND_UNREACHABLE();
40
0
  }
41
0
}
42
43
zend_result php_uri_pass_errors_by_ref_and_free(zval *errors_zv, zval *errors)
44
0
{
45
0
  ZEND_ASSERT(Z_TYPE_P(errors) == IS_UNDEF || Z_TYPE_P(errors) == IS_ARRAY);
46
47
  /* There was no error during parsing */
48
0
  if (Z_ISUNDEF_P(errors)) {
49
0
    return SUCCESS;
50
0
  }
51
52
  /* The errors parameter is an array, but the pass-by ref argument stored by
53
   * errors_zv was not passed - the URI implementation either doesn't support
54
   * returning additional error information, or the caller is not interested in it */
55
0
  if (errors_zv == NULL) {
56
0
    zval_ptr_dtor(errors);
57
0
    return SUCCESS;
58
0
  }
59
60
0
  ZEND_TRY_ASSIGN_REF_TMP(errors_zv, errors);
61
0
  if (EG(exception)) {
62
0
    return FAILURE;
63
0
  }
64
65
0
  return SUCCESS;
66
0
}
67
68
void php_uri_property_read_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, php_uri_component_read_mode component_read_mode)
69
0
{
70
0
  ZEND_PARSE_PARAMETERS_NONE();
71
72
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
73
0
  ZEND_ASSERT(uri_object->uri != NULL);
74
75
0
  const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(uri_object->parser, property_name);
76
77
0
  if (UNEXPECTED(property_handler->read(uri_object->uri, component_read_mode, return_value) == FAILURE)) {
78
0
    zend_throw_exception_ex(php_uri_ce_error, 0, "The %s component cannot be retrieved", ZSTR_VAL(get_known_string_by_property_name(property_name)));
79
0
    RETURN_THROWS();
80
0
  }
81
0
}
82
83
static void php_uri_property_write_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, const zval *property_zv)
84
0
{
85
0
  php_uri_object *old_uri_object = Z_URI_OBJECT_P(ZEND_THIS);
86
0
  ZEND_ASSERT(old_uri_object->uri != NULL);
87
88
0
  zend_object *new_object = old_uri_object->std.handlers->clone_obj(&old_uri_object->std);
89
0
  if (new_object == NULL) {
90
0
    RETURN_THROWS();
91
0
  }
92
93
  /* Assign the object early. The engine will take care of destruction in
94
   * case of an exception being thrown. */
95
0
  RETVAL_OBJ(new_object);
96
97
0
  const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(old_uri_object->parser, property_name);
98
99
0
  php_uri_object *new_uri_object = php_uri_object_from_obj(new_object);
100
0
  ZEND_ASSERT(new_uri_object->uri != NULL);
101
0
  if (UNEXPECTED(property_handler->write == NULL)) {
102
0
    zend_readonly_property_modification_error_ex(ZSTR_VAL(old_uri_object->std.ce->name),
103
0
      ZSTR_VAL(get_known_string_by_property_name(property_name)));
104
0
    RETURN_THROWS();
105
0
  }
106
107
0
  zval errors;
108
0
  ZVAL_UNDEF(&errors);
109
0
  if (UNEXPECTED(property_handler->write(new_uri_object->uri, property_zv, &errors) == FAILURE)) {
110
0
    zval_ptr_dtor(&errors);
111
0
    RETURN_THROWS();
112
0
  }
113
114
0
  ZEND_ASSERT(Z_ISUNDEF(errors));
115
0
}
116
117
void php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name)
118
0
{
119
0
  zend_string *value;
120
121
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
122
0
    Z_PARAM_STR(value)
123
0
  ZEND_PARSE_PARAMETERS_END();
124
125
0
  zval zv;
126
0
  ZVAL_STR(&zv, value);
127
128
0
  php_uri_property_write_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv);
129
0
}
130
131
void php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name)
132
0
{
133
0
  zend_string *value;
134
135
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
136
0
    Z_PARAM_STR_OR_NULL(value)
137
0
  ZEND_PARSE_PARAMETERS_END();
138
139
0
  zval zv;
140
0
  if (value == NULL) {
141
0
    ZVAL_NULL(&zv);
142
0
  } else {
143
0
    ZVAL_STR(&zv, value);
144
0
  }
145
146
0
  php_uri_property_write_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv);
147
0
}
148
149
void php_uri_property_write_long_or_null_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name)
150
0
{
151
0
  zend_long value;
152
0
  bool value_is_null;
153
154
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
155
0
    Z_PARAM_LONG_OR_NULL(value, value_is_null)
156
0
  ZEND_PARSE_PARAMETERS_END();
157
158
0
  zval zv;
159
0
  if (value_is_null) {
160
0
    ZVAL_NULL(&zv);
161
0
  } else {
162
0
    ZVAL_LONG(&zv, value);
163
0
  }
164
165
0
  php_uri_property_write_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv);
166
0
}