]> granicus.if.org Git - php/commitdiff
Emit a warning in case of unallowed characters. Fix another place this
authorAndrey Hristov <andrey@php.net>
Thu, 20 Mar 2014 14:23:40 +0000 (16:23 +0200)
committerAndrey Hristov <andrey@php.net>
Thu, 20 Mar 2014 14:23:40 +0000 (16:23 +0200)
code is used - reuse

ext/mysqli/mysqli_api.c
ext/mysqli/mysqli_nonapi.c
ext/mysqli/tests/mysqli_begin_transaction.phpt
ext/mysqli/tests/mysqli_commit_oo.phpt
ext/mysqlnd/mysqlnd.c

index 3911202066aebdcec3d173a8a2958f7a9fd7f339..e3042b18f859615ff8ec31ad0e7d34d4bcfc1984 100644 (file)
@@ -67,9 +67,50 @@ static void mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str
 /* }}} */
 
 
+/* {{{ mysqlnd_escape_string_for_tx_name_in_comment */
+char *
+mysqli_escape_string_for_tx_name_in_comment(const char * const name TSRMLS_DC)
+{
+       char * ret = NULL;
+       if (name) {
+               zend_bool warned = FALSE;
+               const char * p_orig = name;
+               char * p_copy;
+               p_copy = ret = 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 if (warned == FALSE) {
+                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Transaction name truncated. Must be only [0-9A-Za-z\\-_=]+");
+                               warned = TRUE;
+                       }
+                       ++p_orig;
+               }
+               *p_copy++ = '*';
+               *p_copy++ = '/';
+               *p_copy++ = 0;
+       }
+       return ret;
+}
+/* }}} */
+
 
 /* {{{ 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)
+static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, const unsigned int mode, const char * const name TSRMLS_DC)
 {
        int ret;
        smart_str tmp_str = {0, 0, 0};
@@ -78,37 +119,8 @@ static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, co
 
        {
                char * query;
-               char * name_esc = NULL;
+               char * name_esc = mysqli_escape_string_for_tx_name_in_comment(name TSRMLS_CC);
                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;
-                               }
-                               ++p_orig;
-                       }
-                       *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:"");
@@ -748,7 +760,7 @@ PHP_FUNCTION(mysqli_commit)
        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
 
 #if !defined(MYSQLI_USE_MYSQLND)
-       if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name)) {
+       if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name TSRMLS_CC)) {
 #else
        if (FAIL == mysqlnd_commit(mysql->mysql, flags, name)) {
 #endif
@@ -1998,7 +2010,7 @@ PHP_FUNCTION(mysqli_rollback)
        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
 
 #if !defined(MYSQLI_USE_MYSQLND)
-       if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name)) {
+       if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name TSRMLS_CC)) {
 #else
        if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
 #endif
index db0352baeb0323243cccb2d4d0b7049bf63a9dee..17570c7a1afbf28faffa894444667aea51ea0fa2 100644 (file)
@@ -1046,12 +1046,14 @@ PHP_FUNCTION(mysqli_get_charset)
 /* }}} */
 #endif
 
-
 #if !defined(MYSQLI_USE_MYSQLND)
+extern char * mysqli_escape_string_for_tx_name_in_comment(const char * const name TSRMLS_DC);
+
 /* {{{ proto bool mysqli_begin_transaction_libmysql */
-static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mode, const char * const name)
+static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mode, const char * const name TSRMLS_DC)
 {
        int ret;
+       zend_bool err = FALSE;
        smart_str tmp_str = {0, 0, 0};
        if (mode & TRANS_START_WITH_CONSISTENT_SNAPSHOT) {
                if (tmp_str.len) {
@@ -1059,33 +1061,37 @@ static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mo
                }
                smart_str_appendl(&tmp_str, "WITH CONSISTENT SNAPSHOT", sizeof("WITH CONSISTENT SNAPSHOT") - 1);
        }
-       if (mode & TRANS_START_READ_WRITE) {
-               if (tmp_str.len) {
-                       smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
-               }
-               smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1);
-       }
-       if (mode & TRANS_START_READ_ONLY) {
-               if (tmp_str.len) {
-                       smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
+       if (mode & (TRANS_START_READ_WRITE | TRANS_START_READ_ONLY)) {
+               if (mysql_get_server_version(conn) < 50605L) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "This server version doesn't support 'READ WRITE' and 'READ ONLY'. Minimum 5.6.5 is required");
+                       err = TRUE;
+               } else if (mode & TRANS_START_READ_WRITE) {
+                       if (tmp_str.len) {
+                               smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
+                       }
+                       smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1);
+               } else if (mode & TRANS_START_READ_ONLY) {
+                       if (tmp_str.len) {
+                               smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
+                       }
+                       smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1);
                }
