MDEV-25151 JSON_TABLE: Unexpectedly padded values in a PATH column.

Field length can increase after the change_charset(), so need to
set field->ptr properly.

also sensitive parts of the test moved to json_not_embedded.test.
This commit is contained in:
Alexey Botchkov 2021-03-18 15:36:28 +04:00
parent 047eb2258d
commit 51ac57fbbe
5 changed files with 90 additions and 51 deletions

View File

@ -98,26 +98,6 @@ a
1
connection default;
disconnect con1;
create database db;
use db;
create table t (a text);
insert into t values ('{"foo":"bar"}');
create user u@localhost;
grant select (a) on db.t to u@localhost;
connect con1,localhost,u,,db;
select a from t;
a
{"foo":"bar"}
select * from t, json_table(t.a, '$' columns(f varchar(20) path '$.foo')) as jt;
a f
{"foo":"bar"} bar
select * into outfile 'f' from json_table('[]', '$' columns(x for ordinality)) q;
ERROR 28000: Access denied for user 'u'@'localhost' (using password: NO)
connection default;
disconnect con1;
drop user u@localhost;
drop database db;
use test;
create table t1 (
color varchar(32),
price int
@ -515,5 +495,15 @@ a
SELECT a, b FROM JSON_TABLE('[]', '$' COLUMNS (a FOR ORDINALITY, b INT PATH '$[*]' ERROR ON EMPTY)) AS t ORDER BY a;
ERROR HY000: Field 'b' can't be set for JSON_TABLE 't'.
#
# MDEV-25151 JSON_TABLE: Unexpectedly padded values in a PATH column.
#
SET @old_character_set_connection= @@character_set_connection;
SET @@character_set_connection= utf8;
select hex(a), b from json_table('["foo","bar"]','$[*]' columns (a char(3) path '$', b for ordinality)) t;
hex(a) b
666F6F 1
626172 2
SET @@character_set_connection= @old_character_set_connection;
#
# End of 10.6 tests
#

View File

@ -0,0 +1,20 @@
create database db;
use db;
create table t (a text);
insert into t values ('{"foo":"bar"}');
create user u@localhost;
grant select (a) on db.t to u@localhost;
connect con1,localhost,u,,db;
select a from t;
a
{"foo":"bar"}
select * from t, json_table(t.a, '$' columns(f varchar(20) path '$.foo')) as jt;
a f
{"foo":"bar"} bar
select * into outfile 'f' from json_table('[]', '$' columns(x for ordinality)) q;
ERROR 28000: Access denied for user 'u'@'localhost' (using password: NO)
connection default;
disconnect con1;
drop user u@localhost;
drop database db;
use test;

View File

@ -59,34 +59,6 @@ select a from json_table('{"a":0}',"$" columns(a for ordinality)) foo;
connection default;
disconnect con1;
#
# MDEV-22302 JSON_TABLE: Column privilege is insufficient for query with json_table
#
create database db;
use db;
create table t (a text);
insert into t values ('{"foo":"bar"}');
create user u@localhost;
grant select (a) on db.t to u@localhost;
--connect (con1,localhost,u,,db)
select a from t;
select * from t, json_table(t.a, '$' columns(f varchar(20) path '$.foo')) as jt;
#
# MDEV-25141 JSON_TABLE: SELECT into outfile bypasses file privilege check
#
--error ER_ACCESS_DENIED_ERROR
select * into outfile 'f' from json_table('[]', '$' columns(x for ordinality)) q;
connection default;
disconnect con1;
drop user u@localhost;
drop database db;
use test;
create table t1 (
color varchar(32),
price int
@ -407,6 +379,14 @@ EXECUTE stmt;
--error ER_JSON_TABLE_ERROR_ON_FIELD
SELECT a, b FROM JSON_TABLE('[]', '$' COLUMNS (a FOR ORDINALITY, b INT PATH '$[*]' ERROR ON EMPTY)) AS t ORDER BY a;
--echo #
--echo # MDEV-25151 JSON_TABLE: Unexpectedly padded values in a PATH column.
--echo #
SET @old_character_set_connection= @@character_set_connection;
SET @@character_set_connection= utf8;
select hex(a), b from json_table('["foo","bar"]','$[*]' columns (a char(3) path '$', b for ordinality)) t;
SET @@character_set_connection= @old_character_set_connection;
--echo #
--echo # End of 10.6 tests
--echo #

View File

@ -0,0 +1,30 @@
source include/not_embedded.inc;
#
# MDEV-22302 JSON_TABLE: Column privilege is insufficient for query with json_table
#
create database db;
use db;
create table t (a text);
insert into t values ('{"foo":"bar"}');
create user u@localhost;
grant select (a) on db.t to u@localhost;
--connect (con1,localhost,u,,db)
select a from t;
select * from t, json_table(t.a, '$' columns(f varchar(20) path '$.foo')) as jt;
#
# MDEV-25141 JSON_TABLE: SELECT into outfile bypasses file privilege check
#
--error ER_ACCESS_DENIED_ERROR
select * into outfile 'f' from json_table('[]', '$' columns(x for ordinality)) q;
connection default;
disconnect con1;
drop user u@localhost;
drop database db;
use test;

View File

@ -1134,12 +1134,31 @@ int Table_function_json_table::setup(THD *thd, TABLE_LIST *sql_table,
}
{
/*
The m_json defines it's charset during the fix_fields stage so we're
changing the field's current charsets with it.
The complicated part is that the length of the field can be changed so
in this case we should move all the consequent fiedlds.
*/
List_iterator_fast<Json_table_column> jc_i(m_columns);
for (uint i= 0; t->field[i]; i++)
int field_offset= 0;
Field *f;
for (uint i= 0; (f= t->field[i]); i++)
{
Json_table_column *jc= jc_i++;
t->field[i]->change_charset(
jc->m_explicit_cs ? jc->m_explicit_cs : m_json->collation);
uint32 old_pack_length= f->pack_length();
f->change_charset(
jc->m_explicit_cs ? jc->m_explicit_cs : m_json->collation);
if (field_offset)
{
f->move_field(f->ptr + field_offset, f->null_ptr, f->null_bit);
f->reset();
}
field_offset= (field_offset + f->pack_length()) - old_pack_length;
/*
The m_field->charset is going to be reused if it's the prepared
statement running several times. So should restored the original