[MDEV-12378] Crash if a FETCH statement produces warnings Created: 2017-03-28  Updated: 2020-04-21

Status: Stalled
Project: MariaDB Server
Component/s: Stored routines
Affects Version/s: 10.2
Fix Version/s: 10.2

Type: Bug Priority: Major
Reporter: Alexander Barkov Assignee: Oleksandr Byelkin
Resolution: Unresolved Votes: 0
Labels: None

Issue Links:
Relates
relates to MDEV-12377 truncation in FETCH reports a wrong r... Open
Sprint: 10.2.7-1

 Description   

The script that is reported in MDEV-12377 causes a crash in 10.2.
This only happens if FETCH causes warnings. If I modify the data in the below script not to have the trailing 'x' character in the column t1.b, the crash goes away.

SET sql_mode=default;
DROP TABLE IF EXISTS t1;
DROP PROCEDURE IF EXISTS p1;
 
CREATE TABLE t1 (a INT, b VARCHAR(10));
INSERT INTO t1 VALUES (10,'11x');
INSERT INTO t1 VALUES (10,'12x');
 
DELIMITER $$;
CREATE PROCEDURE p1()
BEGIN
  DECLARE cur1 CURSOR FOR SELECT b FROM t1;
    BEGIN
    DECLARE res int;
    OPEN cur1;
    FETCH cur1 INTO res;
    CLOSE cur1;
  END;
END;
$$
DELIMITER ;$$
 
CALL p1();
SHOW WARNINGS;

This is a stack trace:

#0  0x00007ffff5994a28 in raise () from /lib64/libc.so.6
#1  0x00007ffff599662a in abort () from /lib64/libc.so.6
#2  0x00007ffff598d227 in __assert_fail_base () from /lib64/libc.so.6
#3  0x00007ffff598d2d2 in __assert_fail () from /lib64/libc.so.6
#4  0x0000555555acbc73 in Diagnostics_area::set_ok_status (
    this=0x7ffec6c1b058, affected_rows=0, last_insert_id=0, message=0x0)
    at /home/bar/maria-git/server.10.2/sql/sql_error.cc:380
#5  0x0000555555a7f855 in my_ok (thd=0x7ffec6c16070, affected_rows=0, id=0, 
    message=0x0) at /home/bar/maria-git/server.10.2/sql/sql_class.h:4319
#6  0x0000555555af67ab in do_execute_sp (thd=0x7ffec6c16070, sp=0x7ffec6d80088)
    at /home/bar/maria-git/server.10.2/sql/sql_parse.cc:2891
#7  0x0000555555aff7a1 in mysql_execute_command (thd=0x7ffec6c16070)
    at /home/bar/maria-git/server.10.2/sql/sql_parse.cc:5771
#8  0x0000555555b05c29 in mysql_parse (thd=0x7ffec6c16070, 
    rawbuf=0x7ffec6c63088 "CALL p1()", length=9, parser_state=0x7ffff7f2dd20, 
    is_com_multi=false, is_next_command=false)
    at /home/bar/maria-git/server.10.2/sql/sql_parse.cc:7858



 Comments   
Comment by Oleksandr Byelkin [ 2017-04-03 ]

It is an attempt to send OK when error was send (or at leas diagnostic area set to error state).

Comment by Oleksandr Byelkin [ 2017-04-03 ]

Conversion cause error level warning, which cause set error in Diagnistics_area in THD::raise_condition().

Question is why it set ERROR when there is no real error send to client.

Comment by Oleksandr Byelkin [ 2017-04-03 ]

It looks like fetch do not process error state to the end in strict tables mode.

Comment by Oleksandr Byelkin [ 2017-04-03 ]

SET @save_sql_mode=@@sql_mode;
SET sql_mode="STRICT_TRANS_TABLES";
 
CREATE TABLE t1 (a INT, b VARCHAR(10));
INSERT INTO t1 VALUES (10,'11x');
INSERT INTO t1 VALUES (10,'12x');
 
DELIMITER $$;
CREATE PROCEDURE p1()
BEGIN
  DECLARE cur1 CURSOR FOR SELECT b FROM t1;
    BEGIN
    DECLARE res int;
    OPEN cur1;
    FETCH cur1 INTO res;
    CLOSE cur1;
  END;
END;
$$
DELIMITER ;$$
 
--error WARN_DATA_TRUNCATED
CALL p1();
 
drop procedure p1;
drop table t1;
SET sql_mode=@save_sql_mode;

Comment by Oleksandr Byelkin [ 2017-04-03 ]

10.1 return error as it should by above test suite.

Comment by Oleksandr Byelkin [ 2017-04-03 ]

