diff --git a/mysql-test/main/mysqltest_tracking_info.result b/mysql-test/main/mysqltest_tracking_info.result index d2eaa5afea8..0fb16b67d4b 100644 --- a/mysql-test/main/mysqltest_tracking_info.result +++ b/mysql-test/main/mysqltest_tracking_info.result @@ -39,3 +39,12 @@ SELECT @c:=10; @c:=10 10 SET @@session.session_track_user_variables=0; +# +# mdev-22337 Assertion `Alloced_length >= (str_length + length + +net_length_size(length))' failed in Binary_string::q_net_store_data +on long MULTIPOLYGON query with session_track_user_variables=1 +(optimized builds) +# +set @@session.session_track_user_variables=1; +set @a=repeat('X', 1029); +set @@session.session_track_user_variables=0; diff --git a/mysql-test/main/mysqltest_tracking_info.test b/mysql-test/main/mysqltest_tracking_info.test index 405b920051a..b3f05781d89 100644 --- a/mysql-test/main/mysqltest_tracking_info.test +++ b/mysql-test/main/mysqltest_tracking_info.test @@ -34,3 +34,15 @@ SET @b=NULL; SELECT @c:=10; --disable_session_track_info SET @@session.session_track_user_variables=0; + +--echo # +--echo # mdev-22337 Assertion `Alloced_length >= (str_length + length + +--echo net_length_size(length))' failed in Binary_string::q_net_store_data +--echo on long MULTIPOLYGON query with session_track_user_variables=1 +--echo (optimized builds) +--echo # +set @@session.session_track_user_variables=1; +--enable_session_track_info +set @a=repeat('X', 1029); +--disable_session_track_info +set @@session.session_track_user_variables=0; diff --git a/sql/session_tracker.cc b/sql/session_tracker.cc index e1c2ec37644..ed422fa025d 100644 --- a/sql/session_tracker.cc +++ b/sql/session_tracker.cc @@ -1198,12 +1198,18 @@ bool User_variables_tracker::store(THD *thd, String *buf) auto var= m_changed_user_variables.at(i); String value_str; bool null_value; + uint length; var->val_str(&null_value, &value_str, DECIMAL_MAX_SCALE); - buf->q_append(static_cast(SESSION_TRACK_USER_VARIABLES)); - ulonglong length= net_length_size(var->name.length) + var->name.length; + + length= net_length_size(var->name.length) + var->name.length; if (!null_value) length+= net_length_size(value_str.length()) + value_str.length(); + + if (buf->reserve(sizeof(char) + length + net_length_size(length))) + return true; + + buf->q_append(static_cast(SESSION_TRACK_USER_VARIABLES)); buf->q_net_store_length(length); buf->q_net_store_data(reinterpret_cast(var->name.str), var->name.length); @@ -1259,7 +1265,7 @@ void Session_tracker::store(THD *thd, String *buf) } size_t length= buf->length() - start; - uchar *data= (uchar *)(buf->ptr() + start); + uchar *data; uint size; if ((size= net_length_size(length)) != 1) @@ -1269,8 +1275,16 @@ void Session_tracker::store(THD *thd, String *buf) buf->length(start); // it is safer to have 0-length block in case of error return; } + + /* + The 'buf->reserve()' can change the buf->ptr() so we cannot + calculate the 'data' earlier. + */ + data= (uchar *)(buf->ptr() + start); memmove(data + (size - 1), data, length); } + else + data= (uchar *)(buf->ptr() + start); net_store_length(data - 1, length); }