]> granicus.if.org Git - php/commitdiff
Fix problem with mysqli_commt()/mysqli_rollback()
authorAndrey Hristov <andrey@php.net>
Wed, 19 Mar 2014 16:32:19 +0000 (18:32 +0200)
committerAndrey Hristov <andrey@php.net>
Wed, 19 Mar 2014 16:32:19 +0000 (18:32 +0200)
NEWS
ext/mysqli/mysqli_api.c
ext/mysqli/tests/mysqli_commit_oo.phpt
ext/mysqlnd/mysqlnd.c

diff --git a/NEWS b/NEWS
index 13c615d9460024cfa67789cc19dad77b95e5f624..e8377e7a764678cdbc59f9d6bff8ba482483a5c2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2014, PHP 5.5.12
+- SPL:
+  . Fixed problem in mysqli_commit()/mysqli_rollback() with second parameter
+    (extra comma) and third parameters (lack of escaping). (Andrey)
 
 
 ?? ??? 2014, PHP 5.5.11
index 719dffff3df96dfb871906028fb02c6af465d2cb..d9e52b3d3ac2f519a1254e06dbae52d55903cfab 100644 (file)
@@ -643,24 +643,24 @@ static void mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str
 {
        if (mode & TRANS_COR_AND_CHAIN && !(mode & TRANS_COR_AND_NO_CHAIN)) {
                if (str->len) {
-                       smart_str_appendl(str, ", ", sizeof(", ") - 1);
+                       smart_str_appendl(str, " ", sizeof(" ") - 1);
                }
                smart_str_appendl(str, "AND CHAIN", sizeof("AND CHAIN") - 1);
        } else if (mode & TRANS_COR_AND_NO_CHAIN && !(mode & TRANS_COR_AND_CHAIN)) {
                if (str->len) {
-                       smart_str_appendl(str, ", ", sizeof(", ") - 1);
+                       smart_str_appendl(str, " ", sizeof(" ") - 1);
                }
                smart_str_appendl(str, "AND NO CHAIN", sizeof("AND NO CHAIN") - 1);
        }
 
        if (mode & TRANS_COR_RELEASE && !(mode & TRANS_COR_NO_RELEASE)) {
                if (str->len) {
-                       smart_str_appendl(str, ", ", sizeof(", ") - 1);
+                       smart_str_appendl(str, " ", sizeof(" ") - 1);
                }
                smart_str_appendl(str, "RELEASE", sizeof("RELEASE") - 1);
        } else if (mode & TRANS_COR_NO_RELEASE && !(mode & TRANS_COR_RELEASE)) {
                if (str->len) {
-                       smart_str_appendl(str, ", ", sizeof(", ") - 1);
+                       smart_str_appendl(str, " ", sizeof(" ") - 1);
                }
                smart_str_appendl(str, "NO RELEASE", sizeof("NO RELEASE") - 1);
        }
@@ -669,6 +669,7 @@ static void mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str
 /* }}} */
 
 
+
 /* {{{ proto bool mysqli_commit_or_rollback_libmysql */
 static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, const unsigned int mode, const char * const name)
 {
@@ -678,25 +679,60 @@ static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, co
        smart_str_0(&tmp_str);
 
        {
-               char * commented_name = NULL;
-               unsigned int commented_name_len = name? spprintf(&commented_name, 0, " /*%s*/", name):0;
                char * query;
-               unsigned int query_len = spprintf(&query, 0, (commit? "COMMIT%s %s":"ROLLBACK%s %s"),
-                                                                                 commented_name? commented_name:"", tmp_str.c? tmp_str.c:"");
+               char * name_esc = NULL;
+               size_t query_len;
+               
+               if (name) {     
+                       const char * p_orig = name;
+                       char * p_copy;
+                       p_copy = name_esc = emalloc(strlen(name) + 1 + 2 + 2 + 1); /* space, open, close, NullS */
+                       *p_copy++ = ' ';
+                       *p_copy++ = '/';
+                       *p_copy++ = '*';
+                       while (1) {
+                               register char v = *p_orig;
+                               if (v == 0) {
+                                       break;
+                               }
+                               if ((v >= '0' && v <= '9') ||
+                                       (v >= 'a' && v <= 'z') ||
+                                       (v >= 'A' && v <= 'Z') ||
+                                       v == '-' ||
+                                       v == '_' ||
+                                       v == ' ' ||
+                                       v == '=')
+                               {
+                                       *p_copy = v;
+                               } else {
+                                       *p_copy = '?';
+                               }
+                               ++p_orig;
+                               ++p_copy;
+                       }
+                       *p_copy++ = '*';
+                       *p_copy++ = '/';
+                       *p_copy++ = 0;
+               }
+
+               query_len = spprintf(&query, 0, (commit? "COMMIT%s %s":"ROLLBACK%s %s"),
+                                                                                 name_esc? name_esc:"", tmp_str.c? tmp_str.c:"");
                smart_str_free(&tmp_str);
+               if (name_esc) {
+                       efree(name_esc);
+                       name_esc = NULL;
+               }
 
                ret = mysql_real_query(conn, query, query_len);
                efree(query);
-               if (commented_name) {
-                       efree(commented_name);
-               }
        }
+       return ret;
 }
 /* }}} */
 #endif
 
 
