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.
parent ef957961
...@@ -107,6 +107,17 @@ Database Table In_use Name_locked ...@@ -107,6 +107,17 @@ Database Table In_use Name_locked
SET GLOBAL GENERAL_LOG=ON; SET GLOBAL GENERAL_LOG=ON;
SET GLOBAL SLOW_QUERY_LOG=ON; SET GLOBAL SLOW_QUERY_LOG=ON;
truncate table mysql.general_log; 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; set names utf8;
create table bug16905 (s char(15) character set utf8 default 'пусто'); create table bug16905 (s char(15) character set utf8 default 'пусто');
insert into bug16905 values ('новое'); insert into bug16905 values ('новое');
......
...@@ -130,6 +130,16 @@ show open tables; ...@@ -130,6 +130,16 @@ show open tables;
SET GLOBAL GENERAL_LOG=ON; SET GLOBAL GENERAL_LOG=ON;
SET GLOBAL SLOW_QUERY_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 # Bug #16905 Log tables: unicode statements are logged incorrectly
# #
......
...@@ -7644,6 +7644,17 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) ...@@ -7644,6 +7644,17 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
if (value.alloc(new_length)) if (value.alloc(new_length))
goto oom_error; 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 "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 is never used to limit the length of the data. The cut of long data
......
...@@ -2069,6 +2069,7 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions); ...@@ -2069,6 +2069,7 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions);
#define FIELDFLAG_NO_DEFAULT 16384 /* sql */ #define FIELDFLAG_NO_DEFAULT 16384 /* sql */
#define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag #define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag
#define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql #define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql
#define FIELDFLAG_HEX_ESCAPE ((uint) 0x10000)
#define FIELDFLAG_PACK_SHIFT 3 #define FIELDFLAG_PACK_SHIFT 3
#define FIELDFLAG_DEC_SHIFT 8 #define FIELDFLAG_DEC_SHIFT 8
#define FIELDFLAG_MAX_DEC 31 #define FIELDFLAG_MAX_DEC 31
...@@ -2094,3 +2095,4 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions); ...@@ -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_maybe_null(x) (x & FIELDFLAG_MAYBE_NULL)
#define f_no_default(x) (x & FIELDFLAG_NO_DEFAULT) #define f_no_default(x) (x & FIELDFLAG_NO_DEFAULT)
#define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR) #define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
#define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE)
...@@ -418,6 +418,7 @@ bool Log_to_csv_event_handler:: ...@@ -418,6 +418,7 @@ bool Log_to_csv_event_handler::
A positive return value in store() means truncation. A positive return value in store() means truncation.
Still logging a message in the log in this case. 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) if (table->field[5]->store(sql_text, sql_text_len, client_cs) < 0)
goto err; goto err;
......
...@@ -840,6 +840,68 @@ outp: ...@@ -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, copy a string,
with optional character set conversion, with optional character set conversion,
......
...@@ -37,6 +37,9 @@ uint32 well_formed_copy_nchars(CHARSET_INFO *to_cs, ...@@ -37,6 +37,9 @@ uint32 well_formed_copy_nchars(CHARSET_INFO *to_cs,
const char **well_formed_error_pos, const char **well_formed_error_pos,
const char **cannot_convert_error_pos, const char **cannot_convert_error_pos,
const char **from_end_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 class String
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment