]> granicus.if.org Git - php/commitdiff
Fixed bug #77165
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 15 Nov 2018 16:13:12 +0000 (17:13 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 15 Nov 2018 16:16:39 +0000 (17:16 +0100)
Also add some helper macros for PROTECT/UNPROTECT that check for
IMMUTABLE. These checks are needed for nearly any use of
PROTECT/UNPROTECT.

NEWS
Zend/zend_types.h
ext/mbstring/mbstring.c
ext/mbstring/tests/bug77165.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index a35d2a6b4d5cfc67207c3a2ed42cd8baeceb690f..bd1e72f898c2a2c802e8ea6b41e22ef397e23033 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,10 @@ PHP                                                                        NEWS
   . Fixed bug #77147 (Fixing 60494 ignored ICONV_MIME_DECODE_CONTINUE_ON_ERROR).
     (cmb)
 
+- MBstring:
+  . Fixed bug #77165 (mb_check_encoding crashes when argument given an empty
+    array). (Nikita)
+
 - SOAP:
   . Fixed bug #77141 (Signedness issue in SOAP when precision=-1). (cmb)
 
index 5492f17c00c87d5ace6cfcb17a6d3ede3d960612..4250aabd1f9e7ae60da7496ce364269ea780c302 100644 (file)
@@ -570,6 +570,14 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
                GC_DEL_FLAGS(p, GC_PROTECTED); \
        } while (0)
 
+#define GC_TRY_PROTECT_RECURSION(p) do { \
+               if (!(GC_FLAGS(p) & GC_IMMUTABLE)) GC_PROTECT_RECURSION(p); \
+       } while (0)
+
+#define GC_TRY_UNPROTECT_RECURSION(p) do { \
+               if (!(GC_FLAGS(p) & GC_IMMUTABLE)) GC_UNPROTECT_RECURSION(p); \
+       } while (0)
+
 #define Z_IS_RECURSIVE(zval)        GC_IS_RECURSIVE(Z_COUNTED(zval))
 #define Z_PROTECT_RECURSION(zval)   GC_PROTECT_RECURSION(Z_COUNTED(zval))
 #define Z_UNPROTECT_RECURSION(zval) GC_UNPROTECT_RECURSION(Z_COUNTED(zval))
index 6554bd72bf9c39f80606764329a40395b914f174..ae8c4bef7f38854842ea30007cbdef7163d1a66b 100644 (file)
@@ -3125,7 +3125,7 @@ MBSTRING_API HashTable *php_mb_convert_encoding_recursive(HashTable *input, cons
                php_error_docref(NULL, E_WARNING, "Cannot convert recursively referenced values");
                return NULL;
        }
-       GC_PROTECT_RECURSION(input);
+       GC_TRY_PROTECT_RECURSION(input);
        output = zend_new_array(zend_hash_num_elements(input));
        ZEND_HASH_FOREACH_KEY_VAL(input, idx, key, entry) {
                /* convert key */
@@ -3170,7 +3170,7 @@ MBSTRING_API HashTable *php_mb_convert_encoding_recursive(HashTable *input, cons
                        zend_hash_index_add(output, idx, &entry_tmp);
                }
        } ZEND_HASH_FOREACH_END();
-       GC_UNPROTECT_RECURSION(input);
+       GC_TRY_UNPROTECT_RECURSION(input);
 
        return output;
 }
@@ -4738,7 +4738,7 @@ MBSTRING_API int php_mb_check_encoding_recursive(HashTable *vars, const zend_str
                php_error_docref(NULL, E_WARNING, "Cannot not handle circular references");
                return 0;
        }
-       GC_PROTECT_RECURSION(vars);
+       GC_TRY_PROTECT_RECURSION(vars);
        ZEND_HASH_FOREACH_KEY_VAL(vars, idx, key, entry) {
                ZVAL_DEREF(entry);
                if (key) {
@@ -4772,7 +4772,7 @@ MBSTRING_API int php_mb_check_encoding_recursive(HashTable *vars, const zend_str
                                break;
                }
        } ZEND_HASH_FOREACH_END();
-       GC_UNPROTECT_RECURSION(vars);
+       GC_TRY_UNPROTECT_RECURSION(vars);
        mbfl_buffer_converter_delete(convd);
        return valid;
 }
diff --git a/ext/mbstring/tests/bug77165.phpt b/ext/mbstring/tests/bug77165.phpt
new file mode 100644 (file)
index 0000000..69708f6
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+Bug #77165: mb_check_encoding crashes when argument given an empty array
+--FILE--
+<?php
+var_dump(mb_check_encoding(array()));
+var_dump(mb_convert_encoding(array(), 'UTF-8'));
+?>
+--EXPECT--
+bool(true)
+array(0) {
+}