in 10.1 thd->killed set to KILL_BAD_DATA when in 10.2 it is not

Comment by Oleksandr Byelkin [ 2017-04-03 ]

The assignment of KILL_BAD_DATA was removed in this cset:
commit 5f0c31f928338e8a6ffde098b7ffd3d1a8b02903
Author: Monty <monty@mariadb.org>
Date: Tue Jan 10 18:28:24 2017 +0200

MDEV-11597 Assertion when doing select from virtual column with impossible value

  • Changed error handlers interface so that they can change error level in
    the handler
  • Give warnings and errors when calculating virtual columns
  • On insert/update error is fatal in strict mode.
  • SELECT and DELETE will only give a warning if a virtual field generates an error
  • Added VCOL_UPDATE_FOR_DELETE and VCOL_UPDATE_INDEX_FOR_REPLACE to be able to
    easily detect in update_virtual_fields() if we should use an error
    handler to mask errors or not.
Comment by Oleksandr Byelkin [ 2017-04-03 ]

That assigning KILL_BAD_DATA to thd->killed was transfer of an error in this case

Attempt to add error check of save_to_field of sp_eval_expr() lead to many problem and do not fix the bug.

Comment by Oleksandr Byelkin [ 2017-09-13 ]

How the error was transferred in 10.1:

  1. THD::raise_condition set THD->killed to KILL_BAD_DATA in case of WARN_LEVEL_WARN and abort on warning (!!! why bad data? probably no other cases)
  2. Also error was returnrd by storing functions and it traveled "up" until reach Materialized_cursor::fetch which just ignore all result codes, so it assign 0 or NULL and act as if was not an error (if make it reacting on error it will lead to failed tests)
  3. sp_cursor::fetch is also on the stack and also do not react on thd->is_error() (if react it will lead to crashes)
  4. sp_head::execute run error handlers, there is no handlers found so error_status is not set
  5. sp_head::execute checks thd->killed and go out execution loop
  6. sp_head::execute thd->killed and set error_status

Here is stacktrace for reference:

