1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Bug #54465: assert: field_types == 0 || field_types[field_pos]

== MYSQL_TYPE_LONGLONG

A MIN/MAX() function with a subquery as its argument could lead
to a debug assertion on debug builds or wrong data on release
ones.

The problem was a combination of the following factors:

- Item_sum_hybrid::fix_fields() might use the argument
(args[0]) to calculate 'hybrid_field_type' which was later used
to decide how the data should be sent to the client.

- Item_sum::make_field() might use the argument again to
calculate the field's type when sending result set metadata to
the client.

- The argument could be changed in between these two calls via
  Item::set_arg() leading to inconsistent metadata being
  reported.

Here is what was happening for the bug's test case:

1. Item_sum_hybrid::fix_fields() calculates hybrid_field_type
as MYSQL_TYPE_LONGLONG based on args[0] which is an
Item::SUBSELECT_ITEM at that time.

2. A temporary table is created to execute the
query. create_tmp_field_from_item() creates a Field_long object
according to the subselect's max_length.

3. The subselect item in Item_sum_hybrid is replaced by the
Item_field object referencing the newly created Field_long.

4. Item_sum::make_field() rightfully returns the
MYSQL_TYPE_LONG type when calculating the result set metadata.

5. When sending the actual data, Item::send() relies on the
virtual field_type() function which in our case returns
previously calculated hybrid_field_type == MYSQL_TYPE_LONGLONG.

It looks like the only solution is to never refer to the
argument's metadata after the result metadata has been
calculated in fix_fields(), since the argument itself may be
different by then. In this sense, Item_sum::make_field() should
never be used, because it may rely on the argument's metadata
and is only called after fix_fields(). The "default"
implementation in Item::make_field() should be used instead as
it relies only on field_type(), but not on the argument's type.

Fixed by removing Item_sum::make_field() so that the superclass
implementation Item::make_field() is always used.

mysql-test/r/func_group.result:
  Added a test case for bug #54465.
mysql-test/t/func_group.test:
  Added a test case for bug #54465.
sql/item_sum.cc:
  Removed Item_sum::make_field() so that the superclass
  implementation Item::make_field() is always used.
sql/item_sum.h:
  Removed Item_sum::make_field() so that the superclass
  implementation Item::make_field() is always used.
This commit is contained in:
Alexey Kopytov
2010-08-27 13:44:35 +04:00
parent 27d5b6e57f
commit d7d0f6390b
4 changed files with 25 additions and 21 deletions

View File

@ -1713,4 +1713,15 @@ f1 f2 f3 f4 f1 = f2
NULL NULL NULL NULL NULL
drop table t1;
#
# Bug #54465: assert: field_types == 0 || field_types[field_pos] ==
# MYSQL_TYPE_LONGLONG
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1), (2);
SELECT MAX((SELECT 1 FROM t1 ORDER BY @var LIMIT 1)) m FROM t1 t2, t1
ORDER BY t1.a;
m
1
DROP TABLE t1;
#
End of 5.1 tests