-               smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1);
        }
        smart_str_0(&tmp_str);
 
-       {
-               char * commented_name = NULL;
-               unsigned int commented_name_len = name? spprintf(&commented_name, 0, " /*%s*/", name):0;
+       if (err == FALSE){
+               char * name_esc = mysqli_escape_string_for_tx_name_in_comment(name TSRMLS_CC);
                char * query;
                unsigned int query_len = spprintf(&query, 0, "START TRANSACTION%s %s",
-                                                                                 commented_name? commented_name:"", tmp_str.c? tmp_str.c:"");
+                                                                                 name_esc? name_esc:"", tmp_str.c? tmp_str.c:"");
+
                smart_str_free(&tmp_str);
+               if (name_esc) {
+                       efree(name_esc);
+               }
 
                ret = mysql_real_query(conn, query, query_len);
                efree(query);
-               if (commented_name) {
-                       efree(commented_name);
-               }
        }
        return ret;
 }
@@ -1120,7 +1126,7 @@ PHP_FUNCTION(mysqli_begin_transaction)
        }
        
 #if !defined(MYSQLI_USE_MYSQLND)
-       if (mysqli_begin_transaction_libmysql(mysql->mysql, flags, name)) {
+       if (mysqli_begin_transaction_libmysql(mysql->mysql, flags, name TSRMLS_CC)) {
                RETURN_FALSE;
        }
 #else
index 24e8d3c54b30f12497d62675d50e404bdb4ddcee..99f87c18521bb89e084cbe361e48850142866f85 100644 (file)
@@ -134,7 +134,8 @@ NULL
 [017] [1792] %s
 [018] invalid_flag = %d [%d]%A
 
-Warning: mysqli_begin_transaction(): Invalid value for parameter flags (-1) in %s on line %d
+Warning: mysqli_begin_transaction(): Invalid value for parameter flags (-1) in /work/dev/php/php-5.5/ext/mysqli/tests/mysqli_begin_transaction.php on line 98
 [019] [%d]%A
-[020] [%d]%A
+
+Warning: mysqli::begin_transaction(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in /work/dev/php/php-5.5/ext/mysqli/tests/mysqli_begin_transaction.php on line 103
 done!
\ No newline at end of file
index da9432facdcc9b43271ae6b4155d238a2de4e385..77bcf412e7a5fa1e655632d7541852a1f0d83007 100644 (file)
@@ -76,22 +76,22 @@ if (!have_innodb($link))
                printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
        }
        if (!$mysqli->commit(0 , "*/ nonsense")) {
-               printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+               printf("[013] [%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 ulf вендел")) {
+               printf("[014] [%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 \t\n\r\b")) {
+               printf("[015] [%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);
+               printf("[016] [%d] %s\n", $mysqli->errno, $mysqli->error);
        }
 
        $mysqli->close();
 
        if (NULL !== ($tmp = @$mysqli->commit())) {
-               printf("[013] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+               printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
        }
 
        print "done!";
@@ -101,4 +101,9 @@ if (!have_innodb($link))
        require_once("clean_table.inc");
 ?>
 --EXPECTF--
+Warning: mysqli::commit(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in %s on line %d
+
+Warning: mysqli::commit(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in %s on line %d
+
+Warning: mysqli::commit(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in %s on line %d
 done!
\ No newline at end of file
index c138c50ed9c50977507b87f8039b57d1d3511f76..1222a7f3025c0121ad238f36ac1c662e68ec7db0 100644 (file)
@@ -2678,6 +2678,49 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_cor_options_to_string)(const MYSQLND_CONN_D
 /* }}} */
 
 
+/* {{{ mysqlnd_escape_string_for_tx_name_in_comment */
+static char *
+mysqlnd_escape_string_for_tx_name_in_comment(const char * const name TSRMLS_DC)
+{
+       char * ret = NULL;
+       DBG_ENTER("mysqlnd_escape_string_for_tx_name_in_comment");
+       if (name) {
+               zend_bool warned = FALSE;
+               const char * p_orig = name;
+               char * p_copy;
+               p_copy = ret = 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 if (warned == FALSE) {
+                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Transaction name truncated. Must be only [0-9A-Za-z\\-_=]+");
+                               warned = TRUE;
+                       }
+                       ++p_orig;
+               }
+               *p_copy++ = '*';
+               *p_copy++ = '/';
+               *p_copy++ = 0;
+       }
+       DBG_RETURN(ret);
+}
+/* }}} */
+
+
 /* {{{ mysqlnd_conn_data::tx_commit_ex */
 static enum_func_status
 MYSQLND_METHOD(mysqlnd_conn_data, tx_commit_or_rollback)(MYSQLND_CONN_DATA * conn, const zend_bool commit, const unsigned int flags, const char * const name TSRMLS_DC)
@@ -2695,49 +2738,20 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit_or_rollback)(MYSQLND_CONN_DATA * con
 
                        {
                                char * query;
-                               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;
-                                               }
-                                               ++p_orig;
-                                       }
-                                       *p_copy++ = '*';
-                                       *p_copy++ = '/';
-                                       *p_copy++ = 0;
-                               }
-
+                               char * name_esc = mysqlnd_escape_string_for_tx_name_in_comment(name TSRMLS_CC);
+                               
                                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;
                                }
+                               if (!query) {
+                                       SET_OOM_ERROR(*conn->error_info);
+                                       break;
+                               }
 
                                ret = conn->m->query(conn, query, query_len TSRMLS_CC);
                                mnd_sprintf_free(query);
@@ -2768,36 +2782,41 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_begin)(MYSQLND_CONN_DATA * conn, const unsi
                                }
                                smart_str_appendl(&tmp_str, "WITH CONSISTENT SNAPSHOT", sizeof("WITH CONSISTENT SNAPSHOT") - 1);
                        }
