From: Tjerk Meesters Date: Wed, 27 Aug 2014 14:59:18 +0000 (+0800) Subject: Fixed corruption of execute_data when ZEND_STRLEN has to cast an object to string. X-Git-Tag: PRE_PHP7_REMOVALS~272 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a79b9333848829d78580b1c7287539f319883631;p=php Fixed corruption of execute_data when ZEND_STRLEN has to cast an object to string. --- diff --git a/Zend/tests/strlen.phpt b/Zend/tests/strlen.phpt new file mode 100644 index 0000000000..ddf0141386 --- /dev/null +++ b/Zend/tests/strlen.phpt @@ -0,0 +1,51 @@ +--TEST-- +Fixed execute_data corruption with __toString() +--FILE-- +something; + } +} + +$t = new Test; +var_dump(strlen($t)); +var_dump($t->something); + +class Test2 +{ + public $something; + + public function __construct(&$a) + { + $this->something = &$a; + } + + public function __toString() + { + return $this->something; + } +} + +$a = 'world'; +$t2 = new Test2($a); +var_dump(strlen($t2)); +var_dump($t2->something); +var_dump($a); + +$a = 'foobar'; +var_dump(strlen($t2)); +var_dump($t2->something); +--EXPECT-- +int(5) +string(5) "hello" +int(5) +string(5) "world" +string(5) "world" +int(6) +string(6) "foobar" diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 07fd4bafb0..d856abb88b 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5891,12 +5891,14 @@ ZEND_VM_HANDLER(121, ZEND_STRLEN, CONST|TMP|VAR|CV, ANY) zend_string_release(str); } else if (Z_TYPE_P(value) == IS_OBJECT) { zend_string *str; + zval tmp; - if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) { + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) { ZEND_VM_C_GOTO(strlen_error); } ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); + zval_dtor(&tmp); } else { ZEND_VM_C_LABEL(strlen_error): zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0929507e92..52346cbc0d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3388,12 +3388,14 @@ static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_string_release(str); } else if (Z_TYPE_P(value) == IS_OBJECT) { zend_string *str; + zval tmp; - if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) { + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) { goto strlen_error; } ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); + zval_dtor(&tmp); } else { strlen_error: zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); @@ -10187,12 +10189,14 @@ static int ZEND_FASTCALL ZEND_STRLEN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_string_release(str); } else if (Z_TYPE_P(value) == IS_OBJECT) { zend_string *str; + zval tmp; - if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) { + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) { goto strlen_error; } ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); + zval_dtor(&tmp); } else { strlen_error: zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); @@ -16981,12 +16985,14 @@ static int ZEND_FASTCALL ZEND_STRLEN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_string_release(str); } else if (Z_TYPE_P(value) == IS_OBJECT) { zend_string *str; + zval tmp; - if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) { + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) { goto strlen_error; } ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); + zval_dtor(&tmp); } else { strlen_error: zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); @@ -34233,12 +34239,14 @@ static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_string_release(str); } else if (Z_TYPE_P(value) == IS_OBJECT) { zend_string *str; + zval tmp; - if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) { + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) { goto strlen_error; } ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); + zval_dtor(&tmp); } else { strlen_error: zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));