Bug #119572 Contribution by Tencent: Prepared statement reprepare with optimizer trace crashes in decimal2string
Submitted: 18 Dec 2025 3:42 Modified: 21 Dec 2025 9:24
Reporter: jarne yang Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Prepared statements Severity:S6 (Debug Builds)
Version:8.0,8.4,9.7.0 OS:Any
Assigned to: CPU Architecture:Any

[18 Dec 2025 3:42] jarne yang
Description:
During reprepare, copy_parameter_types() calls Item_param::copy_param_actual_type(), which tries to zero the DECIMAL buffer but uses memset(decimal_value.buf, 0, DECIMAL_BUFF_LENGTH);, i.e., only 9 bytes. A DECIMAL buffer holds 9 dec1 values (9×4 bytes). For parameters whose precision/scale spans beyond the second dec1 (e.g., DECIMAL(16,10)), decimal2string() walks into the uninitialized dec1, reads a negative value, and div_by_pow10 asserts x >= 0. If the precision/scale uses only the first dec1 or two, the garbage isn’t read, so no crash—hence the conditional nature.

How to repeat:
In debug version:

SET optimizer_trace="enabled=on";
CREATE TABLE t1 (dc2 DECIMAL(16,10));
INSERT INTO t1 VALUES (1.1111111111);

PREPARE s FROM 'SELECT dc2+? FROM t1';
SET @a=1.12345678901234;
EXECUTE s USING @a;

-- trigger reprepare
ALTER TABLE t1 COMMENT='force reprepare';

EXECUTE s USING @a;  -- crash here

Suggested fix:
Zero the entire DECIMAL buffer in Item_param::copy_param_actual_type():
memset(decimal_value.buf, 0, DECIMAL_BUFF_LENGTH * sizeof(decimal_digit_t));

This prevents uninitialized dec1 from being read during optimizer-trace printing in reprepare.
[21 Dec 2025 9:24] MySQL Verification Team
Thank you,  verified as described!

