1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-34388: Stack overflow on Alpine Linux

page_is_corrupted(): Do not allocate the buffers from stack,
but from the heap, in xb_fil_cur_open().

row_quiesce_write_cfg(): Issue one type of message when we
fail to create the .cfg file.

update_statistics_for_table(), read_statistics_for_table(),
delete_statistics_for_table(), rename_table_in_stat_tables():
Use a common stack buffer for Index_stat, Column_stat, Table_stat.

ha_connect::FileExists(): Invoke push_warning_printf() so that
we can avoid allocating a buffer for snprintf().

translog_init_with_table(): Do not duplicate TRANSLOG_PAGE_SIZE_BUFF.

Let us also globally enable the GCC 4.4 and clang 3.0 option
-Wframe-larger-than=16384 to reduce the possibility of introducing
such stack overflow in the future.  For RocksDB and Mroonga we relax
these limits.

Reviewed by: Vladislav Lesin
This commit is contained in:
Marko Mäkelä
2025-05-20 17:27:05 +03:00
parent 2350295643
commit 82d7419e06
21 changed files with 130 additions and 119 deletions

View File

@@ -2785,9 +2785,6 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
After having been updated the statistical system tables are closed.
*/
/* Stack usage 20248 from clang */
PRAGMA_DISABLE_CHECK_STACK_FRAME
int update_statistics_for_table(THD *thd, TABLE *table)
{
TABLE_LIST tables[STATISTICS_TABLES];
@@ -2816,9 +2813,13 @@ int update_statistics_for_table(THD *thd, TABLE *table)
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
char statbuf[sizeof(Index_stat)];
static_assert(sizeof(statbuf) >= sizeof(Table_stat), "");
static_assert(sizeof(statbuf) >= sizeof(Column_stat), "");
/* Update the statistical table table_stats */
stat_table= tables[TABLE_STAT].table;
Table_stat table_stat(stat_table, table);
Table_stat &table_stat= *new(statbuf) Table_stat(stat_table, table);
restore_record(stat_table, s->default_values);
table_stat.set_key_fields();
err= table_stat.update_stat();
@@ -2827,7 +2828,7 @@ int update_statistics_for_table(THD *thd, TABLE *table)
/* Update the statistical table colum_stats */
stat_table= tables[COLUMN_STAT].table;
Column_stat column_stat(stat_table, table);
Column_stat &column_stat= *new(statbuf) Column_stat(stat_table, table);
for (Field **field_ptr= table->field; *field_ptr; field_ptr++)
{
Field *table_field= *field_ptr;
@@ -2844,7 +2845,7 @@ int update_statistics_for_table(THD *thd, TABLE *table)
stat_table= tables[INDEX_STAT].table;
uint key;
key_map::Iterator it(table->keys_in_use_for_query);
Index_stat index_stat(stat_table, table);
Index_stat &index_stat= *new(statbuf) Index_stat(stat_table, table);
while ((key= it++) != key_map::Iterator::BITMAP_END)
{
@@ -2872,7 +2873,6 @@ int update_statistics_for_table(THD *thd, TABLE *table)
new_trans.restore_old_transaction();
DBUG_RETURN(rc);
}
PRAGMA_REENABLE_CHECK_STACK_FRAME
/**
@@ -2957,7 +2957,10 @@ read_statistics_for_table(THD *thd, TABLE *table,
/* Read statistics from the statistical table table_stats */
Table_statistics *read_stats= new_stats_cb->table_stats;
stat_table= stat_tables[TABLE_STAT].table;
Table_stat table_stat(stat_table, table);
char statbuf[sizeof(Index_stat)];
static_assert(sizeof(statbuf) >= sizeof(Table_stat), "");
static_assert(sizeof(statbuf) >= sizeof(Column_stat), "");
Table_stat &table_stat= *new(statbuf) Table_stat(stat_table, table);
table_stat.set_key_fields();
if (table_stat.get_stat_values(new_stats_cb->table_stats))
new_stats_cb->stats_available|= TABLE_STAT_TABLE;
@@ -2965,7 +2968,7 @@ read_statistics_for_table(THD *thd, TABLE *table,
/* Read statistics from the statistical table column_stats */
stat_table= stat_tables[COLUMN_STAT].table;
ulong total_hist_size= 0;
Column_stat column_stat(stat_table, table);
Column_stat &column_stat= *new(statbuf) Column_stat(stat_table, table);
Column_statistics *column_statistics= new_stats_cb->table_stats->column_stats;
found= 0;
for (field_ptr= table_share->field;
@@ -2990,7 +2993,7 @@ read_statistics_for_table(THD *thd, TABLE *table,
/* Read statistics from the statistical table index_stats */
stat_table= stat_tables[INDEX_STAT].table;
Index_stat index_stat(stat_table, table);
Index_stat &index_stat= *new(statbuf) Index_stat(stat_table, table);
Index_statistics *index_statistics= new_stats_cb->table_stats->index_stats;
for (key_info= table_share->key_info,
key_info_end= key_info + table_share->keys;
@@ -3285,9 +3288,6 @@ end:
The function is called when executing the statement DROP TABLE 'tab'.
*/
/* Stack size 20248 with clang */
PRAGMA_DISABLE_CHECK_STACK_FRAME
int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db,
const LEX_CSTRING *tab)
{
@@ -3311,7 +3311,10 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db,
/* Delete statistics on table from the statistical table index_stats */
stat_table= tables[INDEX_STAT].table;
Index_stat index_stat(stat_table, db, tab);
char statbuf[sizeof(Index_stat)];
static_assert(sizeof(statbuf) >= sizeof(Table_stat), "");
static_assert(sizeof(statbuf) >= sizeof(Column_stat), "");
Index_stat &index_stat= *new(statbuf) Index_stat(stat_table, db, tab);
index_stat.set_full_table_name();
while (index_stat.find_next_stat_for_prefix(2))
{
@@ -3322,7 +3325,7 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db,
/* Delete statistics on table from the statistical table column_stats */
stat_table= tables[COLUMN_STAT].table;
Column_stat column_stat(stat_table, db, tab);
Column_stat &column_stat= *new(statbuf) Column_stat(stat_table, db, tab);
column_stat.set_full_table_name();
while (column_stat.find_next_stat_for_prefix(2))
{
@@ -3333,7 +3336,7 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db,
/* Delete statistics on table from the statistical table table_stats */
stat_table= tables[TABLE_STAT].table;
Table_stat table_stat(stat_table, db, tab);
Table_stat &table_stat= *new(statbuf) Table_stat(stat_table, db, tab);
table_stat.set_key_fields();
if (table_stat.find_stat())
{
@@ -3356,7 +3359,6 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db,
new_trans.restore_old_transaction();
DBUG_RETURN(rc);
}
PRAGMA_REENABLE_CHECK_STACK_FRAME
/**
@@ -3725,7 +3727,6 @@ int rename_indexes_in_stat_table(THD *thd, TABLE *tab,
int rc= 0;
uint duplicate_counter= 0;
List_iterator<Alter_info::RENAME_INDEX_STAT_PARAMS> it(*indexes);
Alter_info::RENAME_INDEX_STAT_PARAMS *index;
char tmp_name_buffer[32];
LEX_CSTRING tmp_name= {tmp_name_buffer, 0};
DBUG_ENTER("rename_indexes_in_stat_tables");
@@ -3746,15 +3747,16 @@ int rename_indexes_in_stat_table(THD *thd, TABLE *tab,
/* Rename index in the statistical table index_stat */
stat_table= tables.table;
char statbuf[sizeof(Index_stat)];
/*
Loop over all indexes and rename to new name or temp name in case of
conflicts
*/
while ((index= it++))
while (Alter_info::RENAME_INDEX_STAT_PARAMS *index= it++)
{
Index_stat index_stat(stat_table, tab);
Index_stat &index_stat= *new(statbuf) Index_stat(stat_table, tab);
uint found= 0;
/* We have to make a loop as one index may have many entries */
@@ -3822,12 +3824,11 @@ int rename_indexes_in_stat_table(THD *thd, TABLE *tab,
the final name.
*/
Alter_info::RENAME_INDEX_STAT_PARAMS *index;
it.rewind();
Index_stat index_stat(stat_table, tab);
Index_stat &index_stat= *new(statbuf) Index_stat(stat_table, tab);
stat_table->file->ha_index_init(index_stat.stat_key_idx, 0);
while ((index= it++))
while (Alter_info::RENAME_INDEX_STAT_PARAMS *index= it++)
{
int err __attribute__((unused));
@@ -3901,9 +3902,6 @@ int rename_indexes_in_stat_table(THD *thd, TABLE *tab,
The function is called when executing any statement that renames a table
*/
/* Stack size 20968 with clang */
PRAGMA_DISABLE_CHECK_STACK_FRAME
int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db,
const LEX_CSTRING *tab,
const LEX_CSTRING *new_db,
@@ -3928,7 +3926,11 @@ int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db,
/* Rename table in the statistical table index_stats */
stat_table= tables[INDEX_STAT].table;
Index_stat index_stat(stat_table, db, tab);
char statbuf[sizeof(Index_stat)];
static_assert(sizeof(statbuf) >= sizeof(Table_stat), "");
static_assert(sizeof(statbuf) >= sizeof(Column_stat), "");
Index_stat &index_stat= *new(statbuf) Index_stat(stat_table, db, tab);
index_stat.set_full_table_name();
Stat_table_write_iter index_iter(&index_stat);
@@ -3945,7 +3947,7 @@ int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db,
/* Rename table in the statistical table column_stats */
stat_table= tables[COLUMN_STAT].table;
Column_stat column_stat(stat_table, db, tab);
Column_stat &column_stat= *new(statbuf) Column_stat(stat_table, db, tab);
column_stat.set_full_table_name();
Stat_table_write_iter column_iter(&column_stat);
if (column_iter.init(2))
@@ -3961,7 +3963,7 @@ int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db,
/* Rename table in the statistical table table_stats */
stat_table= tables[TABLE_STAT].table;
Table_stat table_stat(stat_table, db, tab);
Table_stat &table_stat= *new(statbuf) Table_stat(stat_table, db, tab);
table_stat.set_key_fields();
if (table_stat.find_stat())
{
@@ -3981,7 +3983,6 @@ int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db,
new_trans.restore_old_transaction();
DBUG_RETURN(rc);
}
PRAGMA_REENABLE_CHECK_STACK_FRAME
/**