Details
-
Bug
-
Status: Confirmed (View Workflow)
-
Major
-
Resolution: Unresolved
-
11.4.4
-
None
-
Ubuntu Nobel
Description
I've just worked around an obscure bug where the error message did not match the error condition.
A stored procedure calls another stored procedure multiple times:
create procedure testCursorCall() |
begin
|
select '1'; |
call testCursor(vPractIds);
|
|
select '2'; |
call testCursor(vPractIds);
|
|
select '3'; |
call testCursor(vPractIds);
|
|
select '4'; |
call testCursor(vPractIds);
|
end |
The routine testCursor creates a cursor to run through a temp table. It then destroys and recreates the temp table before using the cursor:
create procedure testCursor() |
begin
|
declare done, vItem int unsigned; |
declare testCur cursor for |
select x.Item |
from tmpFoo as x |
order by x.Item asc; |
declare continue handler for not found set done = 1; |
|
drop temporary table if exists tmpFoo; |
create temporary table tmpFoo |
(Id int unsigned primary key auto_increment, |
Item varchar(256) |
) engine = memory;
|
|
insert into tmpFoo |
(Item)
|
values |
("1"), ("2"); |
|
open testCur; |
curLoop: loop
|
set done = 0; |
fetch testCur into vItem; |
if done = 1 then |
leave curLoop;
|
end if; |
end loop; |
close testCur; |
end |
The second time testCursorCall() calls testCursor(), I get a syntax error:
MariaDB [mbook_dev]> call testCursorCall();
|
+---+
|
| 1 |
|
+---+
|
| 1 |
|
+---+
|
1 row in set (0.003 sec)
|
|
+---+
|
| 2 |
|
+---+
|
| 2 |
|
+---+
|
1 row in set (0.007 sec)
|
|
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'select x.Item
|
from tmpFoo as x
|
order by x.Item asc' at line 2
|
After much experimentation, I found that the actual error is that the temp table should not be dropped and recreated.
I suspect Maria is not recompiling the Cursor on the second run, but the table being dropped and recreated is destroying the internal table reference the compiled cursor is using. This is just a guess - I know nothing of MariaDB internals.
If testCursor is changed to the following, then it works:
create procedure testCursor() |
begin
|
declare done, vItem int unsigned; |
declare testCur cursor for |
select x.Item |
from tmpFoo as x |
order by x.Item asc; |
declare continue handler for not found set done = 1; |
|
create temporary table if not exists tmpFoo |
(Id int unsigned primary key auto_increment, |
Item varchar(256) |
) engine = memory;
|
truncate table tmpFoo; |
|
insert into tmpFoo |
(Item)
|
values |
("1"), ("2"); |
|
open testCur; |
curLoop: loop
|
set done = 0; |
fetch testCur into vItem; |
if done = 1 then |
leave curLoop;
|
end if; |
end loop; |
close testCur; |
end |
MariaDB [mbook_dev]> call testCursorCall();
|
+---+
|
| 1 |
|
+---+
|
| 1 |
|
+---+
|
1 row in set (0.001 sec)
|
|
+---+
|
| 2 |
|
+---+
|
| 2 |
|
+---+
|
1 row in set (0.003 sec)
|
|
+---+
|
| 3 |
|
+---+
|
| 3 |
|
+---+
|
1 row in set (0.004 sec)
|
|
+---+
|
| 4 |
|
+---+
|
| 4 |
|
+---+
|
1 row in set (0.005 sec)
|
|
Query OK, 8 rows affected (0.005 sec)
|
Thanks,
-Oli
Thanks! I repeated as described on 11.4,11.7. no errors on 10.5-10.11.
--delimiter //
begin
curloop: loop
leave curloop;
begin
call testcursor();
call testcursor();
call testcursor();
call testcursor();
call testcursorcall()//
Starting MariaDB 11.4.5-MariaDB-debug-log source revision 866a8ea6736d2edc0f6be552d1cdd6810c10d5ab
=================================================================
==1639238==ERROR: AddressSanitizer: heap-use-after-free on address 0x62500016d398 at pc 0x55967de71a41 bp 0x7fe7e18b62c0 sp 0x7fe7e18b62b0
READ of size 8 at 0x62500016d398 thread T5
#0 0x55967de71a40 in Dynamic_array<sp_pcontext*>::elements() const /11.4/src/sql/sql_array.h:237
#1 0x55967de6caca in sp_pcontext::~sp_pcontext() /11.4/src/sql/sp_pcontext.cc:125
#2 0x55967de6caa6 in sp_pcontext::~sp_pcontext() /11.4/src/sql/sp_pcontext.cc:126
#3 0x55967de6caa6 in sp_pcontext::~sp_pcontext() /11.4/src/sql/sp_pcontext.cc:126
#4 0x55967de4c7d7 in sp_head::~sp_head() /11.4/src/sql/sp_head.cc:904
#5 0x55967de4c96d in sp_head::~sp_head() /11.4/src/sql/sp_head.cc:921
#6 0x55967de48163 in sp_head::destroy(sp_head*) /11.4/src/sql/sp_head.cc:536
#7 0x55967de436de in hash_free_sp_head /11.4/src/sql/sp_cache.cc:289
#8 0x55968000e6e5 in my_hash_free_elements /11.4/src/mysys/hash.c:135
#9 0x55968000ea6f in my_hash_reset /11.4/src/mysys/hash.c:178
#10 0x55967de437f7 in sp_cache::clear() /11.4/src/sql/sp_cache.cc:321
#11 0x55967de43897 in Sp_caches::sp_caches_empty() /11.4/src/sql/sp_cache.cc:335
#12 0x55967e0c78ba in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) /11.4/src/sql/sql_parse.cc:2424
#13 0x55967e0c13e4 in do_command(THD*, bool) /11.4/src/sql/sql_parse.cc:1418
#14 0x55967e5be326 in do_handle_one_connection(CONNECT*, bool) /11.4/src/sql/sql_connect.cc:1429
#15 0x55967e5bde79 in handle_one_connection /11.4/src/sql/sql_connect.cc:1341
#16 0x55967f2a028f in pfs_spawn_thread /11.4/src/storage/perfschema/pfs.cc:2201
#17 0x7fe7efa9a608 in start_thread /build/glibc-LcI20x/glibc-2.31/nptl/pthread_create.c:477
#18 0x7fe7ef5d5352 in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x11f352) (BuildId: 0702430aef5fa3dda43986563e9ffcc47efbd75e)
0x62500016d398 is located 664 bytes inside of 8324-byte region [0x62500016d100,0x62500016f184)
freed by thread T5 here:
#0 0x7fe7efff7440 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
#1 0x5596800b0b7a in free_memory /11.4/src/mysys/safemalloc.c:297
#2 0x5596800aff86 in sf_free /11.4/src/mysys/safemalloc.c:203
#3 0x55968007f67c in my_free /11.4/src/mysys/my_malloc.c:221
#4 0x559680050c5c in root_free /11.4/src/mysys/my_alloc.c:77
#5 0x55968005372f in free_root /11.4/src/mysys/my_alloc.c:508
#6 0x55967de69a84 in sp_lex_instr::~sp_lex_instr() /11.4/src/sql/sp_instr.h:420
#7 0x55967e7e6856 in sp_instr_cpush::~sp_instr_cpush() /11.4/src/sql/sp_instr.h:1247
#8 0x55967e7e6883 in sp_instr_cpush::~sp_instr_cpush() /11.4/src/sql/sp_instr.h:1247
#9 0x55967de4c745 in sp_head::~sp_head() /11.4/src/sql/sp_head.cc:902
#10 0x55967de4c96d in sp_head::~sp_head() /11.4/src/sql/sp_head.cc:921
#11 0x55967de48163 in sp_head::destroy(sp_head*) /11.4/src/sql/sp_head.cc:536
#12 0x55967de436de in hash_free_sp_head /11.4/src/sql/sp_cache.cc:289
#13 0x55968000e6e5 in my_hash_free_elements /11.4/src/mysys/hash.c:135
#14 0x55968000ea6f in my_hash_reset /11.4/src/mysys/hash.c:178
#15 0x55967de437f7 in sp_cache::clear() /11.4/src/sql/sp_cache.cc:321
#16 0x55967de43897 in Sp_caches::sp_caches_empty() /11.4/src/sql/sp_cache.cc:335
#17 0x55967e0c78ba in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) /11.4/src/sql/sql_parse.cc:2424
#18 0x55967e0c13e4 in do_command(THD*, bool) /11.4/src/sql/sql_parse.cc:1418
#19 0x55967e5be326 in do_handle_one_connection(CONNECT*, bool) /11.4/src/sql/sql_connect.cc:1429
#20 0x55967e5bde79 in handle_one_connection /11.4/src/sql/sql_connect.cc:1341
#21 0x55967f2a028f in pfs_spawn_thread /11.4/src/storage/perfschema/pfs.cc:2201
#22 0x7fe7efa9a608 in start_thread /build/glibc-LcI20x/glibc-2.31/nptl/pthread_create.c:477
previously allocated by thread T5 here:
#0 0x7fe7efff88ff in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x5596800af94f in sf_malloc /11.4/src/mysys/safemalloc.c:126
#2 0x55968007e762 in my_malloc /11.4/src/mysys/my_malloc.c:93
#3 0x559680050bd4 in root_alloc /11.4/src/mysys/my_alloc.c:66
#4 0x559680051449 in init_alloc_root /11.4/src/mysys/my_alloc.c:175
#5 0x55967e50bd38 in init_sql_alloc(unsigned int, st_mem_root*, unsigned int, unsigned int, unsigned long) /11.4/src/sql/thr_malloc.cc:64
#6 0x55967e7d72d0 in sp_lex_instr::setup_memroot_for_reparsing(sp_head*) /11.4/src/sql/sp_instr.cc:725
#7 0x55967e7d77f6 in sp_lex_instr::parse_expr(THD*, sp_head*, LEX*) /11.4/src/sql/sp_instr.cc:789
#8 0x55967e7d5edd in sp_lex_keeper::validate_lex_and_exec_core(THD*, unsigned int*, bool, sp_lex_instr*) /11.4/src/sql/sp_instr.cc:448
#9 0x55967e7d6592 in sp_lex_keeper::cursor_reset_lex_and_exec_core(THD*, unsigned int*, bool, sp_lex_instr*) /11.4/src/sql/sp_instr.cc:530
#10 0x55967e7df2cf in sp_instr_copen::execute(THD*, unsigned int*) /11.4/src/sql/sp_instr.cc:1834
#11 0x55967de4ed2e in sp_head::execute(THD*, bool) /11.4/src/sql/sp_head.cc:1286
#12 0x55967de5522a in sp_head::execute_procedure(THD*, List<Item>*) /11.4/src/sql/sp_head.cc:2302
#13 0x55967e0cbb40 in do_execute_sp /11.4/src/sql/sql_parse.cc:3069
#14 0x55967e0cd7f2 in Sql_cmd_call::execute(THD*) /11.4/src/sql/sql_parse.cc:3292
#15 0x55967e0e07ce in mysql_execute_command(THD*, bool) /11.4/src/sql/sql_parse.cc:5864
#16 0x55967e7d952c in sp_instr_stmt::exec_core(THD*, unsigned int*) /11.4/src/sql/sp_instr.cc:1050
#17 0x55967e7d4f3e in sp_lex_keeper::reset_lex_and_exec_core(THD*, unsigned int*, bool, sp_instr*, bool) /11.4/src/sql/sp_instr.cc:296
#18 0x55967e7d618d in sp_lex_keeper::validate_lex_and_exec_core(THD*, unsigned int*, bool, sp_lex_instr*) /11.4/src/sql/sp_instr.cc:475
#19 0x55967e7d8c68 in sp_instr_stmt::execute(THD*, unsigned int*) /11.4/src/sql/sp_instr.cc:953
#20 0x55967de4ed2e in sp_head::execute(THD*, bool) /11.4/src/sql/sp_head.cc:1286
#21 0x55967de5522a in sp_head::execute_procedure(THD*, List<Item>*) /11.4/src/sql/sp_head.cc:2302
#22 0x55967e0cbb40 in do_execute_sp /11.4/src/sql/sql_parse.cc:3069
#23 0x55967e0cd7f2 in Sql_cmd_call::execute(THD*) /11.4/src/sql/sql_parse.cc:3292
#24 0x55967e0e07ce in mysql_execute_command(THD*, bool) /11.4/src/sql/sql_parse.cc:5864
#25 0x55967e0edf9d in mysql_parse(THD*, char*, unsigned int, Parser_state*) /11.4/src/sql/sql_parse.cc:7893
#26 0x55967e0c471d in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) /11.4/src/sql/sql_parse.cc:1905
#27 0x55967e0c13e4 in do_command(THD*, bool) /11.4/src/sql/sql_parse.cc:1418
#28 0x55967e5be326 in do_handle_one_connection(CONNECT*, bool) /11.4/src/sql/sql_connect.cc:1429
#29 0x55967e5bde79 in handle_one_connection /11.4/src/sql/sql_connect.cc:1341
Thread T5 created by T0 here:
#0 0x7fe7eff64175 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:208
#1 0x55967f29be4c in my_thread_create /11.4/src/storage/perfschema/my_thread.h:52
#2 0x55967f2a0682 in pfs_spawn_thread_v1 /11.4/src/storage/perfschema/pfs.cc:2252
#3 0x55967dcd10fb in inline_mysql_thread_create /11.4/src/include/mysql/psi/mysql_thread.h:1139
#4 0x55967dce9e92 in create_thread_to_handle_connection(CONNECT*) /11.4/src/sql/mysqld.cc:6183
#5 0x55967dcea4fd in create_new_thread(CONNECT*) /11.4/src/sql/mysqld.cc:6245
#6 0x55967dcea82a in handle_accepted_socket(st_mysql_socket, st_mysql_socket) /11.4/src/sql/mysqld.cc:6307
#7 0x55967dceb527 in handle_connections_sockets() /11.4/src/sql/mysqld.cc:6420
#8 0x55967dce7f06 in run_main_loop /11.4/src/sql/mysqld.cc:5662
#9 0x55967dce96dc in mysqld_main(int, char**) /11.4/src/sql/mysqld.cc:6084
#10 0x55967dcd039c in main /11.4/src/sql/main.cc:34
#11 0x7fe7ef4da082 in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: heap-use-after-free /11.4/src/sql/sql_array.h:237 in Dynamic_array<sp_pcontext*>::elements() const
Shadow bytes around the buggy address:
0x62500016d100: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x62500016d180: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x62500016d200: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x62500016d280: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x62500016d300: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x62500016d380: fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd
0x62500016d400: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x62500016d480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x62500016d500: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x62500016d580: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x62500016d600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==1639238==ABORTING
The weird thing - it is indeed shows the syntax error in the place where there is a problem - while creating a procedure - if I add a space after for (e.g. "declare testcur cursor for select x.item from tmpfoo as x order by x.item asc; ") --then the problem is not reproducible :
MariaDB [test]> call testcursorcall()//
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0,001 sec)
+---+
| 2 |
+---+
| 2 |
+---+
1 row in set (0,001 sec)
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'select x.item
from tmpfoo as x
order by x.item asc' at line 2
MariaDB [test]> create or replace procedure testcursor()
-> begin
-> declare done, vitem int unsigned;
-> declare testcur cursor for select x.item from tmpfoo as x order by x.item asc;
-> declare continue handler for not found set done = 1;
->
->
-> DROP TEMPORARY TABLE IF EXISTS tmpfoo;
-> CREATE TEMPORARY TABLE tmpfoo (id int unsigned PRIMARY KEY auto_increment, item varchar(256) ) engine = memory;
->
->
-> insert into tmpfoo (item) values ("1"), ("2");
->
-> open testcur;
-> curloop: loop
-> set done = 0;
-> fetch testcur into vitem;
-> if done = 1 then
-> leave curloop;
-> end if;
-> end loop;
-> close testcur;
-> end//
Query OK, 0 rows affected (0,019 sec)
MariaDB [test]> call testcursorcall()//
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0,001 sec)
+---+
| 2 |
+---+
| 2 |
+---+
1 row in set (0,002 sec)
+---+
| 3 |
+---+
| 3 |
+---+
1 row in set (0,002 sec)
+---+
| 4 |
+---+
| 4 |
+---+
1 row in set (0,002 sec)
Query OK, 8 rows affected (0,003 sec)