diff --git a/mysql-test/main/vector2.result b/mysql-test/main/vector2.result index 99bff8aa4d67f..1d39de5213ae4 100644 --- a/mysql-test/main/vector2.result +++ b/mysql-test/main/vector2.result @@ -565,4 +565,33 @@ tmp CREATE TABLE `tmp` ( c drop table tmp, t1, t2; set sql_mode=@old_sql_mode; +# +# MDEV-40486 ER_TOO_BIG_FIELDLENGTH or assertion failure upon creating vector from blob +# +## Original testcase +CREATE TABLE t (a TEXT) AS SELECT '[1]' AS a; +CREATE TABLE tt AS SELECT VEC_FROMTEXT(a) AS f FROM t; +ERROR 42000: Column length too big for column 'f' (max = 16383); use BLOB or TEXT instead +DROP TABLE t; +## Conversion from max varchar length +CREATE TABLE t (a VARCHAR(16383)) AS +SELECT concat('[1', repeat(',1', 8190), ']') AS a; +CREATE TABLE tt AS SELECT VEC_FROMTEXT(a) AS f FROM t; +DROP TABLE t,tt; +## Conversion to max vector dimension +CREATE TABLE tt AS +SELECT VEC_FROMTEXT(concat('[1', repeat(',1', 16382), ']')) AS f; +DROP TABLE tt; +CREATE TABLE tt AS +SELECT VEC_FROMTEXT(concat('[1', repeat(',1', 16383), ']')) AS f; +ERROR 42000: Column length too big for column 'f' (max = 16383); use BLOB or TEXT instead +## Zero length: no underflow +## Note that CREATE ... SELECT raises warning as error +SELECT VEC_FROMTEXT('') AS f; +f +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'VEC_FromText' +CREATE TABLE tt AS SELECT VEC_FROMTEXT('') AS f; +ERROR HY000: Unexpected end of JSON text in argument 1 to function 'VEC_FromText' # End of 11.8 tests diff --git a/mysql-test/main/vector2.test b/mysql-test/main/vector2.test index be2493011aacd..c31322584a287 100644 --- a/mysql-test/main/vector2.test +++ b/mysql-test/main/vector2.test @@ -447,4 +447,35 @@ drop table tmp, t1, t2; set sql_mode=@old_sql_mode; +--echo # +--echo # MDEV-40486 ER_TOO_BIG_FIELDLENGTH or assertion failure upon creating vector from blob +--echo # + +--echo ## Original testcase +CREATE TABLE t (a TEXT) AS SELECT '[1]' AS a; +--error ER_TOO_BIG_FIELDLENGTH +CREATE TABLE tt AS SELECT VEC_FROMTEXT(a) AS f FROM t; +DROP TABLE t; + +--echo ## Conversion from max varchar length +CREATE TABLE t (a VARCHAR(16383)) AS + SELECT concat('[1', repeat(',1', 8190), ']') AS a; +CREATE TABLE tt AS SELECT VEC_FROMTEXT(a) AS f FROM t; +DROP TABLE t,tt; + +--echo ## Conversion to max vector dimension +CREATE TABLE tt AS + SELECT VEC_FROMTEXT(concat('[1', repeat(',1', 16382), ']')) AS f; +DROP TABLE tt; + +--error ER_TOO_BIG_FIELDLENGTH +CREATE TABLE tt AS + SELECT VEC_FROMTEXT(concat('[1', repeat(',1', 16383), ']')) AS f; + +--echo ## Zero length: no underflow +--echo ## Note that CREATE ... SELECT raises warning as error +SELECT VEC_FROMTEXT('') AS f; +--error ER_JSON_EOS +CREATE TABLE tt AS SELECT VEC_FROMTEXT('') AS f; + --echo # End of 11.8 tests diff --git a/sql/item_vectorfunc.cc b/sql/item_vectorfunc.cc index 13e458d7675d6..e5138f85bdafd 100644 --- a/sql/item_vectorfunc.cc +++ b/sql/item_vectorfunc.cc @@ -181,12 +181,13 @@ Item_func_vec_fromtext::Item_func_vec_fromtext(THD *thd, Item *a) bool Item_func_vec_fromtext::fix_length_and_dec(THD *thd) { + uint maxlen= args[0]->max_char_length(); decimals= 0; /* Worst case scenario, for a valid input we have a string of the form: [1,2,3,4,5,...] single digit numbers. - This means we can have (max_length - 1) / 2 floats. - Each float takes 4 bytes, so we do (max_length - 1) * 2. */ - fix_length_and_charset((args[0]->max_length - 1) * 2, &my_charset_bin); + This means we can have (maxlen - 1) / 2 floats. + Each float takes 4 bytes, so we do (maxlen - 1) * 2. */ + fix_length_and_charset(maxlen ? (maxlen - 1) * 2 : 0, &my_charset_bin); set_maybe_null(); return false; } diff --git a/sql/item_vectorfunc.h b/sql/item_vectorfunc.h index babf634704108..0631958fa0565 100644 --- a/sql/item_vectorfunc.h +++ b/sql/item_vectorfunc.h @@ -98,7 +98,15 @@ class Item_func_vec_fromtext: public Item_str_func const Type_handler *type_handler() const override { return &type_handler_vector; } Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table) override - { return create_table_field_from_handler(root, table); } + { + if (max_length > MAX_FIELD_VARCHARLENGTH) + { + my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), name.str, + static_cast(MAX_FIELD_VARCHARLENGTH / sizeof(float))); + return NULL; + } + return create_table_field_from_handler(root, table); + } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= { STRING_WITH_LEN("VEC_FromText") };