summaryrefslogtreecommitdiff
path: root/ext/json/json_encoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/json/json_encoder.c')
-rw-r--r--ext/json/json_encoder.c72
1 files changed, 25 insertions, 47 deletions
diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c
index c5f92e1919..545d229f35 100644
--- a/ext/json/json_encoder.c
+++ b/ext/json/json_encoder.c
@@ -117,14 +117,14 @@ static inline void php_json_encode_double(smart_str *buf, double d, int options)
#define PHP_JSON_HASH_APPLY_PROTECTION_INC(_tmp_ht) \
do { \
- if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(_tmp_ht)) { \
+ if (_tmp_ht && ZEND_HASH_APPLY_PROTECTION(_tmp_ht)) { \
ZEND_HASH_INC_APPLY_COUNT(_tmp_ht); \
} \
} while (0)
#define PHP_JSON_HASH_APPLY_PROTECTION_DEC(_tmp_ht) \
do { \
- if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(_tmp_ht)) { \
+ if (_tmp_ht && ZEND_HASH_APPLY_PROTECTION(_tmp_ht)) { \
ZEND_HASH_DEC_APPLY_COUNT(_tmp_ht); \
} \
} while (0)
@@ -142,12 +142,14 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
r = PHP_JSON_OUTPUT_OBJECT;
}
- if (myht && ZEND_HASH_GET_APPLY_COUNT(myht) > 1) {
+ if (myht && ZEND_HASH_GET_APPLY_COUNT(myht) > 0) {
encoder->error_code = PHP_JSON_ERROR_RECURSION;
smart_str_appendl(buf, "null", 4);
return FAILURE;
}
+ PHP_JSON_HASH_APPLY_PROTECTION_INC(myht);
+
if (r == PHP_JSON_OUTPUT_ARRAY) {
smart_str_appendc(buf, '[');
} else {
@@ -162,13 +164,8 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
zend_string *key;
zval *data;
zend_ulong index;
- HashTable *tmp_ht;
ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, data) {
- ZVAL_DEREF(data);
- tmp_ht = HASH_OF(data);
- PHP_JSON_HASH_APPLY_PROTECTION_INC(tmp_ht);
-
if (r == PHP_JSON_OUTPUT_ARRAY) {
if (need_comma) {
smart_str_appendc(buf, ',');
@@ -182,7 +179,6 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
if (key) {
if (ZSTR_VAL(key)[0] == '\0' && ZSTR_LEN(key) > 0 && Z_TYPE_P(val) == IS_OBJECT) {
/* Skip protected and private members. */
- PHP_JSON_HASH_APPLY_PROTECTION_DEC(tmp_ht);
continue;
}
@@ -218,14 +214,14 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
if (php_json_encode_zval(buf, data, options, encoder) == FAILURE &&
!(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
- PHP_JSON_HASH_APPLY_PROTECTION_DEC(tmp_ht);
+ PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
return FAILURE;
}
-
- PHP_JSON_HASH_APPLY_PROTECTION_DEC(tmp_ht);
} ZEND_HASH_FOREACH_END();
}
+ PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
+
if (encoder->depth > encoder->max_depth) {
encoder->error_code = PHP_JSON_ERROR_DEPTH;
if (!(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
@@ -250,40 +246,23 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
}
/* }}} */
-static int php_json_utf8_to_utf16(unsigned short *utf16, char utf8[], size_t len) /* {{{ */
+static int php_json_valid_utf8(char utf8[], size_t len) /* {{{ */
{
size_t pos = 0, us;
- int j, status;
+ int status;
- if (utf16) {
- /* really convert the utf8 string */
- for (j=0 ; pos < len ; j++) {
- us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
- if (status != SUCCESS) {
- return -1;
- }
- /* From http://en.wikipedia.org/wiki/UTF16 */
- if (us >= 0x10000) {
- us -= 0x10000;
- utf16[j++] = (unsigned short)((us >> 10) | 0xd800);
- utf16[j] = (unsigned short)((us & 0x3ff) | 0xdc00);
- } else {
- utf16[j] = (unsigned short)us;
- }
- }
- } else {
- /* Only check if utf8 string is valid, and compute utf16 length */
- for (j=0 ; pos < len ; j++) {
+ while (pos < len) {
+ us = (unsigned char)utf8[pos];
+ if (us < 0x80) {
+ pos++;
+ } else {
us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
if (status != SUCCESS) {
- return -1;
- }
- if (us >= 0x10000) {
- j++;
+ return 0;
}
}
}
- return j;
+ return 1;
}
/* }}} */
@@ -319,7 +298,7 @@ static int php_json_escape_string(
if (options & PHP_JSON_UNESCAPED_UNICODE) {
/* validate UTF-8 string first */
- if (php_json_utf8_to_utf16(NULL, s, len) < 0) {
+ if (!php_json_valid_utf8(s, len)) {
encoder->error_code = PHP_JSON_ERROR_UTF8;
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
smart_str_appendl(buf, "null", 4);
@@ -475,17 +454,11 @@ static int php_json_escape_string(
static int php_json_encode_serializable_object(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */
{
zend_class_entry *ce = Z_OBJCE_P(val);
+ HashTable* myht = Z_OBJPROP_P(val);
zval retval, fname;
- HashTable* myht;
int return_code;
- if (Z_TYPE_P(val) == IS_ARRAY) {
- myht = Z_ARRVAL_P(val);
- } else {
- myht = Z_OBJPROP_P(val);
- }
-
- if (myht && ZEND_HASH_GET_APPLY_COUNT(myht) > 1) {
+ if (myht && ZEND_HASH_GET_APPLY_COUNT(myht) > 0) {
encoder->error_code = PHP_JSON_ERROR_RECURSION;
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
smart_str_appendl(buf, "null", 4);
@@ -493,6 +466,7 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
return FAILURE;
}
+ PHP_JSON_HASH_APPLY_PROTECTION_INC(myht);
ZVAL_STRING(&fname, "jsonSerialize");
@@ -505,6 +479,7 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
smart_str_appendl(buf, "null", 4);
}
+ PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
return FAILURE;
}
@@ -516,16 +491,19 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
smart_str_appendl(buf, "null", 4);
}
+ PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
return FAILURE;
}
if ((Z_TYPE(retval) == IS_OBJECT) &&
(Z_OBJ(retval) == Z_OBJ_P(val))) {
/* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
+ PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
return_code = php_json_encode_array(buf, &retval, options, encoder);
} else {
/* All other types, encode as normal */
return_code = php_json_encode_zval(buf, &retval, options, encoder);
+ PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
}
zval_ptr_dtor(&retval);