From 4e97c4322361956987090133a4af41220b1f5b5a Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Thu, 23 Jul 2026 17:09:01 +1000 Subject: [PATCH] MDEV-40486 Length check for vector fields in CREATE TABLE ... SELECT The changes of MDEV-39558 2b6529426a7e7c65d286e093d84138be9dcc34a3 added length check assertion in Field_varstring constructors, and length check in type inference for SELECT set operations, to emit errors before reaching the assertions. That change caused an error to turn into an assertion failure in a separate path, when the length limit violation is not detected before tripping the assertion. So in this patch we fix it by adding an earlier length check in that path. Also use max_char_length() instead of max_length. This is a more accurate length of characters. And add handling of empty string edge case. Added testcases accordingly. --- mysql-test/main/vector2.result | 29 +++++++++++++++++++++++++++++ mysql-test/main/vector2.test | 31 +++++++++++++++++++++++++++++++ sql/item_vectorfunc.cc | 7 ++++--- sql/item_vectorfunc.h | 10 +++++++++- 4 files changed, 73 insertions(+), 4 deletions(-) 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") };