Skip to content

Commit a2894d6

Browse files
committed
Bug#21487833: DBUG_ABORT() IN JSON_WRAPPER::MAKE_HASH_KEY WITH ORDERED JSON
If a NULL value is inserted into a not nullable JSON column (which is possible if strict SQL mode is turned off), an empty string is inserted at that position. Since an empty string is not a valid representation of a JSON value, code that attempts to parse it, might raise an error, or possibly hit an assertion in debug builds. Field_json::val_json() knows about this case and will return a representation of the JSON null literal if it encounters it. However, some parts of the code bypass val_json() and access the internal representation directly, and they fail when they try to parse the stored value. This patch fixes the failures by making the failing code access the JSON values via Field_json::val_json(), which doesn't suffer from this problem, instead of accessing the internal representation directly.
1 parent aaf9f41 commit a2894d6

File tree

4 files changed

+63
-31
lines changed

4 files changed

+63
-31
lines changed

mysql-test/r/json.result

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13032,3 +13032,28 @@ j1 jv j2 JSON_ARRAY(j1, jv, j2)
1303213032
1 1 1 [1, 1, 1]
1303313033
DROP TABLE t1, t2;
1303413034
DROP VIEW v;
13035+
#
13036+
# Bug#21487833: DBUG_ABORT() IN JSON_WRAPPER::MAKE_HASH_KEY
13037+
# WITH ORDERED JSON
13038+
#
13039+
Warnings:
13040+
Warning 3135 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict mode. They will be merged with strict mode in a future release.
13041+
CREATE TABLE t (a BLOB, b JSON NOT NULL) ENGINE=InnoDB;
13042+
INSERT INTO t VALUES ('', NULL), ('', NULL);
13043+
Warnings:
13044+
Warning 1048 Column 'b' cannot be null
13045+
UPDATE t SET a = 1 ORDER BY b;
13046+
SELECT COUNT(a) FROM t GROUP BY b;
13047+
COUNT(a)
13048+
2
13049+
SELECT DISTINCT B FROM t;
13050+
B
13051+
null
13052+
SELECT b FROM t UNION DISTINCT SELECT b FROM t;
13053+
b
13054+
null
13055+
SELECT * FROM t ORDER BY b;
13056+
a b
13057+
1 null
13058+
1 null
13059+
DROP TABLE t;

mysql-test/t/json.test

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5903,6 +5903,21 @@ SELECT j1, jv, j2, JSON_ARRAY(j1, jv, j2) FROM t1 LEFT JOIN v ON j1 = jv;
59035903
DROP TABLE t1, t2;
59045904
DROP VIEW v;
59055905

5906+
--echo #
5907+
--echo # Bug#21487833: DBUG_ABORT() IN JSON_WRAPPER::MAKE_HASH_KEY
5908+
--echo # WITH ORDERED JSON
5909+
--echo #
5910+
--source include/turn_off_strict_mode.inc
5911+
CREATE TABLE t (a BLOB, b JSON NOT NULL) ENGINE=InnoDB;
5912+
INSERT INTO t VALUES ('', NULL), ('', NULL);
5913+
UPDATE t SET a = 1 ORDER BY b;
5914+
SELECT COUNT(a) FROM t GROUP BY b;
5915+
SELECT DISTINCT B FROM t;
5916+
SELECT b FROM t UNION DISTINCT SELECT b FROM t;
5917+
SELECT * FROM t ORDER BY b;
5918+
DROP TABLE t;
5919+
--source include/restore_strict_mode.inc
5920+
59065921
# Local Variables:
59075922
# mode: sql
59085923
# sql-product: mysql

sql/field.cc

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9046,19 +9046,23 @@ bool Field_json::get_time(MYSQL_TIME *ltime)
90469046

90479047
void Field_json::make_sort_key(uchar *to, size_t length)
90489048
{
9049-
String tmp;
9050-
String *s= Field_blob::val_str(&tmp, &tmp);
9051-
Json_wrapper wr(json_binary::parse_binary(s->ptr(), s->length()));
9049+
Json_wrapper wr;
9050+
if (val_json(&wr))
9051+
{
9052+
/* purecov: begin inspected */
9053+
memset(to, 0, length);
9054+
return;
9055+
/* purecov: end */
9056+
}
90529057
wr.make_sort_key(to, length);
90539058
}
90549059

90559060

90569061
ulonglong Field_json::make_hash_key(ulonglong *hash_val)
90579062
{
9058-
String tmp;
9059-
String *s= Field_blob::val_str(&tmp, &tmp);
9060-
Json_wrapper wr(json_binary::parse_binary(s->ptr(), s->length()));
9061-
9063+
Json_wrapper wr;
9064+
if (val_json(&wr))
9065+
return *hash_val; /* purecov: inspected */
90629066
return wr.make_hash_key(hash_val);
90639067
}
90649068

sql/sql_executor.cc

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
#include "sql_optimizer.h" // JOIN
3737
#include "sql_show.h" // get_schema_tables_result
3838
#include "sql_tmp_table.h" // create_tmp_table
39-
#include "json_binary.h" // json_binary::Value
4039
#include "json_dom.h" // Json_wrapper
4140

4241
#include <algorithm>
@@ -3098,29 +3097,18 @@ static bool cmp_field_value(Field *field, my_ptrdiff_t diff)
30983097

30993098
Field_json *json_field= down_cast<Field_json *>(field);
31003099

3101-
char *left_data;
3102-
json_field->get_ptr(pointer_cast<uchar **>(&left_data));
3103-
json_binary::Value left_value(json_binary::parse_binary(left_data, src_len));
3104-
if (left_value.type() == json_binary::Value::ERROR)
3105-
{
3106-
/* purecov: begin inspected */
3107-
my_error(ER_INVALID_JSON_BINARY_DATA, MYF(0));
3108-
return true;
3109-
/* purecov: end */
3110-
}
3111-
Json_wrapper left_wrapper(left_value);
3112-
3113-
char *right_data;
3114-
json_field->get_ptr(pointer_cast<uchar **>(&right_data), diff);
3115-
json_binary::Value right_value(json_binary::parse_binary(right_data, dst_len));
3116-
if (right_value.type() == json_binary::Value::ERROR)
3117-
{
3118-
/* purecov: begin inspected */
3119-
my_error(ER_INVALID_JSON_BINARY_DATA, MYF(0));
3120-
return true;
3121-
/* purecov: end */
3122-
}
3123-
Json_wrapper right_wrapper(right_value);
3100+
// Fetch the JSON value on the left side of the comparison.
3101+
Json_wrapper left_wrapper;
3102+
if (json_field->val_json(&left_wrapper))
3103+
return true; /* purecov: inspected */
3104+
3105+
// Fetch the JSON value on the right side of the comparison.
3106+
Json_wrapper right_wrapper;
3107+
json_field->ptr+= diff;
3108+
bool err= json_field->val_json(&right_wrapper);
3109+
json_field->ptr-= diff;
3110+
if (err)
3111+
return true; /* purecov: inspected */
31243112

31253113
return (left_wrapper.compare(right_wrapper) != 0);
31263114
}

0 commit comments

Comments
 (0)