From: Sneha Modi Date: November 22 2011 10:58am Subject: bzr push into mysql-trunk branch (sneha.modi:3640 to 3641) Bug#11748731 List-Archive: http://lists.mysql.com/commits/142128 X-Bug: 11748731 Message-Id: <201111221058.pAMAwT24020214@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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).