From e73e7bb9aec760edf7b142ac57696d44da149d86 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 14 Jul 2008 15:41:30 -0600 Subject: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) The crash was caused by freeing the internal parser stack during the parser execution. This occured only for complex stored procedures, after reallocating the parser stack using my_yyoverflow(), with the following C call stack: - MYSQLparse() - any rule calling sp_head::restore_lex() - lex_end() - x_free(lex->yacc_yyss), xfree(lex->yacc_yyvs) The root cause is the implementation of stored procedures, which breaks the assumption from 4.1 that there is only one LEX structure per parser call. The solution is to separate the LEX structure into: - attributes that represent a statement (the current LEX structure), - attributes that relate to the syntax parser itself (Yacc_state), so that parsing multiple statements in stored programs can create multiple LEX structures while not changing the unique Yacc_state. Now, Yacc_state and the existing Lex_input_stream are aggregated into Parser_state, a structure that represent the complete state of the (Lexical + Syntax) parser. mysql-test/r/parser_stack.result: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) mysql-test/t/parser_stack.test: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sp.cc: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sp_head.cc: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sql_class.cc: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sql_class.h: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sql_lex.cc: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sql_lex.h: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sql_parse.cc: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sql_prepare.cc: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sql_trigger.cc: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sql_view.cc: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) sql/sql_yacc.yy: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) --- sql/sql_lex.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'sql/sql_lex.cc') diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a1bfc3edc6c..0cf7c11b447 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -192,7 +192,6 @@ void lex_start(THD *thd) lex->select_lex.order_list.empty(); lex->select_lex.udf_list.empty(); lex->current_select= &lex->select_lex; - lex->yacc_yyss=lex->yacc_yyvs=0; lex->sql_command= lex->orig_sql_command= SQLCOM_END; lex->duplicates= DUP_ERROR; lex->ignore= 0; @@ -210,11 +209,16 @@ void lex_start(THD *thd) void lex_end(LEX *lex) { - DBUG_ENTER("lex_end"); - DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex)); - x_free(lex->yacc_yyss); - x_free(lex->yacc_yyvs); - DBUG_VOID_RETURN; + /* Empty in 5.0, non empty in 5.1 */ +} + +Yacc_state::~Yacc_state() +{ + if (yacc_yyss) + { + x_free(yacc_yyss); + x_free(yacc_yyvs); + } } @@ -531,7 +535,7 @@ int MYSQLlex(void *arg, void *yythd) uint length; enum my_lex_states state; THD *thd= (THD *)yythd; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; LEX *lex= thd->lex; YYSTYPE *yylval=(YYSTYPE*) arg; CHARSET_INFO *cs= thd->charset(); @@ -1781,7 +1785,7 @@ void Query_tables_list::destroy_query_tables_list() */ st_lex::st_lex() - :result(0), yacc_yyss(0), yacc_yyvs(0), + :result(0), sql_command(SQLCOM_END) { reset_query_tables_list(TRUE); -- cgit v1.2.1 From f48b42e77657dd2e27380201631fd0f137863b85 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Wed, 8 Oct 2008 02:34:00 +0500 Subject: Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while ``FLUSH TABLES WITH READ LOCK'' Concurrent execution of 1) multitable update with a NATURAL/USING join and 2) a such query as "FLUSH TABLES WITH READ LOCK" or "ALTER TABLE" of updating table led to a server crash. The mysql_multi_update_prepare() function call is optimized to lock updating tables only, so it postpones locking to the last, and if locking fails, it does cleanup of modified syntax structures and repeats a query analysis. However, that cleanup procedure was incomplete for NATURAL/USING join syntax data: 1) some Field_item items pointed into freed table structures, and 2) the TABLE_LIST::join_columns fields was not reset. Major change: short-living Field *Natural_join_column::table_field has been replaced with long-living Item*. mysql-test/r/lock_multi.result: Added test case for bug #38691. mysql-test/t/lock_multi.test: Added test case for bug #38691. sql/item.cc: Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while ``FLUSH TABLES WITH READ LOCK'' The Item_field constructor has been modified to allocate and copy original database/table/field names always (not during PS preparation/1st execution only), because an initialization of Item_field items with a pointer to short-living Field structures is a common practice. sql/sql_base.cc: Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while ``FLUSH TABLES WITH READ LOCK'' 1) Type adjustment for Natural_join_column::table_field (Field to Item_field); 2) The setup_natural_join_row_types function has been updated to take into account new first_natural_join_processing flag to skip unnecessary reinitialization of Natural_join_column::join_columns during table reopening after lock_tables() failure (like the 'first_execution' flag for PS). sql/sql_lex.cc: Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while ``FLUSH TABLES WITH READ LOCK'' Initialization of the new st_select_lex::first_natural_join_processing flag has been added. sql/sql_lex.h: Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while ``FLUSH TABLES WITH READ LOCK'' The st_select_lex::first_natural_join_processing flag has been added to skip unnecessary rebuilding of NATURAL/USING JOIN structures during table reopening after lock_tables failure. sql/sql_update.cc: Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while ``FLUSH TABLES WITH READ LOCK'' Extra cleanup calls have been added to reset Natural_join_column::table_field items. sql/table.cc: Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while ``FLUSH TABLES WITH READ LOCK'' Type adjustment for Natural_join_column::table_field (Field to Item_field). sql/table.h: Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while ``FLUSH TABLES WITH READ LOCK'' Type of the Natural_join_column::table_field field has been changed from Field that points into short-living TABLE memory to long-living Item_field that can be linked to (fixed) reopened table. --- sql/sql_lex.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'sql/sql_lex.cc') diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0cf7c11b447..ba9c0e93134 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1205,6 +1205,7 @@ void st_select_lex::init_query() subquery_in_having= explicit_limit= 0; is_item_list_lookup= 0; first_execution= 1; + first_natural_join_processing= 1; first_cond_optimization= 1; parsing_place= NO_MATTER; exclude_from_table_unique_test= no_wrap_view_item= FALSE; -- cgit v1.2.1 From 3ad228d7fba6fa2e5b98569f798583b8f8b90db9 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 15 Oct 2008 18:34:51 -0300 Subject: Bug#37075: offset of limit clause might be truncated on 32-bits server w/o big tables The problem is that the offset argument of the limit clause might be truncated on a 32-bits server built without big tables support. The truncation was happening because the original 64-bits long argument was being cast to a 32-bits (ha_rows) offset counter. The solution is to check if the conversing resulted in value truncation and if so, the offset is set to the maximum possible value that can fit on the type. mysql-test/r/limit.result: Add test case result for Bug#37075 mysql-test/t/limit.test: Add test case for Bug#37075 sql/sql_lex.cc: Check for truncation of the offset value. If value was truncated, set to the maximum possible value. --- sql/sql_lex.cc | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'sql/sql_lex.cc') diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ba9c0e93134..71aa80b8170 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2041,12 +2041,26 @@ st_lex::copy_db_to(char **p_db, uint *p_db_length) const void st_select_lex_unit::set_limit(SELECT_LEX *sl) { ha_rows select_limit_val; + ulonglong val; DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare()); - select_limit_val= (ha_rows)(sl->select_limit ? sl->select_limit->val_uint() : - HA_POS_ERROR); - offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() : - ULL(0)); + val= sl->select_limit ? sl->select_limit->val_uint() : HA_POS_ERROR; + select_limit_val= (ha_rows)val; +#ifndef BIG_TABLES + /* + Check for overflow : ha_rows can be smaller then ulonglong if + BIG_TABLES is off. + */ + if (val != (ulonglong)select_limit_val) + select_limit_val= HA_POS_ERROR; +#endif + val= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0); + offset_limit_cnt= (ha_rows)val; +#ifndef BIG_TABLES + /* Check for truncation. */ + if (val != (ulonglong)offset_limit_cnt) + offset_limit_cnt= HA_POS_ERROR; +#endif select_limit_cnt= select_limit_val + offset_limit_cnt; if (select_limit_cnt < select_limit_val) select_limit_cnt= HA_POS_ERROR; // no limit -- cgit v1.2.1