From 330df4b836113f6f294c07d5d28fb81197968474 Mon Sep 17 00:00:00 2001 From: hopebo Date: Tue, 2 Nov 2021 18:29:53 +0800 Subject: [PATCH] Bugfix Arithmetic overflow when group_concat_max_len is set to a large value Description ----------- When group_concat_max_len is set to a large value, the product of `max_characters` and `collation.collation->mbmaxlen` may exceed the range of uint32, which causes arithmetic overflow when passed as parameter to `Field_blob::Field_blob()`. In this case, the result of GROUP_CONCAT() will be truncated unexpectedly. Fix --- When the product of `max_characters` and `collation.collation->mbmaxlen` exceeds the maximum number that uint32 can represent, we use UINT_MAX32 to represent the field length to avoid arithmetic overflow. --- sql/item_sum.cc | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 24a5fe28368..bde6109ea7c 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -4257,14 +4257,20 @@ Field *Item_func_group_concat::make_string_field(TABLE *table_arg) const { const uint32 max_characters = group_concat_max_len / collation.collation->mbminlen; + + // Avoid arithmetic overflow + const uint32 field_length = std::min( + static_cast(max_characters) * collation.collation->mbmaxlen, + UINT_MAX32); + if (max_characters > CONVERT_IF_BIGGER_TO_BLOB) field = new (*THR_MALLOC) - Field_blob(max_characters * collation.collation->mbmaxlen, - is_nullable(), item_name.ptr(), collation.collation, true); + Field_blob(field_length, is_nullable(), item_name.ptr(), + collation.collation, true); else - field = new (*THR_MALLOC) Field_varstring( - max_characters * collation.collation->mbmaxlen, is_nullable(), - item_name.ptr(), table_arg->s, collation.collation); + field = new (*THR_MALLOC) + Field_varstring(field_length, is_nullable(), item_name.ptr(), + table_arg->s, collation.collation); if (field) field->init(table_arg); return field; @@ -4373,7 +4379,10 @@ bool Item_func_group_concat::fix_fields(THD *thd, Item **ref) { group_concat_max_len = static_cast(thd->variables.group_concat_max_len); uint32 max_chars = group_concat_max_len / collation.collation->mbminlen; - uint32 max_byte_length = max_chars * collation.collation->mbmaxlen; + // Avoid arithmetic overflow + uint32 max_byte_length = std::min( + static_cast(max_chars) * collation.collation->mbmaxlen, + UINT_MAX32); max_chars > CONVERT_IF_BIGGER_TO_BLOB ? set_data_type_blob(max_byte_length) : set_data_type_string(max_chars); -- 2.19.1.3.ge56e4f7