]> granicus.if.org Git - php/commitdiff
Fix recursion and protection in the failed JSON encoding
authorJakub Zelenka <bukka@php.net>
Sun, 28 Aug 2016 11:53:11 +0000 (12:53 +0100)
committerJakub Zelenka <bukka@php.net>
Mon, 29 Aug 2016 13:49:40 +0000 (14:49 +0100)
ext/json/json_encoder.c

index fd9669f9d6f52baf7a64df374db26e80df572fd9..8fd2f23dffb4dc901ebf79f0852b0a98439685e9 100644 (file)
@@ -108,6 +108,20 @@ 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)) { \
+                       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)) { \
+                       ZEND_HASH_DEC_APPLY_COUNT(_tmp_ht); \
+               } \
+       } while (0)
+
 static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{ */
 {
        int i, r, need_comma = 0;
@@ -146,9 +160,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
                ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, data) {
                        ZVAL_DEREF(data);
                        tmp_ht = HASH_OF(data);
-                       if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
-                               ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
-                       }
+                       PHP_JSON_HASH_APPLY_PROTECTION_INC(tmp_ht);
 
                        if (r == PHP_JSON_OUTPUT_ARRAY) {
                                if (need_comma) {
@@ -163,9 +175,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
                                if (key) {
                                        if (ZSTR_VAL(key)[0] == '\0' && ZSTR_LEN(key) > 0 && Z_TYPE_P(val) == IS_OBJECT) {
                                                /* Skip protected and private members. */
-                                               if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
-                                                       ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
-                                               }
+                                               PHP_JSON_HASH_APPLY_PROTECTION_DEC(tmp_ht);
                                                continue;
                                        }
 
@@ -198,19 +208,18 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
                                php_json_pretty_print_char(buf, options, ' ');
                        }
 
-                       if (php_json_encode(buf, data, options) == FAILURE && (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
+                       if (php_json_encode(buf, data, options) == FAILURE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
+                               PHP_JSON_HASH_APPLY_PROTECTION_DEC(tmp_ht);
                                return FAILURE;
                        }
 
-                       if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
-                               ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
-                       }
+                       PHP_JSON_HASH_APPLY_PROTECTION_DEC(tmp_ht);
                } ZEND_HASH_FOREACH_END();
        }
 
        if (JSON_G(encoder_depth) > JSON_G(encode_max_depth)) {
                JSON_G(error_code) = PHP_JSON_ERROR_DEPTH;
-               if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
+               if (!(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
                        return FAILURE;
                }
        }