-/* {{{ proto bool mysqli_commit(object link)
+/* {{{ proto bool mysqli_commit(object link[, int flags [, string name ]])
    Commit outstanding actions and close transaction */
 PHP_FUNCTION(mysqli_commit)
 {
index e19f698e8193d402b2ba3e6a6b50c06e9427888f..da9432facdcc9b43271ae6b4155d238a2de4e385 100644 (file)
@@ -21,49 +21,78 @@ if (!have_innodb($link))
        $link   = NULL;
 
        $mysqli = new mysqli();
-       if (!is_null($tmp = @$mysqli->commit()))
+       if (!is_null($tmp = @$mysqli->commit())) {
                printf("[013] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+       }
 
-       if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+       if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket)) {
                printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
                        $host, $user, $db, $port, $socket);
+       }
 
-       if (true !== ($tmp = $mysqli->commit()))
+       if (true !== ($tmp = $mysqli->commit())) {
                printf("[002] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+       }
 
-       if (true !== ($tmp = $mysqli->autocommit(false)))
+       if (true !== ($tmp = $mysqli->autocommit(false))) {
                printf("[003] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
+       }
 
-       if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+       if (!$mysqli->query('DROP TABLE IF EXISTS test')) {
                printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
 
-       if (!$mysqli->query('CREATE TABLE test(id INT) ENGINE = InnoDB'))
+       if (!$mysqli->query('CREATE TABLE test(id INT) ENGINE = InnoDB')) {
                printf("[005] Cannot create test table, [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
 
-       if (!$mysqli->query('INSERT INTO test(id) VALUES (1)'))
+       if (!$mysqli->query('INSERT INTO test(id) VALUES (1)')) {
                printf("[006] [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
 
        $tmp = $mysqli->commit();
-       if ($tmp !== true)
+       if ($tmp !== true) {
                printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+       }
 
        if (!$mysqli->query('ROLLBACK'))
                printf("[008] [%d] %s\n", $mysqli->errno, $mysqli->error);
 
-       if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test'))
+       if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test')) {
                printf("[009] [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
+
        $tmp = $res->fetch_assoc();
-       if (1 != $tmp['num'])
+       if (1 != $tmp['num']) {
                printf("[010] Expecting 1 row in table test, found %d rows\n", $tmp['num']);
+       }
        $res->free();
 
-       if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+       if (!$mysqli->query('DROP TABLE IF EXISTS test')) {
                printf("[011] [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
+
+       if (!$mysqli->commit(0 , "tx_name0123")) {
+               printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
+       if (!$mysqli->commit(0 , "*/ nonsense")) {
+               printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
+       if (!$mysqli->commit(0 , "tx_name")) {
+               printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
+       if (!$mysqli->commit(0 , "tx_name")) {
+               printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
+       if (!$mysqli->commit(MYSQLI_TRANS_COR_AND_CHAIN | MYSQLI_TRANS_COR_NO_RELEASE , "tx_name")) {
+               printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+       }
 
        $mysqli->close();
 
-       if (NULL !== ($tmp = @$mysqli->commit()))
-               printf("[012] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+       if (NULL !== ($tmp = @$mysqli->commit())) {
+               printf("[013] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+       }
 
        print "done!";
 ?>
index 39813145bad7bc2aa6550a6da2242de16401e0c5..bbfc4568966e8480c39180cbe8c5900fe6b1cade 100644 (file)
@@ -2652,24 +2652,24 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_cor_options_to_string)(const MYSQLND_CONN_D
 {
        if (mode & TRANS_COR_AND_CHAIN && !(mode & TRANS_COR_AND_NO_CHAIN)) {
                if (str->len) {
-                       smart_str_appendl(str, ", ", sizeof(", ") - 1);
+                       smart_str_appendl(str, " ", sizeof(" ") - 1);
                }
                smart_str_appendl(str, "AND CHAIN", sizeof("AND CHAIN") - 1);
        } else if (mode & TRANS_COR_AND_NO_CHAIN && !(mode & TRANS_COR_AND_CHAIN)) {
                if (str->len) {
-                       smart_str_appendl(str, ", ", sizeof(", ") - 1);
+                       smart_str_appendl(str, " ", sizeof(" ") - 1);
                }
                smart_str_appendl(str, "AND NO CHAIN", sizeof("AND NO CHAIN") - 1);
        }
 
        if (mode & TRANS_COR_RELEASE && !(mode & TRANS_COR_NO_RELEASE)) {
                if (str->len) {
-                       smart_str_appendl(str, ", ", sizeof(", ") - 1);
+                       smart_str_appendl(str, " ", sizeof(" ") - 1);
                }
                smart_str_appendl(str, "RELEASE", sizeof("RELEASE") - 1);
        } else if (mode & TRANS_COR_NO_RELEASE && !(mode & TRANS_COR_RELEASE)) {
                if (str->len) {
-                       smart_str_appendl(str, ", ", sizeof(", ") - 1);
+                       smart_str_appendl(str, " ", sizeof(" ") - 1);
                }
                smart_str_appendl(str, "NO RELEASE", sizeof("NO RELEASE") - 1);
        }
@@ -2692,23 +2692,58 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit_or_rollback)(MYSQLND_CONN_DATA * con
                        conn->m->tx_cor_options_to_string(conn, &tmp_str, flags TSRMLS_CC);
                        smart_str_0(&tmp_str);
 
+
                        {
-                               char * commented_name = NULL;
-                               unsigned int commented_name_len = name? mnd_sprintf(&commented_name, 0, " /*%s*/", name):0;
                                char * query;
-                               unsigned int query_len = mnd_sprintf(&query, 0, (commit? "COMMIT%s %s":"ROLLBACK%s %s"),
-                                                                                                        commented_name? commented_name:"", tmp_str.c? tmp_str.c:"");
-                               smart_str_free(&tmp_str);
+                               char * name_esc = NULL;
+                               size_t query_len;
+               
+                               if (name) {     
+                                       const char * p_orig = name;
+                                       char * p_copy;
+                                       p_copy = name_esc = mnd_emalloc(strlen(name) + 1 + 2 + 2 + 1); /* space, open, close, NullS */
+                                       *p_copy++ = ' ';
+                                       *p_copy++ = '/';
+                                       *p_copy++ = '*';
+                                       while (1) {
+                                               register char v = *p_orig;
+                                               if (v == 0) {
+                                                       break;
+                                               }
+                                               if ((v >= '0' && v <= '9') ||
+                                                       (v >= 'a' && v <= 'z') ||
+                                                       (v >= 'A' && v <= 'Z') ||
+                                                       v == '-' ||
+                                                       v == '_' ||
+                                                       v == ' ' ||
+                                                       v == '=')
+                                               {
+                                                       *p_copy = v;
+                                               } else {
+                                                       *p_copy = '?';
+                                               }
+                                               ++p_orig;
+                                               ++p_copy;
+                                       }
+                                       *p_copy++ = '*';
+                                       *p_copy++ = '/';
+                                       *p_copy++ = 0;
+                               }
 
+                               query_len = mnd_sprintf(&query, 0, (commit? "COMMIT%s %s":"ROLLBACK%s %s"),
+                                                                               name_esc? name_esc:"", tmp_str.c? tmp_str.c:"");
+                               smart_str_free(&tmp_str);
                                if (!query) {
                                        SET_OOM_ERROR(*conn->error_info);
                                        break;
                                }
+                               if (name_esc) {
+                                       mnd_efree(name_esc);
+                                       name_esc = NULL;
+                               }
+
                                ret = conn->m->query(conn, query, query_len TSRMLS_CC);
                                mnd_sprintf_free(query);
-                               if (commented_name) {
-                                       mnd_sprintf_free(commented_name);
-                               }
                        }
                } while (0);
                conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);