mirror of
https://github.com/MariaDB/server.git
synced 2025-03-30 11:55:31 +02:00
Manual merge from mysql-5.1-bugteam to mysql-trunk-merge.
conflicts: conflict mysys/safemalloc.c conflict sql/mysqld.cc conflict sql/sp.cc conflict sql/sql_lex.cc conflict sql/sql_lex.h conflict sql/sql_parse.cc conflict sql/sql_prepare.cc
This commit is contained in:
commit
f84b3f5c21
18 changed files with 179 additions and 47 deletions
|
@ -39,5 +39,14 @@ a
|
|||
2
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string
|
||||
#
|
||||
CREATE TABLE t1(a BLOB);
|
||||
SET SESSION debug="+d,bug42064_simulate_oom";
|
||||
INSERT INTO t1 VALUES("");
|
||||
Got one of the listed errors
|
||||
SET SESSION debug=DEFAULT;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 5.1 tests
|
||||
#
|
||||
|
|
|
@ -46,6 +46,20 @@ SELECT * FROM t1;
|
|||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1(a BLOB);
|
||||
|
||||
SET SESSION debug="+d,bug42064_simulate_oom";
|
||||
# May fail with either ER_OUT_OF_RESOURCES or EE_OUTOFMEMORY
|
||||
--error ER_OUT_OF_RESOURCES, 5
|
||||
INSERT INTO t1 VALUES("");
|
||||
SET SESSION debug=DEFAULT;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 5.1 tests
|
||||
--echo #
|
||||
|
|
|
@ -154,6 +154,14 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
|
|||
|
||||
DBUG_ASSERT(alloc_root_inited(mem_root));
|
||||
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
||||
{
|
||||
if (mem_root->error_handler)
|
||||
(*mem_root->error_handler)();
|
||||
DBUG_SET("-d,simulate_out_of_memory");
|
||||
DBUG_RETURN((void*) 0); /* purecov: inspected */
|
||||
});
|
||||
|
||||
length+=ALIGN_SIZE(sizeof(USED_MEM));
|
||||
if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME | ME_FATALERROR))))
|
||||
{
|
||||
|
@ -176,6 +184,14 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
|
|||
DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root));
|
||||
DBUG_ASSERT(alloc_root_inited(mem_root));
|
||||
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
||||
{
|
||||
/* Avoid reusing an already allocated block */
|
||||
if (mem_root->error_handler)
|
||||
(*mem_root->error_handler)();
|
||||
DBUG_SET("-d,simulate_out_of_memory");
|
||||
DBUG_RETURN((void*) 0); /* purecov: inspected */
|
||||
});
|
||||
length= ALIGN_SIZE(length);
|
||||
if ((*(prev= &mem_root->free)) != NULL)
|
||||
{
|
||||
|
|
|
@ -31,13 +31,23 @@ void *my_malloc(size_t size, myf my_flags)
|
|||
|
||||
if (!size)
|
||||
size=1; /* Safety */
|
||||
if ((point = (char*)malloc(size)) == NULL)
|
||||
|
||||
point= (char *) malloc(size);
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
||||
{
|
||||
free(point);
|
||||
point= NULL;
|
||||
});
|
||||
|
||||
if (point == NULL)
|
||||
{
|
||||
my_errno=errno;
|
||||
if (my_flags & MY_FAE)
|
||||
error_handler_hook=fatal_error_handler_hook;
|
||||
if (my_flags & (MY_FAE+MY_WME))
|
||||
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH),size);
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
||||
DBUG_SET("-d,simulate_out_of_memory"););
|
||||
if (my_flags & MY_FAE)
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -139,6 +139,11 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags)
|
|||
size + /* size requested */
|
||||
4 + /* overrun mark */
|
||||
sf_malloc_endhunc);
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
||||
{
|
||||
free(irem);
|
||||
irem= NULL;
|
||||
});
|
||||
}
|
||||
/* Check if there isn't anymore memory avaiable */
|
||||
if (!irem)
|
||||
|
@ -159,6 +164,8 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags)
|
|||
}
|
||||
DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'",
|
||||
(long)sf_malloc_max_memory,lineno, filename));
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
||||
DBUG_SET("-d,simulate_out_of_memory"););
|
||||
if (MyFlags & MY_FAE)
|
||||
exit(1);
|
||||
DBUG_RETURN ((void*) 0);
|
||||
|
|
|
@ -1447,7 +1447,10 @@ Event_job_data::execute(THD *thd, bool drop)
|
|||
thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length());
|
||||
|
||||
{
|
||||
Parser_state parser_state(thd, thd->query(), thd->query_length());
|
||||
Parser_state parser_state;
|
||||
if (parser_state.init(thd, thd->query(), thd->query_length()))
|
||||
goto end;
|
||||
|
||||
lex_start(thd);
|
||||
|
||||
if (parse_sql(thd, & parser_state, creation_ctx))
|
||||
|
|
|
@ -3254,9 +3254,12 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
|
|||
thd->table_map_for_update= (table_map)table_map_for_update;
|
||||
|
||||
/* Execute the query (note that we bypass dispatch_command()) */
|
||||
Parser_state parser_state(thd, thd->query(), thd->query_length());
|
||||
mysql_parse(thd, thd->query(), thd->query_length(), &parser_state);
|
||||
log_slow_statement(thd);
|
||||
Parser_state parser_state;
|
||||
if (!parser_state.init(thd, thd->query(), thd->query_length()))
|
||||
{
|
||||
mysql_parse(thd, thd->query(), thd->query_length(), &parser_state);
|
||||
log_slow_statement(thd);
|
||||
}
|
||||
|
||||
/*
|
||||
Resetting the enable_slow_log thd variable.
|
||||
|
|
|
@ -3113,6 +3113,10 @@ void my_message_sql(uint error, const char *str, myf MyFlags)
|
|||
MYSQL_ERROR::WARN_LEVEL_ERROR,
|
||||
str);
|
||||
}
|
||||
|
||||
/* When simulating OOM, skip writing to error log to avoid mtr errors */
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_VOID_RETURN;);
|
||||
|
||||
if (!thd || MyFlags & ME_NOREFRESH)
|
||||
sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
|
||||
DBUG_VOID_RETURN;
|
||||
|
|
|
@ -720,11 +720,18 @@ static sp_head *sp_compile(THD *thd, String *defstr, ulong sql_mode,
|
|||
ha_rows old_select_limit= thd->variables.select_limit;
|
||||
sp_rcontext *old_spcont= thd->spcont;
|
||||
Silence_deprecated_warning warning_handler;
|
||||
Parser_state parser_state;
|
||||
|
||||
thd->variables.sql_mode= sql_mode;
|
||||
thd->variables.select_limit= HA_POS_ERROR;
|
||||
|
||||
Parser_state parser_state(thd, defstr->c_ptr(), defstr->length());
|
||||
if (parser_state.init(thd, defstr->c_ptr(), defstr->length()))
|
||||
{
|
||||
thd->variables.sql_mode= old_sql_mode;
|
||||
thd->variables.select_limit= old_select_limit;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lex_start(thd);
|
||||
thd->push_internal_handler(&warning_handler);
|
||||
thd->spcont= 0;
|
||||
|
|
|
@ -878,6 +878,9 @@ THD::raise_condition_no_handler(uint sql_errno,
|
|||
if (no_warnings_for_error && (level == MYSQL_ERROR::WARN_LEVEL_ERROR))
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
/* When simulating OOM, skip writing to error log to avoid mtr errors */
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_RETURN(NULL););
|
||||
|
||||
cond= warning_info->push_warning(this, sql_errno, sqlstate, level, msg);
|
||||
DBUG_RETURN(cond);
|
||||
}
|
||||
|
|
|
@ -147,20 +147,30 @@ st_parsing_options::reset()
|
|||
Perform initialization of Lex_input_stream instance.
|
||||
|
||||
Basically, a buffer for pre-processed query. This buffer should be large
|
||||
enough to keep multi-statement query. The allocation is done once in the
|
||||
Lex_input_stream constructor in order to prevent memory pollution when
|
||||
enough to keep multi-statement query. The allocation is done once in
|
||||
Lex_input_stream::init() in order to prevent memory pollution when
|
||||
the server is processing large multi-statement queries.
|
||||
|
||||
@todo Check return value of THD::alloc().
|
||||
*/
|
||||
|
||||
Lex_input_stream::Lex_input_stream(THD *thd,
|
||||
const char* buffer,
|
||||
unsigned int length)
|
||||
:m_thd(thd)
|
||||
bool Lex_input_stream::init(THD *thd,
|
||||
const char* buff,
|
||||
unsigned int length)
|
||||
{
|
||||
DBUG_EXECUTE_IF("bug42064_simulate_oom",
|
||||
DBUG_SET("+d,simulate_out_of_memory"););
|
||||
|
||||
m_cpp_buf= (char*) thd->alloc(length + 1);
|
||||
reset(buffer, length);
|
||||
|
||||
DBUG_EXECUTE_IF("bug42064_simulate_oom",
|
||||
DBUG_SET("-d,bug42064_simulate_oom"););
|
||||
|
||||
if (m_cpp_buf == NULL)
|
||||
return TRUE;
|
||||
|
||||
m_thd= thd;
|
||||
reset(buff, length);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -203,8 +213,6 @@ Lex_input_stream::reset(const char *buffer, unsigned int length)
|
|||
m_cpp_ptr= m_cpp_buf;
|
||||
}
|
||||
|
||||
Lex_input_stream::~Lex_input_stream()
|
||||
{}
|
||||
|
||||
/**
|
||||
The operation is called from the parser in order to
|
||||
|
|
|
@ -1378,8 +1378,21 @@ enum enum_comment_state
|
|||
class Lex_input_stream
|
||||
{
|
||||
public:
|
||||
Lex_input_stream(THD *thd, const char* buff, unsigned int length);
|
||||
~Lex_input_stream();
|
||||
Lex_input_stream()
|
||||
{
|
||||
}
|
||||
|
||||
~Lex_input_stream()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Object initializer. Must be called before usage.
|
||||
|
||||
@retval FALSE OK
|
||||
@retval TRUE Error
|
||||
*/
|
||||
bool init(THD *thd, const char *buff, unsigned int length);
|
||||
|
||||
void reset(const char *buff, unsigned int length);
|
||||
|
||||
|
@ -2317,10 +2330,21 @@ public:
|
|||
class Parser_state
|
||||
{
|
||||
public:
|
||||
Parser_state(THD *thd, const char* buff, unsigned int length)
|
||||
: m_lip(thd, buff, length), m_yacc()
|
||||
Parser_state()
|
||||
: m_yacc()
|
||||
{}
|
||||
|
||||
/**
|
||||
Object initializer. Must be called before usage.
|
||||
|
||||
@retval FALSE OK
|
||||
@retval TRUE Error
|
||||
*/
|
||||
bool init(THD *thd, const char *buff, unsigned int length)
|
||||
{
|
||||
return m_lip.init(thd, buff, length);
|
||||
}
|
||||
|
||||
~Parser_state()
|
||||
{}
|
||||
|
||||
|
|
|
@ -559,7 +559,14 @@ static void handle_bootstrap_impl(THD *thd)
|
|||
mode we have only one thread.
|
||||
*/
|
||||
thd->set_time();
|
||||
Parser_state parser_state(thd, thd->query(), length);
|
||||
Parser_state parser_state;
|
||||
if (parser_state.init(thd, thd->query(), length))
|
||||
{
|
||||
thd->protocol->end_statement();
|
||||
bootstrap_error= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
mysql_parse(thd, thd->query(), length, &parser_state);
|
||||
close_thread_tables(thd); // Free tables
|
||||
|
||||
|
@ -1121,7 +1128,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
#if defined(ENABLED_PROFILING)
|
||||
thd->profiling.set_query_source(thd->query(), thd->query_length());
|
||||
#endif
|
||||
Parser_state parser_state(thd, thd->query(), thd->query_length());
|
||||
Parser_state parser_state;
|
||||
if (parser_state.init(thd, thd->query(), thd->query_length()))
|
||||
break;
|
||||
|
||||
mysql_parse(thd, thd->query(), thd->query_length(), &parser_state);
|
||||
|
||||
|
@ -5907,14 +5916,17 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
|
|||
bool error= 0;
|
||||
DBUG_ENTER("mysql_test_parse_for_slave");
|
||||
|
||||
Parser_state parser_state(thd, inBuf, length);
|
||||
lex_start(thd);
|
||||
mysql_reset_thd_for_next_command(thd);
|
||||
Parser_state parser_state;
|
||||
if (!(error= parser_state.init(thd, inBuf, length)))
|
||||
{
|
||||
lex_start(thd);
|
||||
mysql_reset_thd_for_next_command(thd);
|
||||
|
||||
if (!parse_sql(thd, & parser_state, NULL) &&
|
||||
all_tables_not_ok(thd, lex->select_lex.table_list.first))
|
||||
error= 1; /* Ignore question */
|
||||
thd->end_statement();
|
||||
if (!parse_sql(thd, & parser_state, NULL) &&
|
||||
all_tables_not_ok(thd, lex->select_lex.table_list.first))
|
||||
error= 1; /* Ignore question */
|
||||
thd->end_statement();
|
||||
}
|
||||
thd->cleanup_after_query();
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
|
|
@ -4199,7 +4199,9 @@ bool mysql_unpack_partition(THD *thd,
|
|||
|
||||
thd->variables.character_set_client= system_charset_info;
|
||||
|
||||
Parser_state parser_state(thd, part_buf, part_info_len);
|
||||
Parser_state parser_state;
|
||||
if (parser_state.init(thd, part_buf, part_info_len))
|
||||
goto end;
|
||||
|
||||
if (init_lex_with_single_table(thd, table, &lex))
|
||||
goto end;
|
||||
|
|
|
@ -2944,7 +2944,9 @@ Execute_sql_statement::execute_server_code(THD *thd)
|
|||
if (alloc_query(thd, m_sql_text.str, m_sql_text.length))
|
||||
return TRUE;
|
||||
|
||||
Parser_state parser_state(thd, thd->query(), thd->query_length());
|
||||
Parser_state parser_state;
|
||||
if (parser_state.init(thd, thd->query(), thd->query_length()))
|
||||
return TRUE;
|
||||
|
||||
parser_state.m_lip.multi_statements= FALSE;
|
||||
lex_start(thd);
|
||||
|
@ -3184,14 +3186,17 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
|||
old_stmt_arena= thd->stmt_arena;
|
||||
thd->stmt_arena= this;
|
||||
|
||||
Parser_state parser_state(thd, thd->query(), thd->query_length());
|
||||
parser_state.m_lip.stmt_prepare_mode= TRUE;
|
||||
parser_state.m_lip.multi_statements= FALSE;
|
||||
lex_start(thd);
|
||||
Parser_state parser_state;
|
||||
if (!parser_state.init(thd, thd->query(), thd->query_length()))
|
||||
{
|
||||
parser_state.m_lip.stmt_prepare_mode= TRUE;
|
||||
parser_state.m_lip.multi_statements= FALSE;
|
||||
lex_start(thd);
|
||||
|
||||
error= parse_sql(thd, & parser_state, NULL) ||
|
||||
thd->is_error() ||
|
||||
init_param_array(this);
|
||||
error= parse_sql(thd, & parser_state, NULL) ||
|
||||
thd->is_error() ||
|
||||
init_param_array(this);
|
||||
}
|
||||
|
||||
lex->set_trg_event_type_for_tables();
|
||||
|
||||
|
|
|
@ -1327,9 +1327,9 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
|||
|
||||
thd->variables.sql_mode= (ulong)*trg_sql_mode;
|
||||
|
||||
Parser_state parser_state(thd,
|
||||
trg_create_str->str,
|
||||
trg_create_str->length);
|
||||
Parser_state parser_state;
|
||||
if (parser_state.init(thd, trg_create_str->str, trg_create_str->length))
|
||||
goto err_with_lex_cleanup;
|
||||
|
||||
Trigger_creation_ctx *creation_ctx=
|
||||
Trigger_creation_ctx::create(thd,
|
||||
|
|
|
@ -1216,9 +1216,10 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
|||
char old_db_buf[NAME_LEN+1];
|
||||
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
|
||||
bool dbchanged;
|
||||
Parser_state parser_state(thd,
|
||||
table->select_stmt.str,
|
||||
table->select_stmt.length);
|
||||
Parser_state parser_state;
|
||||
if (parser_state.init(thd, table->select_stmt.str,
|
||||
table->select_stmt.length))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
Use view db name as thread default database, in order to ensure
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
extern "C" {
|
||||
void sql_alloc_error_handler(void)
|
||||
{
|
||||
sql_print_error("%s", ER(ER_OUT_OF_RESOURCES));
|
||||
|
||||
THD *thd= current_thd;
|
||||
if (thd)
|
||||
{
|
||||
|
@ -53,6 +51,12 @@ extern "C" {
|
|||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip writing to the error log to avoid mtr complaints */
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory", return;);
|
||||
|
||||
sql_print_error("%s", ER(ER_OUT_OF_RESOURCES));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue