From a29b1d7151497b4777e4b4917f0eee001705a928 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Aug 2005 04:26:32 -0400 Subject: BUG#11338 (logging of prepared statement w/ blob type) In cp932, '\' character can be the second byte in a multi-byte character stream. This makes it difficult to use mysql_escape_string. Added flag to indicate which languages allow '\' as second byte of multibyte sequence so that when putting a prepared statement into the binlog we can decide at runtime whether hex encoding is really needed. include/m_ctype.h: Added bool to indicate character sets which allow '\' as the second byte of a multibyte character set (currently only cp932). For these character sets, escaping with '\' is dangerous and leads to corruption in replication. include/my_sys.h: Add function to enocde a string as hex with no prefix (bare) mysys/charset.c: Add function to encode string as hex with no prefix (bare). sql/item.cc: Check the connection character set to see if escape_string_for_mysql is safe, or if character set requires unambiguous (hex) encoding sql/item.h: Pass thd to query_val_str for access to charset() sql/sql_prepare.cc: Pass thd to query_val_str. strings/ctype-big5.c: Add escape_with_backslash_is_dangerous flag. strings/ctype-bin.c: Add escape_with_backslash_is_dangerous flag strings/ctype-cp932.c: Add escape_with_backslash_is_dangerous flag. strings/ctype-czech.c: Add escape_with_backslash_is_dangerous flag. strings/ctype-euc_kr.c: Add escape_with_backslash_is_dangerous flag. strings/ctype-extra.c: Add escape_with_backslash_is_dangerous flag. strings/ctype-gb2312.c: Add escape_with_backslash_is_dangerous flag. strings/ctype-gbk.c: Added escape_with_backslash_is_dangerous flag. strings/ctype-latin1.c: Added escape_with_backslash_is_dangerous flag. strings/ctype-sjis.c: Added escape_with_backslash_is_dangerous flag. strings/ctype-tis620.c: Added esacpe_with_backslash_character_is_dangerous flag. strings/ctype-uca.c: Added escape_with_backslash_is_dangerous flag. strings/ctype-ucs2.c: Added escape_with_backslash_is_dangerous. strings/ctype-ujis.c: Added escape_with_backslash_is_dangerous flag. strings/ctype-utf8.c: Added escape_with_backslash_is_dangerous. strings/ctype-win1250ch.c: Added escape_with_backslash_is_dangerous. --- sql/item.cc | 18 +++++++++++++----- sql/item.h | 2 +- sql/sql_prepare.cc | 4 ++-- 3 files changed, 16 insertions(+), 8 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index b3d2932acf6..79579eeeb67 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1443,7 +1443,7 @@ String *Item_param::val_str(String* str) and avoid one more memcpy/alloc between str and log string. */ -const String *Item_param::query_val_str(String* str) const +const String *Item_param::query_val_str(String* str, THD *thd) const { switch (state) { case INT_VALUE: @@ -1482,10 +1482,18 @@ const String *Item_param::query_val_str(String* str) const buf= str->c_ptr_quick(); ptr= buf; - *ptr++= '\''; - ptr+= escape_string_for_mysql(str_value.charset(), ptr, - str_value.ptr(), str_value.length()); - *ptr++= '\''; + if (thd->charset()->escape_with_backslash_is_dangerous) + { + ptr= strmov(ptr, "x\'"); + ptr= bare_str_to_hex(ptr, str_value.ptr(), str_value.length()); + } + else + { + *ptr++= '\''; + ptr+= escape_string_for_mysql(str_value.charset(), ptr, + str_value.ptr(), str_value.length()); + } + *ptr++='\''; str->length(ptr - buf); break; } diff --git a/sql/item.h b/sql/item.h index 825b37fe64c..ee86fb80167 100644 --- a/sql/item.h +++ b/sql/item.h @@ -591,7 +591,7 @@ public: */ void (*set_param_func)(Item_param *param, uchar **pos, ulong len); - const String *query_val_str(String *str) const; + const String *query_val_str(String *str, THD *thd) const; bool convert_str_value(THD *thd); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 6507de37a71..d0c06a3eaf7 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -601,7 +601,7 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array, param->set_param_func(param, &read_pos, data_end - read_pos); } } - res= param->query_val_str(&str); + res= param->query_val_str(&str, thd); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -749,7 +749,7 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query) client_param->buffer_length); } } - res= param->query_val_str(&str); + res= param->query_val_str(&str, thd); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ -- cgit v1.2.1 From cd737f81c92d9921facad75e56c298a31cf1c871 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Aug 2005 21:22:35 +0300 Subject: Changes for Netware. This is needed when building against newer Libc than we've used before. --- sql/mysqld.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b5a292fec28..55995a71980 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -152,6 +152,7 @@ int deny_severity = LOG_WARNING; #define zVOLSTATE_MAINTENANCE 3 #ifdef __NETWARE__ +#include #include #include #include -- cgit v1.2.1 From 1b970e94e0a736a2056cb94cfcba0b50133da1d6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 14:49:34 -0400 Subject: Bug#11338 Fixes from review (identical functionality). include/my_sys.h: Fixes from review (use version in log_event.cc instead) mysql-test/r/ctype_cp932.result: Updated test for bug#11338 (logging of prepared statement w/ blob type) mysql-test/t/ctype_cp932.test: udpated test for bug#11338 (logging of prepared statement w/ blob type) mysys/charset.c: Fixes from review (use version in log_event.cc instead) sql/item.cc: Fixes from review (store character_set_client differently so that fix can be merged forward to 5.0) sql/item.h: Fixes from review sql/log_event.cc: Fixes from review, str_to_hex is now used by item.cc sql/log_event.h: Added prototype for str_to_hex (now used by item.cc) sql/sql_prepare.cc: Fixes from review, store character_set_client differently so that Item_param::query_val_str can use it. --- sql/item.cc | 15 +++++++-------- sql/item.h | 3 ++- sql/log_event.cc | 2 +- sql/log_event.h | 2 +- sql/sql_prepare.cc | 9 ++++++--- 5 files changed, 17 insertions(+), 14 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 79579eeeb67..2ae56d17b07 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1230,7 +1230,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) CHARSET_INFO *tocs= thd->variables.collation_connection; uint32 dummy_offset; - value.cs_info.character_set_client= fromcs; + value.cs_info.character_set_of_placeholder= fromcs; /* Setup source and destination character sets so that they are different only if conversion is necessary: this will @@ -1443,7 +1443,7 @@ String *Item_param::val_str(String* str) and avoid one more memcpy/alloc between str and log string. */ -const String *Item_param::query_val_str(String* str, THD *thd) const +const String *Item_param::query_val_str(String* str) const { switch (state) { case INT_VALUE: @@ -1482,18 +1482,17 @@ const String *Item_param::query_val_str(String* str, THD *thd) const buf= str->c_ptr_quick(); ptr= buf; - if (thd->charset()->escape_with_backslash_is_dangerous) + if (value.cs_info.character_set_client->escape_with_backslash_is_dangerous) { - ptr= strmov(ptr, "x\'"); - ptr= bare_str_to_hex(ptr, str_value.ptr(), str_value.length()); + ptr= str_to_hex(ptr, str_value.ptr(), str_value.length()); } else { *ptr++= '\''; ptr+= escape_string_for_mysql(str_value.charset(), ptr, str_value.ptr(), str_value.length()); + *ptr++='\''; } - *ptr++='\''; str->length(ptr - buf); break; } @@ -1523,10 +1522,10 @@ bool Item_param::convert_str_value(THD *thd) here only if conversion is really necessary. */ if (value.cs_info.final_character_set_of_str_value != - value.cs_info.character_set_client) + value.cs_info.character_set_of_placeholder) { rc= thd->convert_string(&str_value, - value.cs_info.character_set_client, + value.cs_info.character_set_of_placeholder, value.cs_info.final_character_set_of_str_value); } else diff --git a/sql/item.h b/sql/item.h index ff34dfad025..080b804c730 100644 --- a/sql/item.h +++ b/sql/item.h @@ -532,6 +532,7 @@ public: struct CONVERSION_INFO { CHARSET_INFO *character_set_client; + CHARSET_INFO *character_set_of_placeholder; /* This points at character set of connection if conversion to it is required (i. e. if placeholder typecode is not BLOB). @@ -591,7 +592,7 @@ public: */ void (*set_param_func)(Item_param *param, uchar **pos, ulong len); - const String *query_val_str(String *str, THD *thd) const; + const String *query_val_str(String *str) const; bool convert_str_value(THD *thd); diff --git a/sql/log_event.cc b/sql/log_event.cc index 4d260763491..66c732e8cb0 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -207,7 +207,7 @@ static inline int read_str(char * &buf, char *buf_end, char * &str, /* Transforms a string into "" or its expression in 0x... form. */ -static char *str_to_hex(char *to, char *from, uint len) +char *str_to_hex(char *to, const char *from, uint len) { char *p= to; if (len) diff --git a/sql/log_event.h b/sql/log_event.h index 7ae4e863fc2..5c81d0c92f0 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1069,5 +1069,5 @@ public: bool is_valid() { return 1; } }; #endif - +char *str_to_hex(char *to, const char *from, uint len); #endif /* _log_event_h */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d0c06a3eaf7..8a50d0bd50e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -528,7 +528,9 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: param->set_param_func= set_param_str; - param->value.cs_info.character_set_client= &my_charset_bin; + param->value.cs_info.character_set_of_placeholder= &my_charset_bin; + param->value.cs_info.character_set_client= + thd->variables.character_set_client; param->value.cs_info.final_character_set_of_str_value= &my_charset_bin; param->item_type= Item::STRING_ITEM; param->item_result_type= STRING_RESULT; @@ -544,6 +546,7 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, CHARSET_INFO *tocs= thd->variables.collation_connection; uint32 dummy_offset; + param->value.cs_info.character_set_of_placeholder= fromcs; param->value.cs_info.character_set_client= fromcs; /* @@ -601,7 +604,7 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array, param->set_param_func(param, &read_pos, data_end - read_pos); } } - res= param->query_val_str(&str, thd); + res= param->query_val_str(&str); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -749,7 +752,7 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query) client_param->buffer_length); } } - res= param->query_val_str(&str, thd); + res= param->query_val_str(&str); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ -- cgit v1.2.1