diff options
Diffstat (limited to 'ext/json/json_encoder.c')
-rw-r--r-- | ext/json/json_encoder.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index 9d480bcc90..50dcc02052 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -285,20 +285,30 @@ static int php_json_escape_string( do { us = (unsigned char)s[pos]; if (us >= 0x80) { + int utf8_sub = 0; size_t prev_pos = pos; us = php_next_utf8_char((unsigned char *)s, len, &pos, &status); /* check whether UTF8 character is correct */ if (status != SUCCESS) { - if (buf->s) { - ZSTR_LEN(buf->s) = checkpoint; - } - encoder->error_code = PHP_JSON_ERROR_UTF8; - if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) { - smart_str_appendl(buf, "null", 4); + if (options & PHP_JSON_INVALID_UTF8_IGNORE) { + /* ignore invalid UTF8 character */ + continue; + } else if (options & PHP_JSON_INVALID_UTF8_SUBSTITUTE) { + /* Use Unicode character 'REPLACEMENT CHARACTER' (U+FFFD) */ + us = 0xfffd; + utf8_sub = 1; + } else { + if (buf->s) { + ZSTR_LEN(buf->s) = checkpoint; + } + encoder->error_code = PHP_JSON_ERROR_UTF8; + if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) { + smart_str_appendl(buf, "null", 4); + } + return FAILURE; } - return FAILURE; } /* Escape U+2028/U+2029 line terminators, UNLESS both @@ -307,7 +317,11 @@ static int php_json_escape_string( if ((options & PHP_JSON_UNESCAPED_UNICODE) && ((options & PHP_JSON_UNESCAPED_LINE_TERMINATORS) || us < 0x2028 || us > 0x2029)) { - smart_str_appendl(buf, s + prev_pos, pos - prev_pos); + if (utf8_sub) { + smart_str_appendl(buf, "\xef\xbf\xbd", 3); + } else { + smart_str_appendl(buf, s + prev_pos, pos - prev_pos); + } continue; } /* From http://en.wikipedia.org/wiki/UTF16 */ |