]> granicus.if.org Git - php/commitdiff
Add sanity check for type of read_property return value
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 16 Mar 2021 09:38:04 +0000 (10:38 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 16 Mar 2021 09:42:47 +0000 (10:42 +0100)
If an internal class overrides read_property and declared property
types, make sure that the returned value matches the declared
type (in debug builds).

Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 11a140e8453357bce58915de38bd44572f2db293..bfafff9e35703b1eb9b60e9fff6367d188c9af4d 100644 (file)
@@ -1189,6 +1189,15 @@ static ZEND_COLD void zend_internal_call_arginfo_violation(zend_function *fbc)
                fbc->common.scope ? "::" : "",
                ZSTR_VAL(fbc->common.function_name));
 }
+
+static void zend_verify_internal_read_property_type(zend_object *obj, zend_string *name, zval *val)
+{
+       zend_property_info *prop_info =
+               zend_get_property_info(obj->ce, name, /* silent */ true);
+       if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
+               zend_verify_property_type(prop_info, val, /* strict */ true);
+       }
+}
 #endif
 
 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data)
index a81ff958f2ab0eec9b3ab8e264010f28d98b8b1c..39f121695850507f5928c3b785bcf5e0863d6e00 100644 (file)
@@ -2106,6 +2106,11 @@ ZEND_VM_C_LABEL(fetch_obj_r_fast_copy):
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if (OP2_TYPE != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
index 4f09b31909b71597ce9ba7258c91c86f293f8701..f133eab7db11a55aa3745f01f78a82739fc2cd24 100644 (file)
@@ -6286,6 +6286,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if (IS_CONST != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -8613,6 +8618,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -10963,6 +10973,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if (IS_CV != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -15382,6 +15397,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if (IS_CONST != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -16802,6 +16822,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -18114,6 +18139,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if (IS_CV != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -31487,6 +31517,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if (IS_CONST != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -33400,6 +33435,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -35899,6 +35939,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if (IS_CV != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -40086,6 +40131,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if (IS_CONST != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -43752,6 +43802,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
                        zend_tmp_string_release(tmp_name);
@@ -48795,6 +48850,11 @@ fetch_obj_r_fast_copy:
                }
 
                retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+#if ZEND_DEBUG
+               if (!EG(exception) && zobj->handlers->read_property != zend_std_read_property) {
+                       zend_verify_internal_read_property_type(zobj, name, retval);
+               }
+#endif
 
                if (IS_CV != IS_CONST) {
                        zend_tmp_string_release(tmp_name);