]> granicus.if.org Git - php/commitdiff
Small fix and a test case to prove it
authorAndrey Hristov <andrey@php.net>
Thu, 20 Mar 2008 15:34:09 +0000 (15:34 +0000)
committerAndrey Hristov <andrey@php.net>
Thu, 20 Mar 2008 15:34:09 +0000 (15:34 +0000)
ext/mysqli/mysqli_api.c
ext/mysqli/tests/mysqli_stmt_bind_param_check_param_no_change.phpt [new file with mode: 0644]
ext/mysqlnd/mysqlnd_ps_codec.c

index 509fa81ee9b7d31c6139c52e94874e617d47a0b8..a2f1ab2b858b9f9bbb2e6e417e542948f0e6bf7e 100644 (file)
@@ -749,8 +749,10 @@ PHP_FUNCTION(mysqli_stmt_execute)
                                switch (stmt->stmt->params[i].buffer_type) {
                                        case MYSQL_TYPE_VAR_STRING:
                                                if (UG(unicode) && Z_TYPE_P(the_var) == IS_UNICODE) {
-                                                       php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
-                                                       the_var = copies[i];
+                                                       if (the_var == stmt->param.vars[i]) { 
+                                                               php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
+                                                               the_var = copies[i];
+                                                       }
                                                        zval_unicode_to_string_ex(the_var, UG(utf8_conv) TSRMLS_CC);
                                                } else {
                                                        if (the_var == stmt->param.vars[i] && Z_TYPE_P(stmt->param.vars[i]) != IS_STRING) {
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param_check_param_no_change.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param_check_param_no_change.phpt
new file mode 100644 (file)
index 0000000..5aab1a6
--- /dev/null
@@ -0,0 +1,148 @@
+--TEST--
+mysqli_stmt_bind_param() - checking whether the parameters are modified (bug#44390)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+       include "connect.inc";
+       require('table.inc');
+
+       class foo {
+         // @var $bar string
+         public $bar;
+       }
+
+       $foo = new foo;
+       $foo->bar = "фубар";
+
+       echo "Test 1: \n";
+       $stmt = $link->prepare("SELECT ? FOO");
+       var_dump($foo); // here you can see the bar member var beeing a string
+       $stmt->bind_param("s", $foo->bar);
+       var_dump($foo); // this will show $foo->bar beeing a reference string
+       $stmt->bind_result($one);
+       $stmt->execute();
+       $stmt->fetch();
+       $stmt->free_result();
+       echo("$one\n\n");
+
+       // it is getting worse. Binding the same var twice with different 
+       // types you can get unexpected results (e.g. binary trash for the
+       // string and misc data for the integer. See next 2 tests.
+
+       echo "Test 2: \n";
+       $stmt = $link->prepare("SELECT ? FOO, ? BAR");
+       var_dump($foo);
+       $stmt->bind_param("si", $foo->bar, $foo->bar);
+       echo "---\n";
+       var_dump($foo);
+       echo "---\n";
+       $stmt->execute();
+       var_dump($foo);
+       echo "---\n";
+       $stmt->bind_result($one, $two);
+       $stmt->fetch();
+       $stmt->free_result();
+       echo("$one - $two\n\n");
+
+
+       echo "Test 3: \n";
+       $stmt = $link->prepare("SELECT ? FOO, ? BAR");
+       var_dump($foo);
+       $stmt->bind_param("is", $foo->bar, $foo->bar);
+       var_dump($foo);
+       $stmt->bind_result($one, $two);
+       $stmt->execute();
+       $stmt->fetch();
+       $stmt->free_result();
+       echo("$one - $two\n\n");
+       echo "done!\n";
+?>
+--EXPECTF--
+Test 1: 
+object(foo)#3 (1) {
+  ["bar"]=>
+  string(10) "фубар"
+}
+object(foo)#3 (1) {
+  ["bar"]=>
+  &string(10) "фубар"
+}
+фубар
+
+Test 2: 
+object(foo)#3 (1) {
+  ["bar"]=>
+  string(10) "фубар"
+}
+---
+object(foo)#3 (1) {
+  ["bar"]=>
+  &string(10) "фубар"
+}
+---
+object(foo)#3 (1) {
+  ["bar"]=>
+  &string(10) "фубар"
+}
+---
+фубар - 0
+
+Test 3: 
+object(foo)#3 (1) {
+  ["bar"]=>
+  string(10) "фубар"
+}
+object(foo)#3 (1) {
+  ["bar"]=>
+  &string(10) "фубар"
+}
+0 - фубар
+
+done!
+--UEXPECTF--
+Test 1: 
+object(foo)#3 (1) {
+  [u"bar"]=>
+  unicode(5) "фубар"
+}
+object(foo)#3 (1) {
+  [u"bar"]=>
+  &unicode(5) "фубар"
+}
+фубар
+
+Test 2: 
+object(foo)#3 (1) {
+  [u"bar"]=>
+  unicode(5) "фубар"
+}
+---
+object(foo)#3 (1) {
+  [u"bar"]=>
+  &unicode(5) "фубар"
+}
+---
+object(foo)#3 (1) {
+  [u"bar"]=>
+  &unicode(5) "фубар"
+}
+---
+фубар - 0
+
+Test 3: 
+object(foo)#3 (1) {
+  [u"bar"]=>
+  unicode(5) "фубар"
+}
+object(foo)#3 (1) {
+  [u"bar"]=>
+  &unicode(5) "фубар"
+}
+0 - фубар
+
+done!
index 078ec93024c27b95dc36ae210472174ee5b6cf69..f393e42a545c847c3e453b384b22aef18eebb59d 100644 (file)
@@ -828,14 +828,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
                                                *p = php_mysqlnd_net_store_length(*p, 0);
                                        }
                                        break;
-                               case MYSQL_TYPE_VAR_STRING:
-                                       /*
-                                         If the user uses refs, it could be that the type has
-                                         has changed and we need to convert, again. Which is noop,
-                                         if the type hasn't changed.
-                                       */
-                                       convert_to_string_ex(&stmt->param_bind[i].zv);
-                                       {
+                               case MYSQL_TYPE_VAR_STRING:{
                                                unsigned int len = Z_STRLEN_P(data);
                                                /* to is after p. The latter hasn't been moved */
                                                *p = php_mysqlnd_net_store_length(*p, len);