-                       if (mode & TRANS_START_READ_WRITE) {
-                               if (tmp_str.len) {
-                                       smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
-                               }
-                               smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1);
-                       }
-                       if (mode & TRANS_START_READ_ONLY) {
-                               if (tmp_str.len) {
-                                       smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
+                       if (mode & (TRANS_START_READ_WRITE | TRANS_START_READ_ONLY)) {
+                               unsigned long server_version = conn->m->get_server_version(conn TSRMLS_CC);
+                               if (server_version < 50605L) {
+                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "This server version doesn't support 'READ WRITE' and 'READ ONLY'. Minimum 5.6.5 is required");
+                                       smart_str_free(&tmp_str);
+                                       break;
+                               } else if (mode & TRANS_START_READ_WRITE) {
+                                       if (tmp_str.len) {
+                                               smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
+                                       }
+                                       smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1);
+                               } else if (mode & TRANS_START_READ_ONLY) {
+                                       if (tmp_str.len) {
+                                               smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
+                                       }
+                                       smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1);
                                }
-                               smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1);
                        }
                        smart_str_0(&tmp_str);
 
                        {
-                               char * commented_name = NULL;
-                               unsigned int commented_name_len = name? mnd_sprintf(&commented_name, 0, " /*%s*/", name):0;
+                               char * name_esc = mysqlnd_escape_string_for_tx_name_in_comment(name TSRMLS_CC);
                                char * query;
-                               unsigned int query_len = mnd_sprintf(&query, 0, "START TRANSACTION%s %s", commented_name? commented_name:"", tmp_str.c? tmp_str.c:"");
+                               unsigned int query_len = mnd_sprintf(&query, 0, "START TRANSACTION%s %s", name_esc? name_esc:"", tmp_str.c? tmp_str.c:"");
                                smart_str_free(&tmp_str);
-
+                               if (name_esc) {
+                                       mnd_efree(name_esc);
+                                       name_esc = NULL;
+                               }
                                if (!query) {
                                        SET_OOM_ERROR(*conn->error_info);
                                        break;
                                }
                                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);