Coverage Report

Created: 2026-06-02 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/Zend/zend_multibyte.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Zend Engine                                                          |
4
   +----------------------------------------------------------------------+
5
   | Copyright © Zend Technologies Ltd., a subsidiary company of          |
6
   |     Perforce Software, Inc., and Contributors.                       |
7
   +----------------------------------------------------------------------+
8
   | This source file is subject to the Modified BSD License that is      |
9
   | bundled with this package in the file LICENSE, and is available      |
10
   | through the World Wide Web at <https://www.php.net/license/>.        |
11
   |                                                                      |
12
   | SPDX-License-Identifier: BSD-3-Clause                                |
13
   +----------------------------------------------------------------------+
14
   | Authors: Masaki Fujimoto <fujimoto@php.net>                          |
15
   |          Rui Hirokawa <hirokawa@php.net>                             |
16
   +----------------------------------------------------------------------+
17
*/
18
19
#include "zend.h"
20
#include "zend_compile.h"
21
#include "zend_operators.h"
22
#include "zend_multibyte.h"
23
#include "zend_ini.h"
24
25
static const zend_encoding *dummy_encoding_fetcher(const char *encoding_name)
26
0
{
27
0
  return NULL;
28
0
}
29
30
static const char *dummy_encoding_name_getter(const zend_encoding *encoding)
31
0
{
32
0
  return (const char*)encoding;
33
0
}
34
35
static bool dummy_encoding_lexer_compatibility_checker(const zend_encoding *encoding)
36
0
{
37
0
  return false;
38
0
}
39
40
static const zend_encoding *dummy_encoding_detector(const unsigned char *string, size_t length, const zend_encoding **list, size_t list_size)
41
0
{
42
0
  return NULL;
43
0
}
44
45
static size_t dummy_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const zend_encoding *encoding_to, const zend_encoding *encoding_from)
46
0
{
47
0
  return (size_t)-1;
48
0
}
49
50
static zend_result dummy_encoding_list_parser(const char *encoding_list, size_t encoding_list_len, const zend_encoding ***return_list, size_t *return_size, bool persistent)
51
10
{
52
10
  *return_list = pemalloc(0, persistent);
53
10
  *return_size = 0;
54
10
  return SUCCESS;
55
10
}
56
57
static const zend_encoding *dummy_internal_encoding_getter(void)
58
0
{
59
0
  return NULL;
60
0
}
61
62
static zend_result dummy_internal_encoding_setter(const zend_encoding *encoding)
63
0
{
64
0
  return FAILURE;
65
0
}
66
67
static zend_multibyte_functions multibyte_functions_dummy;
68
static zend_multibyte_functions multibyte_functions = {
69
  NULL,
70
  dummy_encoding_fetcher,
71
  dummy_encoding_name_getter,
72
  dummy_encoding_lexer_compatibility_checker,
73
  dummy_encoding_detector,
74
  dummy_encoding_converter,
75
  dummy_encoding_list_parser,
76
  dummy_internal_encoding_getter,
77
  dummy_internal_encoding_setter
78
};
79
80
ZEND_API const zend_encoding *zend_multibyte_encoding_utf32be = (const zend_encoding*)"UTF-32BE";
81
ZEND_API const zend_encoding *zend_multibyte_encoding_utf32le = (const zend_encoding*)"UTF-32LE";
82
ZEND_API const zend_encoding *zend_multibyte_encoding_utf16be = (const zend_encoding*)"UTF-16BE";
83
ZEND_API const zend_encoding *zend_multibyte_encoding_utf16le = (const zend_encoding*)"UTF-32LE";
84
ZEND_API const zend_encoding *zend_multibyte_encoding_utf8 = (const zend_encoding*)"UTF-8";
85
86
ZEND_API zend_result zend_multibyte_set_functions(const zend_multibyte_functions *functions)
87
0
{
88
0
  zend_multibyte_encoding_utf32be = functions->encoding_fetcher("UTF-32BE");
89
0
  if (!zend_multibyte_encoding_utf32be) {
90
0
    return FAILURE;
91
0
  }
92
0
  zend_multibyte_encoding_utf32le = functions->encoding_fetcher("UTF-32LE");
93
0
  if (!zend_multibyte_encoding_utf32le) {
94
0
    return FAILURE;
95
0
  }
96
0
  zend_multibyte_encoding_utf16be = functions->encoding_fetcher("UTF-16BE");
97
0
  if (!zend_multibyte_encoding_utf16be) {
98
0
    return FAILURE;
99
0
  }
100
0
  zend_multibyte_encoding_utf16le = functions->encoding_fetcher("UTF-16LE");
101
0
  if (!zend_multibyte_encoding_utf16le) {
102
0
    return FAILURE;
103
0
  }
104
0
  zend_multibyte_encoding_utf8 = functions->encoding_fetcher("UTF-8");
105
0
  if (!zend_multibyte_encoding_utf8) {
106
0
    return FAILURE;
107
0
  }
108
109
0
  multibyte_functions_dummy = multibyte_functions;
110
0
  multibyte_functions = *functions;
111
112
  /* As zend_multibyte_set_functions() gets called after ini settings were
113
   * populated, we need to reinitialize script_encoding here.
114
   */
115
0
  {
116
0
    const zend_string *value = zend_ini_str_literal("zend.script_encoding");
117
0
    zend_multibyte_set_script_encoding_by_string(ZSTR_VAL(value), ZSTR_LEN(value));
118
0
  }
119
0
  return SUCCESS;
120
0
}
121
122
ZEND_API void zend_multibyte_restore_functions(void)
123
0
{
124
0
  multibyte_functions = multibyte_functions_dummy;
125
0
}
126
127
ZEND_API const zend_multibyte_functions *zend_multibyte_get_functions(void)
128
1
{
129
1
  return multibyte_functions.provider_name ? &multibyte_functions: NULL;
130
1
}
131
132
ZEND_API const zend_encoding *zend_multibyte_fetch_encoding(const char *name)
133
0
{
134
0
  return multibyte_functions.encoding_fetcher(name);
135
0
}
136
137
ZEND_API const char *zend_multibyte_get_encoding_name(const zend_encoding *encoding)
138
0
{
139
0
  return multibyte_functions.encoding_name_getter(encoding);
140
0
}
141
142
ZEND_API int zend_multibyte_check_lexer_compatibility(const zend_encoding *encoding)
143
0
{
144
0
  return multibyte_functions.lexer_compatibility_checker(encoding);
145
0
}
146
147
ZEND_API const zend_encoding *zend_multibyte_encoding_detector(const unsigned char *string, size_t length, const zend_encoding **list, size_t list_size)
148
0
{
149
0
  return multibyte_functions.encoding_detector(string, length, list, list_size);
150
0
}
151
152
ZEND_API size_t zend_multibyte_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const zend_encoding *encoding_to, const zend_encoding *encoding_from)
153
0
{
154
0
  return multibyte_functions.encoding_converter(to, to_length, from, from_length, encoding_to, encoding_from);
155
0
}
156
157
ZEND_API zend_result zend_multibyte_parse_encoding_list(const char *encoding_list, size_t encoding_list_len, const zend_encoding ***return_list, size_t *return_size, bool persistent)
158
10
{
159
10
  return multibyte_functions.encoding_list_parser(encoding_list, encoding_list_len, return_list, return_size, persistent);
160
10
}
161
162
ZEND_API const zend_encoding *zend_multibyte_get_internal_encoding(void)
163
0
{
164
0
  return multibyte_functions.internal_encoding_getter();
165
0
}
166
167
ZEND_API const zend_encoding *zend_multibyte_get_script_encoding(void)
168
0
{
169
0
  return LANG_SCNG(script_encoding);
170
0
}
171
172
ZEND_API zend_result zend_multibyte_set_script_encoding(const zend_encoding **encoding_list, size_t encoding_list_size)
173
0
{
174
0
  if (CG(script_encoding_list)) {
175
0
    free((char*)CG(script_encoding_list));
176
0
  }
177
0
  CG(script_encoding_list) = encoding_list;
178
0
  CG(script_encoding_list_size) = encoding_list_size;
179
0
  return SUCCESS;
180
0
}
181
182
ZEND_API zend_result zend_multibyte_set_internal_encoding(const zend_encoding *encoding)
183
0
{
184
0
  return multibyte_functions.internal_encoding_setter(encoding);
185
0
}
186
187
ZEND_API zend_result zend_multibyte_set_script_encoding_by_string(const char *new_value, size_t new_value_length)
188
0
{
189
0
  const zend_encoding **list = 0;
190
0
  size_t size = 0;
191
192
0
  if (!new_value) {
193
0
    zend_multibyte_set_script_encoding(NULL, 0);
194
0
    return SUCCESS;
195
0
  }
196
197
0
  if (FAILURE == zend_multibyte_parse_encoding_list(new_value, new_value_length, &list, &size, true)) {
198
0
    return FAILURE;
199
0
  }
200
201
0
  if (size == 0) {
202
0
    pefree((void*)list, 1);
203
0
    return FAILURE;
204
0
  }
205
206
0
  if (FAILURE == zend_multibyte_set_script_encoding(list, size)) {
207
0
    return FAILURE;
208
0
  }
209
210
0
  return SUCCESS;
211
0
}