Skip to content

Commit 13ee8fd

Browse files
committed
Improved UTF-8 validation in JSON
1 parent fa828db commit 13ee8fd

File tree

1 file changed

+10
-27
lines changed

1 file changed

+10
-27
lines changed

ext/json/json_encoder.c

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -246,40 +246,23 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
246246
}
247247
/* }}} */
248248

249-
static int php_json_utf8_to_utf16(unsigned short *utf16, char utf8[], size_t len) /* {{{ */
249+
static int php_json_valid_utf8(char utf8[], size_t len) /* {{{ */
250250
{
251251
size_t pos = 0, us;
252-
int j, status;
252+
int status;
253253

254-
if (utf16) {
255-
/* really convert the utf8 string */
256-
for (j=0 ; pos < len ; j++) {
257-
us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
258-
if (status != SUCCESS) {
259-
return -1;
260-
}
261-
/* From http://en.wikipedia.org/wiki/UTF16 */
262-
if (us >= 0x10000) {
263-
us -= 0x10000;
264-
utf16[j++] = (unsigned short)((us >> 10) | 0xd800);
265-
utf16[j] = (unsigned short)((us & 0x3ff) | 0xdc00);
266-
} else {
267-
utf16[j] = (unsigned short)us;
268-
}
269-
}
270-
} else {
271-
/* Only check if utf8 string is valid, and compute utf16 length */
272-
for (j=0 ; pos < len ; j++) {
254+
while (pos < len) {
255+
us = (unsigned char)utf8[pos];
256+
if (us < 0x80) {
257+
pos++;
258+
} else {
273259
us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
274260
if (status != SUCCESS) {
275-
return -1;
276-
}
277-
if (us >= 0x10000) {
278-
j++;
261+
return 0;
279262
}
280263
}
281264
}
282-
return j;
265+
return 1;
283266
}
284267
/* }}} */
285268

@@ -315,7 +298,7 @@ static int php_json_escape_string(
315298

316299
if (options & PHP_JSON_UNESCAPED_UNICODE) {
317300
/* validate UTF-8 string first */
318-
if (php_json_utf8_to_utf16(NULL, s, len) < 0) {
301+
if (!php_json_valid_utf8(s, len)) {
319302
encoder->error_code = PHP_JSON_ERROR_UTF8;
320303
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
321304
smart_str_appendl(buf, "null", 4);

0 commit comments

Comments
 (0)