3641 Sneha Modi 2011-11-22 [merge]
Null merge of fix for Bug#11748731 from mysql-5.5 -> mysql-trunk
3640 Olav Sandstaa 2011-11-22
Fix for Bug#13102033 CRASH IN COPY_FUNCS IN SQL_SELECT.CC ON JOIN + GROUP BY
+ ORDER BY
This crash occurred in the function copy_funcs() due to the array of
functions pointers was not correctly terminated. This caused data
following the func_ptr array to be interpreted as pointers to
functions/items. The funct_ptr array given to copy_funcs() is stored
inside the join's tmp_table_param structure's member called items_to_copy.
In this case we had added one more entry than we had allocated space for
so the value of the last entry was a pointer to a real item instead of a
NULL pointer. The reason for why an extra pointer was added:
1. When preparing the query we create Item objects for the where,
group by and order by conditions. Since this query involves a view
several of these will be subclasses of Item_ref. In the function
create_view_field() we create three Item_direct_view_ref
objects representing the "v1.i2" for the two instances in the where
clause and one for the order by clause. What is important to
notice is that three separate Item_direct_view_ref objects are
created but the ref pointer of all these points to a common
(Item*) variable (which again points to the actual Item_field object).
2. When optimizing the query we call optimize_conds() which will
build_equal_items and among other things substitute fields with
constants where possible. In this query it will use that "v1.i2 =
211" to replace "v1.i2 > 7" with "211 > 7". To do this replacement
it will use the Item class' compile and transform functions. The
v1.i2 is represented by a subclass of Item_ref. The current code
for Item_ref::compile() will first compile the item object found
through the ref pointer. This will cause the field "i2" to be
replaced by the constant field "211". Because of this the next step
done by Item_ref::compile() is to replace the content in the ref*
variable to point to this constant field. This gives the correct
result for the item three that is being optimized but it causes an
inconsistency for the ORDER BY clause. Since the
Item_direct_view_ref created for the ORDER BY clause points to the
same (Item*) variable as for the Item_direct_view_ref in the where
clause, the update of the ref* in the Item_direct_view_ref of the
where clause will also cause the same change to be done to the
ORDER BY clause. So the result from running optimize_conds() is
that the ORDER BY clause has been changed from "v1.i2" to the
constant "211".
3. When creating the temporary table used for the ORDER BY we will use
the updated Item_direct_view_ref object that now points to the
constant "211". Since this is a constant we do not allocate space
for it in the items_to_copy array but still insert it into the
array (causing the terminating NULL value to be written outside of
the allocated array).
Summary of the bug: Item_ref's compile() and transform() functions
update the ref* variable when the item they reference changes. The
ref* can be shared between multiple Item_ref objects. This causes all
other Item_ref objects that share the common ref* variable to be
wrongly updated.
The fix is to change Item_ref's compile() and transform() functions to
not update the ref* variable but instead they will return the new
object as the result of the compile() or transform() operation. The
result of this change will be that when the object that the Item_ref
references is replaced, the entire Item_ref objects will be replaced
by the new object instead of doing changes to the Item_ref's ref
pointer.
The original substitution is wrong in yet another situation: If we have
two conditions combined with OR, substituting one field reference in one
of the conditions would actually replace the same field in the second
conditions, potentially causing a wrong result.
@ mysql-test/r/join.result
Test case for Bug#13102033 "CRASH IN COPY_FUNCS IN SQL_SELECT.CC ON JOIN
+ GROUP BY + ORDER BY"
@ mysql-test/t/join.test
Test case for Bug#13102033 "CRASH IN COPY_FUNCS IN SQL_SELECT.CC ON JOIN
+ GROUP BY + ORDER BY"
This test contains two queries. The first query contains an ORDER
BY on a field from a view that is also present in the WHERE
condition. These will be represented by Item_direct_view_ref
objects that share a commont *ref pointer. This query will test
that when we do constant propagation on the Item_direct_view_ref
of the WHERE condition it should not change the ORDER BY.
The second query tests that if we have two conditions represented by
Item_direct_view_ref objects combined with OR, constant propagation
for one of these will not replace the second condition and cause
wrong result.
@ sql/item.cc
Change Item_ref's compile() and transform() functions from doing updates
of the ref pointer when the object they references is replaced with a
new object. Instead these functions will return the new object as the
result of the compile/transform.
modified:
mysql-test/r/join.result
mysql-test/t/join.test
sql/item.cc
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (sneha.modi:3640 to 3641) Bug#11748731 | Sneha Modi | 22 Nov |