diff options
author | bar@mysql.com/bar.myoffice.izhnet.ru <> | 2008-02-29 17:56:50 +0400 |
---|---|---|
committer | bar@mysql.com/bar.myoffice.izhnet.ru <> | 2008-02-29 17:56:50 +0400 |
commit | f83cc8e6db90c96db1eb336f690b8a2af3d49e94 (patch) | |
tree | 383fd33306f77670825adcb8b08abae9dff732cc | |
parent | ef9579619d12a6d9034cfbdfdd90cbd6e5a314b9 (diff) | |
download | mariadb-git-f83cc8e6db90c96db1eb336f690b8a2af3d49e94.tar.gz |
Bug#23924 general_log truncates queries with character set introducers.
Problem: logging of utf8-incompatible binary strings didn't work
Fix: hex-encoding of incompatible sequences.
-rw-r--r-- | mysql-test/r/log_tables.result | 11 | ||||
-rw-r--r-- | mysql-test/t/log_tables.test | 10 | ||||
-rw-r--r-- | sql/field.cc | 11 | ||||
-rw-r--r-- | sql/field.h | 2 | ||||
-rw-r--r-- | sql/log.cc | 1 | ||||
-rw-r--r-- | sql/sql_string.cc | 62 | ||||
-rw-r--r-- | sql/sql_string.h | 3 |
7 files changed, 100 insertions, 0 deletions
diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index 0a7634df85a..2a4cee9fbbc 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -107,6 +107,17 @@ Database Table In_use Name_locked SET GLOBAL GENERAL_LOG=ON; SET GLOBAL SLOW_QUERY_LOG=ON; truncate table mysql.general_log; +set names binary; +select _koi8r'ΤΕΣΤ' as test; +test +ΤΕΣΤ +select * from mysql.general_log; +event_time user_host thread_id server_id command_type argument +TIMESTAMP USER_HOST THREAD_ID 1 Query set names binary +TIMESTAMP USER_HOST THREAD_ID 1 Query select _koi8r'\xD4\xC5\xD3\xD4' as test +TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log +set names utf8; +truncate table mysql.general_log; set names utf8; create table bug16905 (s char(15) character set utf8 default 'ΠΏΡΡΡΠΎ'); insert into bug16905 values ('Π½ΠΎΠ²ΠΎΠ΅'); diff --git a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test index 0c986c6d63a..3047d16d3b6 100644 --- a/mysql-test/t/log_tables.test +++ b/mysql-test/t/log_tables.test @@ -131,6 +131,16 @@ SET GLOBAL GENERAL_LOG=ON; SET GLOBAL SLOW_QUERY_LOG=ON; # +# Bug#23924 general_log truncates queries with character set introducers. +# +truncate table mysql.general_log; +set names binary; +select _koi8r'ΤΕΣΤ' as test; +--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID +select * from mysql.general_log; +set names utf8; + +# # Bug #16905 Log tables: unicode statements are logged incorrectly # diff --git a/sql/field.cc b/sql/field.cc index 88fac96df89..fb14b4d5c77 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7644,6 +7644,17 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) if (value.alloc(new_length)) goto oom_error; + + if (f_is_hex_escape(flags)) + { + copy_length= my_copy_with_hex_escaping(field_charset, + (char*) value.ptr(), new_length, + from, length); + Field_blob::store_length(copy_length); + tmp= value.ptr(); + bmove(ptr + packlength, (uchar*) &tmp, sizeof(char*)); + return 0; + } /* "length" is OK as "nchars" argument to well_formed_copy_nchars as this is never used to limit the length of the data. The cut of long data diff --git a/sql/field.h b/sql/field.h index 38a0b1d5bbd..2e8a27e579a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2069,6 +2069,7 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions); #define FIELDFLAG_NO_DEFAULT 16384 /* sql */ #define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag #define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql +#define FIELDFLAG_HEX_ESCAPE ((uint) 0x10000) #define FIELDFLAG_PACK_SHIFT 3 #define FIELDFLAG_DEC_SHIFT 8 #define FIELDFLAG_MAX_DEC 31 @@ -2094,3 +2095,4 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions); #define f_maybe_null(x) (x & FIELDFLAG_MAYBE_NULL) #define f_no_default(x) (x & FIELDFLAG_NO_DEFAULT) #define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR) +#define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE) diff --git a/sql/log.cc b/sql/log.cc index 9b5b2ae5a6c..328aaa45f3f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -418,6 +418,7 @@ bool Log_to_csv_event_handler:: A positive return value in store() means truncation. Still logging a message in the log in this case. */ + table->field[5]->flags|= FIELDFLAG_HEX_ESCAPE; if (table->field[5]->store(sql_text, sql_text_len, client_cs) < 0) goto err; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 7fa3786c382..34b310931d6 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -840,6 +840,68 @@ outp: } +/** + Copy string with HEX-encoding of "bad" characters. + + @details This functions copies the string pointed by "src" + to the string pointed by "dst". Not more than "srclen" bytes + are read from "src". Any sequences of bytes representing + a not-well-formed substring (according to cs) are hex-encoded, + and all well-formed substrings (according to cs) are copied as is. + Not more than "dstlen" bytes are written to "dst". The number + of bytes written to "dst" is returned. + + @param cs character set pointer of the destination string + @param[out] dst destination string + @param dstlen size of dst + @param src source string + @param srclen length of src + + @retval result length +*/ + +size_t +my_copy_with_hex_escaping(CHARSET_INFO *cs, + char *dst, size_t dstlen, + const char *src, size_t srclen) +{ + const char *srcend= src + srclen; + char *dst0= dst; + + for ( ; src < srcend ; ) + { + size_t chlen; + if ((chlen= my_ismbchar(cs, src, srcend))) + { + if (dstlen < chlen) + break; /* purecov: inspected */ + memcpy(dst, src, chlen); + src+= chlen; + dst+= chlen; + dstlen-= chlen; + } + else if (*src & 0x80) + { + if (dstlen < 4) + break; /* purecov: inspected */ + *dst++= '\\'; + *dst++= 'x'; + *dst++= _dig_vec_upper[((unsigned char) *src) >> 4]; + *dst++= _dig_vec_upper[((unsigned char) *src) & 15]; + src++; + dstlen-= 4; + } + else + { + if (dstlen < 1) + break; /* purecov: inspected */ + *dst++= *src++; + dstlen--; + } + } + return dst - dst0; +} + /* copy a string, with optional character set conversion, diff --git a/sql/sql_string.h b/sql/sql_string.h index 128ed749b5f..b4d76a1779a 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -37,6 +37,9 @@ uint32 well_formed_copy_nchars(CHARSET_INFO *to_cs, const char **well_formed_error_pos, const char **cannot_convert_error_pos, const char **from_end_pos); +size_t my_copy_with_hex_escaping(CHARSET_INFO *cs, + char *dst, size_t dstlen, + const char *src, size_t srclen); class String { |