2025-12-21T09:23:04.199283Z 0 [System] [MY-010931] [Server] /usr/global/support/sbester/my/x86_64/debug/mysql-9.7.0-linux-x86_64/bin/mysqld-debug: ready for connections. Version: '9.7.0-debug'  socket: '/tmp/mysql.sock'  port: 3333  (Built on 18 December 2025, commit e46d2b3f077c0a2f465d97e3ddbbf663a71a44e5 with gcc (GCC) 11.5.0 20240719 (Red Hat 11.5.0-5.0.1)).
[New Thread 0x7f4bcf9ff640 (LWP 906376)]
[New Thread 0x7f4bf43fe640 (LWP 906377)]
[New Thread 0x7f4bf33fe640 (LWP 906407)]
mysqld-debug: /usr/global/support/sbester/mysql-trunk/mysys/decimal.cc:181: dec1 div_by_pow10(dec1, int): Assertion `x >= 0' failed.

Thread 50 "connection" received signal SIGABRT, Aborted.
[Switching to Thread 0x7f4bf43fe640 (LWP 906377)]
0x00007f4c21a1106c in __pthread_kill_implementation () from /lib64/libc.so.6
(gdb) bt
#0  0x00007f4c21a1106c in __pthread_kill_implementation () from /lib64/libc.so.6
#1  0x00007f4c219c3b86 in raise () from /lib64/libc.so.6
#2  0x00007f4c219ad873 in abort () from /lib64/libc.so.6
#3  0x00007f4c219ad79b in __assert_fail_base.cold () from /lib64/libc.so.6
#4  0x00007f4c219bc8c6 in __assert_fail () from /lib64/libc.so.6
#5  0x0000000004c12757 in div_by_pow10 (x=-1886417152, p=4) at /usr/global/support/sbester/mysql-trunk/mysys/decimal.cc:181
#6  0x0000000004c136a3 in decimal2string (from=0x7f4bce572c80, to=0x7f4bf43f80cb "", to_len=0x7f4bf43f7fc8, fixed_precision=0, fixed_decimals=0) at /usr/global/support/sbester/mysql-trunk/mysys/decimal.cc:625
#7  0x00000000036a49f1 in my_decimal2string (mask=30, d=0x7f4bce572c80, fixed_prec=0, fixed_dec=0, str=0x7f4bf43f80a0) at /usr/global/support/sbester/mysql-trunk/sql-common/my_decimal.cc:145
#8  0x00000000036a5515 in my_decimal2string (mask=30, d=0x7f4bce572c80, str=0x7f4bf43f80a0) at /usr/global/support/sbester/mysql-trunk/sql-common/my_decimal.h:292
#9  0x00000000039126af in Item_param::query_val_str (this=0x7f4bce572ba0, thd=0x7f4bce40b000, str=0x7f4bf43f80a0) at /usr/global/support/sbester/mysql-trunk/sql/item.cc:4741
#10 0x0000000003913eb2 in Item_param::print (this=0x7f4bce572ba0, thd=0x7f4bce40b000, str=0x7f4bf43f8370, query_type=(QT_TO_SYSTEM_CHARSET | QT_SHOW_SELECT_NUMBER | QT_NO_DEFAULT_DB)) at /usr/global/support/sbester/mysql-trunk/sql/item.cc:5101
#11 0x00000000039a351c in Item_func::print_op (this=0x7f4bce572d58, thd=0x7f4bce40b000, str=0x7f4bf43f8370, query_type=(QT_TO_SYSTEM_CHARSET | QT_SHOW_SELECT_NUMBER | QT_NO_DEFAULT_DB)) at /usr/global/support/sbester/mysql-trunk/sql/item_func.cc:809
#12 0x00000000039cabee in Item_num_op::print (this=0x7f4bce572d58, thd=0x7f4bce40b000, str=0x7f4bf43f8370, query_type=(QT_TO_SYSTEM_CHARSET | QT_SHOW_SELECT_NUMBER | QT_NO_DEFAULT_DB)) at /usr/global/support/sbester/mysql-trunk/sql/item_func.h:1024
#13 0x00000000039051f9 in Item::print_item_w_name (this=0x7f4bce572d58, thd=0x7f4bce40b000, str=0x7f4bf43f8370, query_type=(QT_TO_SYSTEM_CHARSET | QT_SHOW_SELECT_NUMBER | QT_NO_DEFAULT_DB)) at /usr/global/support/sbester/mysql-trunk/sql/item.cc:857
#14 0x000000000342ea8b in Query_block::print_item_list (this=0x7f4bce5726d8, thd=0x7f4bce40b000, str=0x7f4bf43f8370, query_type=(QT_TO_SYSTEM_CHARSET | QT_SHOW_SELECT_NUMBER | QT_NO_DEFAULT_DB)) at /usr/global/support/sbester/mysql-trunk/sql/sql_lex.cc:3353
#15 0x000000000342daf7 in Query_block::print_query_block (this=0x7f4bce5726d8, thd=0x7f4bce40b000, str=0x7f4bf43f8370, query_type=(QT_TO_SYSTEM_CHARSET | QT_SHOW_SELECT_NUMBER | QT_NO_DEFAULT_DB)) at /usr/global/support/sbester/mysql-trunk/sql/sql_lex.cc:3089
#16 0x000000000342d9f7 in Query_block::print (this=0x7f4bce5726d8, thd=0x7f4bce40b000, str=0x7f4bf43f8370, query_type=(QT_TO_SYSTEM_CHARSET | QT_SHOW_SELECT_NUMBER | QT_NO_DEFAULT_DB)) at /usr/global/support/sbester/mysql-trunk/sql/sql_lex.cc:3073
#17 0x0000000003bb40e5 in opt_trace_print_expanded_query (thd=0x7f4bce40b000, query_block=0x7f4bce5726d8, trace_object=0x7f4bf43f87e0) at /usr/global/support/sbester/mysql-trunk/sql/opt_trace2server.cc:269
#18 0x00000000034d47f0 in Query_block::prepare (this=0x7f4bce5726d8, thd=0x7f4bce40b000, insert_field_list=0x0) at /usr/global/support/sbester/mysql-trunk/sql/sql_resolver.cc:483
#19 0x000000000350f8e9 in Sql_cmd_select::prepare_inner (this=0x7f4bce1c36c8, thd=0x7f4bce40b000) at /usr/global/support/sbester/mysql-trunk/sql/sql_select.cc:672
#20 0x000000000350f30d in Sql_cmd_dml::prepare (this=0x7f4bce1c36c8, thd=0x7f4bce40b000) at /usr/global/support/sbester/mysql-trunk/sql/sql_select.cc:586
#21 0x00000000034c22e1 in Prepared_statement::prepare_query (this=0x7f4bce4e7500, thd=0x7f4bce40b000) at /usr/global/support/sbester/mysql-trunk/sql/sql_prepare.cc:1398
#22 0x00000000034c58b9 in Prepared_statement::prepare (this=0x7f4bce4e7500, thd=0x7f4bce40b000, query_str=0x7f4bce4609e8 "SELECT dc2+? FROM t1", query_length=20, orig_param_array=0x7f4bce410f00) at /usr/global/support/sbester/mysql-trunk/sql/sql_prepare.cc:2599
#23 0x00000000034c74ec in Prepared_statement::reprepare (this=0x7f4bce4e7500, thd=0x7f4bce40b000) at /usr/global/support/sbester/mysql-trunk/sql/sql_prepare.cc:3373
#24 0x00000000034c69c2 in Prepared_statement::execute_loop (this=0x7f4bce4e7500, thd=0x7f4bce40b000, expanded_query=0x7f4bf43f95e0, open_cursor=false) at /usr/global/support/sbester/mysql-trunk/sql/sql_prepare.cc:3108
#25 0x00000000034c3bd6 in mysql_sql_stmt_execute (thd=0x7f4bce40b000) at /usr/global/support/sbester/mysql-trunk/sql/sql_prepare.cc:1958
#26 0x000000000347de2c in mysql_execute_command (thd=0x7f4bce40b000, first_level=true) at /usr/global/support/sbester/mysql-trunk/sql/sql_parse.cc:3487
#27 0x0000000003484253 in dispatch_sql_command (thd=0x7f4bce40b000, parser_state=0x7f4bf43fb010, is_retry=false) at /usr/global/support/sbester/mysql-trunk/sql/sql_parse.cc:5433
#28 0x000000000347a37d in dispatch_command (thd=0x7f4bce40b000, com_data=0x7f4bf43fc180, command=COM_QUERY) at /usr/global/support/sbester/mysql-trunk/sql/sql_parse.cc:2152
#29 0x0000000003478298 in do_command (thd=0x7f4bce40b000) at /usr/global/support/sbester/mysql-trunk/sql/sql_parse.cc:1491
#30 0x00000000036d5044 in handle_connection (arg=0x7f4bd149cf80) at /usr/global/support/sbester/mysql-trunk/sql/conn_handler/connection_handler_per_thread.cc:304
#31 0x0000000005527d72 in pfs_spawn_thread (arg=0x7f4c2143c820) at /usr/global/support/sbester/mysql-trunk/storage/perfschema/pfs.cc:3067
#32 0x00007f4c21a0f2fa in start_thread () from /lib64/libc.so.6
#33 0x00007f4c21a94440 in clone3 () from /lib64/libc.so.6
[21 Dec 2025 9:30] MySQL Verification Team
mysqld-debug: Version: '8.0.44-debug'  (Built on 22 October 2025,  
with gcc (GCC) 11.5.0 20240719 (Red Hat 11.5.0-5.0.1)).
mysqld-debug: ./mysqlcom-8.0.44/strings/decimal.cc:175: dec1 div_by_pow10(dec1, int): Assertion `x >= 0' failed.
2025-12-21T09:27:10Z UTC - mysqld got signal 6 ;

....

mysqld-debug: ready for connections. Version: '8.4.7-debug'  socket: '/tmp/mysql.sock'  port: 3306  (Built on 22 October 2025,  with gcc (GCC) 11.5.0 20240719 (Red Hat 11.5.0-5.0.1)).
mysqld-debug: /export/home/tmp/sbester/git/mysqlcom-8.4.7/mysys/decimal.cc:178: dec1 div_by_pow10(dec1, int): Assertion `x >= 0' failed.
2025-12-21T09:30:17Z UTC - mysqld got signal 6 ;