• Norvald H. Ryeng's avatar
    Bug#13003736 CRASH IN ITEM_REF::WALK WITH SUBQUERIES · 5f61cc43
    Norvald H. Ryeng authored
    Problem: Some queries with subqueries and a HAVING clause that
    consists only of a column not in the select or grouping lists causes
    the server to crash.
    
    During parsing, an Item_ref is constructed for the HAVING column. The
    name of the column is resolved when JOIN::prepare calls fix_fields()
    on its having clause. Since the column is not mentioned in the select
    or grouping lists, a ref pointer is not found and a new Item_field is
    created instead. The Item_ref is replaced by the Item_field in the
    tree of HAVING clauses. Since the tree consists only of this item, the
    pointer that is updated is JOIN::having. However,
    st_select_lex::having still points to the Item_ref as the root of the
    tree of HAVING clauses.
    
    The bug is triggered when doing filesort for create_sort_index(). When
    find_all_keys() calls select->cond->walk() it eventually reaches
    Item_subselect::walk() where it continues to walk the having clauses
    from lex->having. This means that it finds the Item_ref instead of the
    new Item_field, and Item_ref::walk() tries to dereference the ref
    pointer, which is still null.
    
    The crash is reproducible only in 5.5, but the problem lies latent in
    5.1 and trunk as well.
    
    Fix: After calling fix_fields on the having clause in JOIN::prepare(),
    set select_lex::having to point to the same item as JOIN::having.
    
    This patch also fixes a bug in 5.1 and 5.5 that is triggered if the
    query is executed as a prepared statement. The Item_field is created
    in the runtime arena when the query is prepared, and the pointer to
    the item is saved by st_select_lex::fix_prepare_information() and
    brought back as a dangling pointer when the query is executed, after
    the runtime arena has been reclaimed.
    
    Fix: Backport fix from trunk that switches to the permanent arena
    before calling Item_ref::fix_fields() in JOIN::prepare().
    5f61cc43
item.cc 213 KB