diff options
author | unknown <jimw@mysql.com> | 2005-07-05 09:47:20 -0700 |
---|---|---|
committer | unknown <jimw@mysql.com> | 2005-07-05 09:47:20 -0700 |
commit | 63c5a72b314bcf4ad68e120fa2e16caa861bb822 (patch) | |
tree | b9559572d9068a65f3ebaa464b35ff27d369fa20 | |
parent | 7450eef89a7aac5be282d7be7b22b0c636b5ea74 (diff) | |
parent | 390bc0d6195a2042d0534fcfbdeee336f8b394fe (diff) | |
download | mariadb-git-63c5a72b314bcf4ad68e120fa2e16caa861bb822.tar.gz |
Merge mysql.com:/home/jimw/my/mysql-5.0-10214
into mysql.com:/home/jimw/my/mysql-5.0-clean
include/my_sys.h:
Auto merged
include/mysql_com.h:
Auto merged
libmysql/libmysql.c:
Auto merged
sql/set_var.cc:
Auto merged
sql/sql_class.cc:
Auto merged
tests/mysql_client_test.c:
Clean up merge of new tests
-rw-r--r-- | include/my_sys.h | 3 | ||||
-rw-r--r-- | include/mysql_com.h | 1 | ||||
-rw-r--r-- | libmysql/libmysql.c | 9 | ||||
-rw-r--r-- | mysys/charset.c | 116 | ||||
-rw-r--r-- | sql/set_var.cc | 9 | ||||
-rw-r--r-- | sql/sql_class.cc | 2 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 30 |
7 files changed, 160 insertions, 10 deletions
diff --git a/include/my_sys.h b/include/my_sys.h index a3d6f6827d3..e31659c0652 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -866,6 +866,9 @@ extern void add_compiled_collation(CHARSET_INFO *cs); extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, ulong to_length, const char *from, ulong length); +extern ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, + char *to, ulong to_length, + const char *from, ulong length); extern void thd_increment_bytes_sent(ulong length); extern void thd_increment_bytes_received(ulong length); diff --git a/include/mysql_com.h b/include/mysql_com.h index 88a614bc4a3..969fba4a433 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -148,6 +148,7 @@ enum enum_server_command */ #define SERVER_STATUS_LAST_ROW_SENT 128 #define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */ +#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512 #define MYSQL_ERRMSG_SIZE 512 #define NET_READ_TIMEOUT 30 /* Timeout on read */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index e33fd470582..2a4bc5151c1 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1616,7 +1616,14 @@ ulong STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, ulong length) { - return escape_string_for_mysql(mysql->charset, to, 0, from, length); + if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) + { + return escape_quotes_for_mysql(mysql->charset, to, 0, from, length); + } + else + { + return escape_string_for_mysql(mysql->charset, to, 0, from, length); + } } diff --git a/mysys/charset.c b/mysys/charset.c index cbd9ba16b4c..4920e7806a2 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -561,11 +561,30 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, DBUG_RETURN(cs); } + /* + Escape string with backslashes (\) + + SYNOPSIS + escape_string_for_mysql() + charset_info Charset of the strings + to Buffer for escaped string + to_length Length of destination buffer, or 0 + from The string to escape + length The length of the string to escape + + DESCRIPTION + This escapes the contents of a string by adding backslashes before special + characters, and turning others into specific escape sequences, such as + turning newlines into \n and null bytes into \0. + NOTE - to keep old C API, to_length may be 0 to mean "big enough" - RETURN - the length of the escaped string or ~0 if it did not fit. + To maintain compatibility with the old C API, to_length may be 0 to mean + "big enough" + + RETURN VALUES + ~0 The escaped string did not fit in the to buffer + >=0 The length of the escaped string */ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, ulong to_length, @@ -573,20 +592,20 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, { const char *to_start= to; const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); - my_bool overflow=0; + my_bool overflow= FALSE; #ifdef USE_MB my_bool use_mb_flag= use_mb(charset_info); #endif for (end= from + length; from < end; from++) { - char escape=0; + char escape= 0; #ifdef USE_MB int tmp_length; if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) { if (to + tmp_length > to_end) { - overflow=1; + overflow= TRUE; break; } while (tmp_length--) @@ -636,7 +655,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, { if (to + 2 > to_end) { - overflow=1; + overflow= TRUE; break; } *to++= '\\'; @@ -646,7 +665,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, { if (to + 1 > to_end) { - overflow=1; + overflow= TRUE; break; } *to++= *from; @@ -656,3 +675,84 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, return overflow ? (ulong)~0 : (ulong) (to - to_start); } + +/* + Escape apostrophes by doubling them up + + SYNOPSIS + escape_quotes_for_mysql() + charset_info Charset of the strings + to Buffer for escaped string + to_length Length of destination buffer, or 0 + from The string to escape + length The length of the string to escape + + DESCRIPTION + This escapes the contents of a string by doubling up any apostrophes that + it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in + effect on the server. + + NOTE + To be consistent with escape_string_for_mysql(), to_length may be 0 to + mean "big enough" + + RETURN VALUES + ~0 The escaped string did not fit in the to buffer + >=0 The length of the escaped string +*/ +ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, + char *to, ulong to_length, + const char *from, ulong length) +{ + const char *to_start= to; + const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); + my_bool overflow= FALSE; +#ifdef USE_MB + my_bool use_mb_flag= use_mb(charset_info); +#endif + for (end= from + length; from < end; from++) + { + char escape= 0; +#ifdef USE_MB + int tmp_length; + if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) + { + if (to + tmp_length > to_end) + { + overflow= TRUE; + break; + } + while (tmp_length--) + *to++= *from++; + from--; + continue; + } + /* + We don't have the same issue here with a non-multi-byte character being + turned into a multi-byte character by the addition of an escaping + character, because we are only escaping the ' character with itself. + */ +#endif + if (*from == '\'') + { + if (to + 2 > to_end) + { + overflow= TRUE; + break; + } + *to++= '\''; + *to++= '\''; + } + else + { + if (to + 1 > to_end) + { + overflow= TRUE; + break; + } + *to++= *from; + } + } + *to= 0; + return overflow ? (ulong)~0 : (ulong) (to - to_start); +} diff --git a/sql/set_var.cc b/sql/set_var.cc index 3f991713eb7..ae7e4bd844b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3238,7 +3238,16 @@ void fix_sql_mode_var(THD *thd, enum_var_type type) global_system_variables.sql_mode= fix_sql_mode(global_system_variables.sql_mode); else + { thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode); + /* + Update thd->server_status + */ + if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) + thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; + else + thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES; + } } /* Map database specific bits to function bits */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a941ba11943..bf6f41d00ed 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -282,6 +282,8 @@ void THD::init(void) #endif pthread_mutex_unlock(&LOCK_global_system_variables); server_status= SERVER_STATUS_AUTOCOMMIT; + if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) + server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; options= thd_startup_options; open_options=ha_open_options; update_lock_default= (variables.low_priority_updates ? diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index a80d5e1d1be..0c79925c3eb 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13332,7 +13332,6 @@ static void test_bug9992() mysql_close(mysql1); } - /* Bug#10736: cursors and subqueries, memroot management */ static void test_bug10736() @@ -13601,6 +13600,34 @@ static void test_bug11656() /* + Check that the server signals when NO_BACKSLASH_ESCAPES mode is in effect, + and mysql_real_escape_string() does the right thing as a result. +*/ + +static void test_bug10214() +{ + MYSQL_RES* res ; + int len; + char out[8]; + + myheader("test_bug10214"); + + DIE_UNLESS(!(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)); + + len= mysql_real_escape_string(mysql, out, "a'b\\c", 5); + DIE_UNLESS(memcmp(out, "a\\'b\\\\c", len) == 0); + + mysql_query(mysql, "set sql_mode='NO_BACKSLASH_ESCAPES'"); + DIE_UNLESS(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES); + + len= mysql_real_escape_string(mysql, out, "a'b\\c", 5); + DIE_UNLESS(memcmp(out, "a''b\\c", len) == 0); + + mysql_query(mysql, "set sql_mode=''"); +} + + +/* Read and parse arguments and MySQL options from my.cnf */ @@ -13839,6 +13866,7 @@ static struct my_tests_st my_tests[]= { { "test_bug10794", test_bug10794 }, { "test_bug11172", test_bug11172 }, { "test_bug11656", test_bug11656 }, + { "test_bug10214", test_bug10214 }, { 0, 0 } }; |