Details
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.
Gliffy Diagrams
Attachments
Activity
- All
- Comments
- Work Log
- History
- Activity
- Transitions
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.