Commit 5d66eeb3 authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-26724 Endless loop in json_escape_to_string upon ... empty string

.. part#2: correctly pass the charset to JSON [un]escape functions
parent 43a8d9f1
...@@ -7898,6 +7898,34 @@ a ...@@ -7898,6 +7898,34 @@ a
b b
drop table t1; drop table t1;
create table t1 (a char(1)) character set latin1;
insert into t1 values (0xD1);
select hex(a) from t1;
hex(a)
D1
set histogram_type='json_hb';
analyze table t1 persistent for all;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
select decode_histogram(hist_type, histogram)
from mysql.column_stats
where db_name=database() and table_name='t1';
decode_histogram(hist_type, histogram)
{
"histogram_hb_v2": [
{
"start": "Ñ",
"end": "Ñ",
"size": 1,
"ndv": 1
}
]
}
select * from t1;
a
Ñ
drop table t1;
# #
# ASAN use-after-poison my_strnxfrm_simple_internal / Histogram_json_hb::range_selectivity ... # ASAN use-after-poison my_strnxfrm_simple_internal / Histogram_json_hb::range_selectivity ...
# (Just the testcase) # (Just the testcase)
......
...@@ -215,6 +215,19 @@ ANALYZE TABLE t PERSISTENT FOR ALL; ...@@ -215,6 +215,19 @@ ANALYZE TABLE t PERSISTENT FOR ALL;
select * from t1; select * from t1;
drop table t1; drop table t1;
create table t1 (a char(1)) character set latin1;
insert into t1 values (0xD1);
select hex(a) from t1;
set histogram_type='json_hb';
analyze table t1 persistent for all;
select decode_histogram(hist_type, histogram)
from mysql.column_stats
where db_name=database() and table_name='t1';
select * from t1;
drop table t1;
--echo # --echo #
--echo # ASAN use-after-poison my_strnxfrm_simple_internal / Histogram_json_hb::range_selectivity ... --echo # ASAN use-after-poison my_strnxfrm_simple_internal / Histogram_json_hb::range_selectivity ...
--echo # (Just the testcase) --echo # (Just the testcase)
......
...@@ -39,7 +39,7 @@ static bool json_unescape_to_string(const char *val, int val_len, String* out) ...@@ -39,7 +39,7 @@ static bool json_unescape_to_string(const char *val, int val_len, String* out)
int res= json_unescape(&my_charset_utf8mb4_bin, int res= json_unescape(&my_charset_utf8mb4_bin,
(const uchar*)val, (const uchar*)val,
(const uchar*)val + val_len, (const uchar*)val + val_len,
&my_charset_utf8mb4_bin, out->charset(),
buf, buf + out->length()); buf, buf + out->length());
if (res >= 0) if (res >= 0)
{ {
...@@ -58,7 +58,7 @@ static bool json_unescape_to_string(const char *val, int val_len, String* out) ...@@ -58,7 +58,7 @@ static bool json_unescape_to_string(const char *val, int val_len, String* out)
Escape a JSON string and save it into *out. Escape a JSON string and save it into *out.
*/ */
static bool json_escape_to_string(const char *val, int val_len, String* out) static bool json_escape_to_string(const String *str, String* out)
{ {
// Make sure 'out' has some memory allocated. // Make sure 'out' has some memory allocated.
if (!out->alloced_length() && out->alloc(128)) if (!out->alloced_length() && out->alloc(128))
...@@ -68,10 +68,11 @@ static bool json_escape_to_string(const char *val, int val_len, String* out) ...@@ -68,10 +68,11 @@ static bool json_escape_to_string(const char *val, int val_len, String* out)
{ {
uchar *buf= (uchar*)out->ptr(); uchar *buf= (uchar*)out->ptr();
out->length(out->alloced_length()); out->length(out->alloced_length());
const uchar *str_ptr= (const uchar*)str->ptr();
int res= json_escape(&my_charset_utf8mb4_bin, int res= json_escape(str->charset(),
(const uchar*)val, str_ptr,
(const uchar*)val + val_len, str_ptr + str->length(),
&my_charset_utf8mb4_bin, &my_charset_utf8mb4_bin,
buf, buf + out->length()); buf, buf + out->length());
if (res >= 0) if (res >= 0)
...@@ -200,7 +201,7 @@ class Histogram_json_builder : public Histogram_builder ...@@ -200,7 +201,7 @@ class Histogram_json_builder : public Histogram_builder
// Escape the value for JSON // Escape the value for JSON
StringBuffer<MAX_FIELD_WIDTH> escaped_val; StringBuffer<MAX_FIELD_WIDTH> escaped_val;
if (json_escape_to_string(str->ptr(), str->length(), &escaped_val)) if (json_escape_to_string(str, &escaped_val))
return true; return true;
// Note: The Json_writer does NOT do escapes (perhaps this should change?) // Note: The Json_writer does NOT do escapes (perhaps this should change?)
...@@ -473,6 +474,7 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, ...@@ -473,6 +474,7 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field,
goto error; goto error;
} }
unescape_buf.set_charset(field->charset());
uint len_to_copy= field->key_length(); uint len_to_copy= field->key_length();
if (json_unescape_to_string(val, val_len, &unescape_buf)) if (json_unescape_to_string(val, val_len, &unescape_buf))
{ {
...@@ -481,7 +483,7 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, ...@@ -481,7 +483,7 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field,
goto error; goto error;
} }
field->store_text(unescape_buf.ptr(), unescape_buf.length(), field->store_text(unescape_buf.ptr(), unescape_buf.length(),
&my_charset_bin); unescape_buf.charset());
value_buf.alloc(field->pack_length()); value_buf.alloc(field->pack_length());
uint bytes= field->get_key_image((uchar*)value_buf.ptr(), len_to_copy, uint bytes= field->get_key_image((uchar*)value_buf.ptr(), len_to_copy,
Field::itRAW); Field::itRAW);
......
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