]> granicus.if.org Git - php/commitdiff
Fixed corruption of execute_data when ZEND_STRLEN has to cast an object to string.
authorTjerk Meesters <datibbaw@php.net>
Wed, 27 Aug 2014 14:59:18 +0000 (22:59 +0800)
committerTjerk Meesters <datibbaw@php.net>
Wed, 27 Aug 2014 15:00:11 +0000 (23:00 +0800)
Zend/tests/strlen.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/strlen.phpt b/Zend/tests/strlen.phpt
new file mode 100644 (file)
index 0000000..ddf0141
--- /dev/null
@@ -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"
index 07fd4bafb0cf684357a43e44d23a8379138326c3..d856abb88bb28b936705ccf807ed54de40580faf 100644 (file)
@@ -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)));
index 0929507e9235d7030905858967c5a948f603483d..52346cbc0dd9aa43ff4e4d52d336a6373c6a2003 100644 (file)
@@ -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)));