[MDEV-4250] Server crashes on a query with AND and OR conditions Created: 2013-03-06  Updated: 2013-03-12  Resolved: 2013-03-12

Status: Closed
Project: MariaDB Server
Component/s: None
Affects Version/s: None
Fix Version/s: 5.5.30, 5.3.13

Type: Bug Priority: Major
Reporter: Elena Stepanova Assignee: Igor Babaev
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Relates

 Description   

The following query makes the server crash with a long corrupted stack trace:

SELECT * FROM mysql.time_zone 
WHERE ( NOT (Use_leap_seconds <= Use_leap_seconds AND Time_zone_id != 1) 
        AND Time_zone_id = Time_zone_id 
     OR Time_zone_id <> Time_zone_id ) 
  AND Use_leap_seconds <> 'N'
;

Reproducible on maria/5.5 tree starting from revision 3671 (merge 5.3=>5.5), however 5.3 does not crash with the same query.

Stack trace (from a debug build, same picture on two different machines, note 2400+ frames):

Thread 1 (Thread 0x7f194ae44700 (LWP 30028)):
#0  __pthread_kill (threadid=<optimized out>, signo=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/pthread_kill.c:63
#1  0x0000000000ccf314 in my_write_core (sig=11) at 5.5/mysys/stacktrace.c:457
#2  0x00000000007c5bc8 in handle_fatal_signal (sig=11) at 5.5/sql/signal_handler.cc:262
#3  <signal handler called>
#4  0x00007f194004ada8 in ?? ()
#5  0xa5a5a5a5a5a5a5a5 in ?? ()
...
#2402 0x00007f1940048fd0 in ?? ()
#2403 0x0000000000000800 in ?? ()
#2404 0x0000000000ca006e in init_dynamic_array2 (array=0xff000000ff, element_size=255, init_buffer=0xff000000ff, init_alloc=255, alloc_increment=255) at 5.5/mysys/array.c:65
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

revision-id: holyfoot@askmonty.org-20130305214525-2lgv24a11bmeu6iq
revno: 3682
branch-nick: 5.5

Reproducible with the default optimizer_switch as well as with all OFF values.
EXPLAIN also crashes.



 Comments   
Comment by Sergei Golubchik [ 2013-03-07 ]

What's happening here:

In build_equal_items_for_cond() a local copy of cond_equal is created on the stack:

11608 static COND *build_equal_items_for_cond(THD *thd, COND *cond,
11609 COND_EQUAL *inherited)
11610 {
11611 Item_equal *item_equal;
11612 COND_EQUAL cond_equal;

It contains a List inside. When a List is initialized it does this->last = &this->first;
later it is copied into an item:

11662 ((Item_cond_and*)cond)->cond_equal= cond_equal;

when this function returns the item gets cond->cond_equal.current_level.last pointer points somewhere in the middle of the stack.

Later in Item_equal::merge_into_list():

5766 if (!merge_into)
5767 list->push_back(this);

this *last pointer is written into, which corrupts the stack.

Comment by Igor Babaev [ 2013-03-08 ]

This bug manifests itself already in the current build of mariadb 5.3.
The returned result for the reported query is incorrect:

MariaDB [test]> SELECT * FROM mysql.time_zone
-> WHERE ( NOT (Use_leap_seconds <= Use_leap_seconds AND Time_zone_id != 1)
-> AND Time_zone_id = Time_zone_id
-> OR Time_zone_id <> Time_zone_id )
-> AND Use_leap_seconds <> 'N'
-> ;
------------------------------+

Time_zone_id Use_leap_seconds

------------------------------+

4 Y

------------------------------+

The expected result is an empty set.

The problem is seen for the following simplified query:

MariaDB [test]> SELECT * FROM mysql.time_zone WHERE (FALSE OR Time_zone_id = 1) AND Use_leap_seconds <> 'N';
------------------------------+

Time_zone_id Use_leap_seconds

------------------------------+

4 Y

------------------------------+
1 row in set (0.00 sec)

EXPLAIN EXTENDED for this query returns:

MariaDB [test]> EXPLAIN EXTENDED SELECT * FROM mysql.time_zone WHERE (FALSE OR Time_zone_id = 1) AND Use_leap_seconds <> 'N';
-------------------------------------------------------------------------------

id select_type table type possible_keys key key_len ref rows filtered Extra

-------------------------------------------------------------------------------

1 SIMPLE time_zone ALL NULL NULL NULL NULL 5 100.00 Using where

-------------------------------------------------------------------------------

MariaDB [test]> show warnings;
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Level Code Message

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Note 1003 select `mysql`.`time_zone`.`Time_zone_id` AS `Time_zone_id`,`mysql`.`time_zone`.`Use_leap_seconds` AS `Use_leap_seconds` from `mysql`.`time_zone` where (`mysql`.`time_zone`.`Use_leap_seconds` <> 'N')

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

It can be seen that the WHERE condition has been converted to a condition that isn't equivalent to the original condition.

This bug appeared after the patch for mdev-4177 had been pushed into the 5.3 tree (rev 3628). The bug existed before this patch, but bug mdev-4177
masked it.

Comment by Igor Babaev [ 2013-03-08 ]

The fix has been pushed into the 5.3 tree.

Generated at Thu Feb 08 06:54:57 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.