summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/strlen.phpt51
-rw-r--r--Zend/zend_vm_def.h6
-rw-r--r--Zend/zend_vm_execute.h24
3 files changed, 71 insertions, 10 deletions
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--
+<?php
+
+class Test
+{
+ public $something = 'hello';
+
+ public function __toString()
+ {
+ return $this->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)));