#0  THD::raise_condition (this=0x5555578b2d20, sql_errno=1265, sqlstate=0x5555563a0829 "01000", level=Sql_condition::WARN_LEVEL_ERROR, msg=0x7ffff062a860 "Data truncated for column 'res' at row 3") at /home/sanja/maria/git/test-server/sql/sql_class.cc:1292
#1  0x00005555559ff3ec in push_warning (thd=0x5555578b2d20, level=Sql_condition::WARN_LEVEL_WARN, code=1265, msg=0x7ffff062a860 "Data truncated for column 'res' at row 3") at /home/sanja/maria/git/test-server/sql/sql_error.cc:752
#2  0x00005555559ff59e in push_warning_printf (thd=0x5555578b2d20, level=Sql_condition::WARN_LEVEL_WARN, code=1265, format=0x5555576a8458 "Data truncated for column '%s' at row %lu") at /home/sanja/maria/git/test-server/sql/sql_error.cc:787
#3  0x0000555555c51b1e in Field::set_warning (this=0x7fffe00090a8, level=Sql_condition::WARN_LEVEL_WARN, code=1265, cut_increment=1) at /home/sanja/maria/git/test-server/sql/field.cc:10775
#4  0x0000555555c5309d in Field::set_warning (this=0x7fffe00090a8, code=1265, cuted_increment=1) at /home/sanja/maria/git/test-server/sql/field.h:1230
#5  0x0000555555c336e6 in Field_num::check_edom_and_important_data_truncation (this=0x7fffe00090a8, type=0x555556438799 "integer", edom=false, cs=0x555556bf3080 <my_charset_latin1>, str=0x7fffe0165b82 "11x", length=3, end=0x7fffe0165b84 "x") at /home/sanja/maria/git/test-server/sql/field.cc:1500
#6  0x0000555555c33760 in Field_num::check_edom_and_truncation (this=0x7fffe00090a8, type=0x555556438799 "integer", edom=false, cs=0x555556bf3080 <my_charset_latin1>, str=0x7fffe0165b82 "11x", length=3, end=0x7fffe0165b84 "x") at /home/sanja/maria/git/test-server/sql/field.cc:1513
#7  0x0000555555c5348f in Field_num::check_int (this=0x7fffe00090a8, cs=0x555556bf3080 <my_charset_latin1>, str=0x7fffe0165b82 "11x", length=3, int_end=0x7fffe0165b84 "x", error=0) at /home/sanja/maria/git/test-server/sql/field.h:1488
#8  0x0000555555c338b5 in Field_num::get_int (this=0x7fffe00090a8, cs=0x555556bf3080 <my_charset_latin1>, from=0x7fffe0165b82 "11x", len=3, rnd=0x7ffff062af50, unsigned_max=4294967295, signed_min=-2147483648, signed_max=2147483647) at /home/sanja/maria/git/test-server/sql/field.cc:1577
#9  0x0000555555c3b6b6 in Field_long::store (this=0x7fffe00090a8, from=0x7fffe0165b82 "11x", len=3, cs=0x555556bf3080 <my_charset_latin1>) at /home/sanja/maria/git/test-server/sql/field.cc:4045
#10 0x0000555555c5b5ed in field_conv_incompatible (to=0x7fffe00090a8, from=0x7fffe0165aa8) at /home/sanja/maria/git/test-server/sql/field_conv.cc:950
#11 0x0000555555c5b0e1 in field_conv (to=0x7fffe00090a8, from=0x7fffe0165aa8) at /home/sanja/maria/git/test-server/sql/field_conv.cc:877
#12 0x0000555555c849c8 in save_field_in_field (from=0x7fffe0165aa8, null_value=0x7fffe0165c4a, to=0x7fffe00090a8, no_conversions=false) at /home/sanja/maria/git/test-server/sql/item.cc:5920
#13 0x0000555555c84c3b in Item_field::save_in_field (this=0x7fffe0165bd8, to=0x7fffe00090a8, no_conversions=false) at /home/sanja/maria/git/test-server/sql/item.cc:5976
#14 0x0000555555dac766 in sp_eval_expr (thd=0x5555578b2d20, result_field=0x7fffe00090a8, expr_item_ptr=0x7ffff062b4d0) at /home/sanja/maria/git/test-server/sql/sp_head.cc:449
#15 0x0000555555db97b0 in sp_rcontext::set_variable (this=0x7fffe0007f30, thd=0x5555578b2d20, field=0x7fffe00090a8, value=0x7ffff062b4d0) at /home/sanja/maria/git/test-server/sql/sp_rcontext.cc:377
#16 0x00005555559f4f44 in sp_rcontext::set_variable (this=0x7fffe0007f30, thd=0x5555578b2d20, var_idx=0, value=0x7ffff062b4d0) at /home/sanja/maria/git/test-server/sql/sp_rcontext.h:201
#17 0x0000555555db9e11 in sp_cursor::Select_fetch_into_spvars::send_data (this=0x7fffe0009290, items=...) at /home/sanja/maria/git/test-server/sql/sp_rcontext.cc:557
#18 0x0000555555dc991c in Materialized_cursor::fetch (this=0x7fffe017bb38, num_rows=1) at /home/sanja/maria/git/test-server/sql/sql_cursor.cc:359
#19 0x0000555555db9ca4 in sp_cursor::fetch (this=0x7fffe0009288, thd=0x5555578b2d20, vars=0x7fffe0160d60) at /home/sanja/maria/git/test-server/sql/sp_rcontext.cc:508
#20 0x0000555555db4ab6 in sp_instr_cfetch::execute (this=0x7fffe0160d28, thd=0x5555578b2d20, nextp=0x7ffff062b654) at /home/sanja/maria/git/test-server/sql/sp_head.cc:3908
#21 0x0000555555dae8ef in sp_head::execute (this=0x7fffe015f1f8, thd=0x5555578b2d20, merge_da_on_success=true) at /home/sanja/maria/git/test-server/sql/sp_head.cc:1316
#22 0x0000555555db0795 in sp_head::execute_procedure (this=0x7fffe015f1f8, thd=0x5555578b2d20, args=0x5555578b7490) at /home/sanja/maria/git/test-server/sql/sp_head.cc:2112
#23 0x0000555555a26334 in do_execute_sp (thd=0x5555578b2d20, sp=0x7fffe015f1f8) at /home/sanja/maria/git/test-server/sql/sql_parse.cc:2413
...

Comment by Oleksandr Byelkin [ 2017-09-13 ]

After removing KILL_BAD_DATA set (the only set statement of it) in 10.2 above procedure do not work: we forget error first, but then check of thd->kill do not interrupt.

If the idea of removing KILL_BAD_DATA was put everything on error handlers and put nothing around them why we do nothing if error handler not found but error is still exists?

If assigning KILL_BAD_DATA and KILL_BAD_DATA_HARD are not presend in the code why its checks and definitions are not removed?

Comment by Alice Sherepa [ 2020-04-21 ]

The test does not crash on current 10.2 (36bddacf6b9177587) -10.5, but returns "Data truncated for column 'res' at row 3" --MDEV-12377

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