Commit bb681dbc authored by unknown's avatar unknown

Bug #31153 calling stored procedure crashes server if available memory is low

When the server was out of memory it crashed because of invalid memory access.

This patch adds detection for failed memory allocations and make the server
output a proper error message.


sql/mysqld.cc:
  Don't try to push_warning from within push_warning. It will cause a recursion
  until the stack is consumed.
  
  If my_net_init fails (for example: because of OOM) the temporary vio object 
  might have been attached to the thd object already. This will cause a double
  free on the vio object when the thd object is deleted later on and the server
  will crash.
sql/sp_head.cc:
  Added check for out-of-memory on a 'new' operation.
  Refactored reset_lex method to return a error state code instead of void.
  Initialize the mem-root with init_sql_alloc to get a basic error handler for
  memory allocation problems. This alone won't prevent the server from crashing,
  NULL pointers have to be accounted for as well.
sql/sp_head.h:
  Use the throw() clause in operator new, to indicate to the compiler that
  memory allocation can fail and return NULL, so that the compiler should
  generate code to check for NULL before invoking C++ constructors, to be
  crash safe.
sql/sql_base.cc:
  Use init_sql_alloc to get basic out-of-memory error handling.
sql/sql_lex.h:
  Use the throw() clause in operator new, to indicate to the compiler that
  memory allocation can fail and return NULL, so that the compiler should
  generate code to check for NULL before invoking C++ constructors, to be
  crash safe.
sql/sql_prepare.cc:
  Use init_sql_alloc to get basic out-of-memory error handling.
sql/sql_yacc.yy:
  Check for memory allocation failures where it matters.
parent f4b6234c
...@@ -2489,7 +2489,12 @@ static int my_message_sql(uint error, const char *str, myf MyFlags) ...@@ -2489,7 +2489,12 @@ static int my_message_sql(uint error, const char *str, myf MyFlags)
thd->query_error= 1; // needed to catch query errors during replication thd->query_error= 1; // needed to catch query errors during replication
if (!thd->no_warnings_for_error) if (!thd->no_warnings_for_error)
{
thd->no_warnings_for_error= TRUE;
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str); push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
thd->no_warnings_for_error= FALSE;
}
/* /*
thd->lex->current_select == 0 if lex structure is not inited thd->lex->current_select == 0 if lex structure is not inited
(not query command (COM_QUERY)) (not query command (COM_QUERY))
...@@ -4295,7 +4300,12 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) ...@@ -4295,7 +4300,12 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
sock == unix_sock ? VIO_LOCALHOST: 0)) || sock == unix_sock ? VIO_LOCALHOST: 0)) ||
my_net_init(&thd->net,vio_tmp)) my_net_init(&thd->net,vio_tmp))
{ {
if (vio_tmp) /*
Only delete the temporary vio if we didn't already attach it to the
NET object. The destructor in THD will delete any initialized net
structure.
*/
if (vio_tmp && thd->net.vio != vio_tmp)
vio_delete(vio_tmp); vio_delete(vio_tmp);
else else
{ {
......
...@@ -411,14 +411,16 @@ check_routine_name(LEX_STRING ident) ...@@ -411,14 +411,16 @@ check_routine_name(LEX_STRING ident)
*/ */
void * void *
sp_head::operator new(size_t size) sp_head::operator new(size_t size) throw()
{ {
DBUG_ENTER("sp_head::operator new"); DBUG_ENTER("sp_head::operator new");
MEM_ROOT own_root; MEM_ROOT own_root;
sp_head *sp; sp_head *sp;
init_alloc_root(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); init_sql_alloc(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
sp= (sp_head *) alloc_root(&own_root, size); sp= (sp_head *) alloc_root(&own_root, size);
if (sp == NULL)
return NULL;
sp->main_mem_root= own_root; sp->main_mem_root= own_root;
DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root)); DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root));
DBUG_RETURN(sp); DBUG_RETURN(sp);
...@@ -429,6 +431,10 @@ sp_head::operator delete(void *ptr, size_t size) ...@@ -429,6 +431,10 @@ sp_head::operator delete(void *ptr, size_t size)
{ {
DBUG_ENTER("sp_head::operator delete"); DBUG_ENTER("sp_head::operator delete");
MEM_ROOT own_root; MEM_ROOT own_root;
if (ptr == NULL)
DBUG_VOID_RETURN;
sp_head *sp= (sp_head *) ptr; sp_head *sp= (sp_head *) ptr;
/* Make a copy of main_mem_root as free_root will free the sp */ /* Make a copy of main_mem_root as free_root will free the sp */
...@@ -472,6 +478,9 @@ sp_head::init(LEX *lex) ...@@ -472,6 +478,9 @@ sp_head::init(LEX *lex)
lex->spcont= m_pcont= new sp_pcontext(); lex->spcont= m_pcont= new sp_pcontext();
if (!lex->spcont)
DBUG_VOID_RETURN;
/* /*
Altough trg_table_fields list is used only in triggers we init for all Altough trg_table_fields list is used only in triggers we init for all
types of stored procedures to simplify reset_lex()/restore_lex() code. types of stored procedures to simplify reset_lex()/restore_lex() code.
...@@ -973,7 +982,7 @@ sp_head::execute(THD *thd) ...@@ -973,7 +982,7 @@ sp_head::execute(THD *thd)
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* init per-instruction memroot */ /* init per-instruction memroot */
init_alloc_root(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0); init_sql_alloc(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
DBUG_ASSERT(!(m_flags & IS_INVOKED)); DBUG_ASSERT(!(m_flags & IS_INVOKED));
m_flags|= IS_INVOKED; m_flags|= IS_INVOKED;
...@@ -1795,16 +1804,29 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) ...@@ -1795,16 +1804,29 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
} }
// Reset lex during parsing, before we parse a sub statement. /**
void @brief Reset lex during parsing, before we parse a sub statement.
@param thd Thread handler.
@return Error state
@retval true An error occurred.
@retval false Success.
*/
bool
sp_head::reset_lex(THD *thd) sp_head::reset_lex(THD *thd)
{ {
DBUG_ENTER("sp_head::reset_lex"); DBUG_ENTER("sp_head::reset_lex");
LEX *sublex; LEX *sublex;
LEX *oldlex= thd->lex; LEX *oldlex= thd->lex;
sublex= new (thd->mem_root)st_lex_local;
if (sublex == 0)
DBUG_RETURN(TRUE);
thd->lex= sublex;
(void)m_lex.push_front(oldlex); (void)m_lex.push_front(oldlex);
thd->lex= sublex= new st_lex;
/* Reset most stuff. */ /* Reset most stuff. */
lex_start(thd); lex_start(thd);
...@@ -1827,7 +1849,7 @@ sp_head::reset_lex(THD *thd) ...@@ -1827,7 +1849,7 @@ sp_head::reset_lex(THD *thd)
sublex->interval_list.empty(); sublex->interval_list.empty();
sublex->type= 0; sublex->type= 0;
DBUG_VOID_RETURN; DBUG_RETURN(FALSE);
} }
// Restore lex during parsing, after we have parsed a sub statement. // Restore lex during parsing, after we have parsed a sub statement.
...@@ -3703,7 +3725,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex, ...@@ -3703,7 +3725,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST)))) if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
{ {
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(TABLE_LIST)); thd->fatal_error();
return NULL; return NULL;
} }
table->db_length= strlen(db); table->db_length= strlen(db);
......
...@@ -191,10 +191,10 @@ public: ...@@ -191,10 +191,10 @@ public:
Security_context m_security_ctx; Security_context m_security_ctx;
static void * static void *
operator new(size_t size); operator new(size_t size) throw ();
static void static void
operator delete(void *ptr, size_t size); operator delete(void *ptr, size_t size) throw ();
sp_head(); sp_head();
...@@ -254,7 +254,7 @@ public: ...@@ -254,7 +254,7 @@ public:
} }
// Resets lex in 'thd' and keeps a copy of the old one. // Resets lex in 'thd' and keeps a copy of the old one.
void bool
reset_lex(THD *thd); reset_lex(THD *thd);
// Restores lex in 'thd' from our copy, but keeps some status from the // Restores lex in 'thd' from our copy, but keeps some status from the
......
...@@ -80,7 +80,6 @@ bool Prelock_error_handler::safely_trapped_errors() ...@@ -80,7 +80,6 @@ bool Prelock_error_handler::safely_trapped_errors()
return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); return ((m_handled_errors > 0) && (m_unhandled_errors == 0));
} }
TABLE *unused_tables; /* Used by mysql_test */ TABLE *unused_tables; /* Used by mysql_test */
HASH open_cache; /* Used by mysql_test */ HASH open_cache; /* Used by mysql_test */
...@@ -2643,7 +2642,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) ...@@ -2643,7 +2642,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
temporary mem_root for new .frm parsing. temporary mem_root for new .frm parsing.
TODO: variables for size TODO: variables for size
*/ */
init_alloc_root(&new_frm_mem, 8024, 8024); init_sql_alloc(&new_frm_mem, 8024, 8024);
thd->current_tablenr= 0; thd->current_tablenr= 0;
restart: restart:
......
...@@ -1283,11 +1283,11 @@ typedef struct st_lex : public Query_tables_list ...@@ -1283,11 +1283,11 @@ typedef struct st_lex : public Query_tables_list
struct st_lex_local: public st_lex struct st_lex_local: public st_lex
{ {
static void *operator new(size_t size) static void *operator new(size_t size) throw()
{ {
return (void*) sql_alloc((uint) size); return (void*) sql_alloc((uint) size);
} }
static void *operator new(size_t size, MEM_ROOT *mem_root) static void *operator new(size_t size, MEM_ROOT *mem_root) throw()
{ {
return (void*) alloc_root(mem_root, (uint) size); return (void*) alloc_root(mem_root, (uint) size);
} }
...@@ -1303,3 +1303,4 @@ extern void lex_start(THD *thd); ...@@ -1303,3 +1303,4 @@ extern void lex_start(THD *thd);
extern void lex_end(LEX *lex); extern void lex_end(LEX *lex);
extern int MYSQLlex(void *arg, void *yythd); extern int MYSQLlex(void *arg, void *yythd);
extern char *skip_rear_comments(CHARSET_INFO *cs, char *begin, char *end); extern char *skip_rear_comments(CHARSET_INFO *cs, char *begin, char *end);
...@@ -2659,7 +2659,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg) ...@@ -2659,7 +2659,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg)
last_errno(0), last_errno(0),
flags((uint) IS_IN_USE) flags((uint) IS_IN_USE)
{ {
init_alloc_root(&main_mem_root, thd_arg->variables.query_alloc_block_size, init_sql_alloc(&main_mem_root, thd_arg->variables.query_alloc_block_size,
thd_arg->variables.query_prealloc_size); thd_arg->variables.query_prealloc_size);
*last_error= '\0'; *last_error= '\0';
} }
......
...@@ -1628,6 +1628,8 @@ create_function_tail: ...@@ -1628,6 +1628,8 @@ create_function_tail:
} }
/* Order is important here: new - reset - init */ /* Order is important here: new - reset - init */
sp= new sp_head(); sp= new sp_head();
if (sp == NULL)
MYSQL_YYABORT;
sp->reset_thd_mem_root(thd); sp->reset_thd_mem_root(thd);
sp->init(lex); sp->init(lex);
sp->init_sp_name(thd, lex->spname); sp->init_sp_name(thd, lex->spname);
...@@ -1929,7 +1931,8 @@ sp_decl: ...@@ -1929,7 +1931,8 @@ sp_decl:
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sphead->reset_lex(YYTHD); if (lex->sphead->reset_lex(YYTHD))
MYSQL_YYABORT;
lex->spcont->declare_var_boundary($2); lex->spcont->declare_var_boundary($2);
} }
type type
...@@ -1937,6 +1940,10 @@ sp_decl: ...@@ -1937,6 +1940,10 @@ sp_decl:
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_pcontext *pctx= lex->spcont; sp_pcontext *pctx= lex->spcont;
if (pctx == 0)
{
MYSQL_YYABORT;
}
uint num_vars= pctx->context_var_count(); uint num_vars= pctx->context_var_count();
enum enum_field_types var_type= (enum enum_field_types) $4; enum enum_field_types var_type= (enum enum_field_types) $4;
Item *dflt_value_item= $5; Item *dflt_value_item= $5;
...@@ -2022,12 +2029,15 @@ sp_decl: ...@@ -2022,12 +2029,15 @@ sp_decl:
{ {
i= new sp_instr_hreturn(sp->instructions(), ctx, i= new sp_instr_hreturn(sp->instructions(), ctx,
ctx->current_var_count()); ctx->current_var_count());
if (i == NULL )
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
} }
else else
{ /* EXIT or UNDO handler, just jump to the end of the block */ { /* EXIT or UNDO handler, just jump to the end of the block */
i= new sp_instr_hreturn(sp->instructions(), ctx, 0); i= new sp_instr_hreturn(sp->instructions(), ctx, 0);
if (i == NULL)
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */ sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */
} }
...@@ -2055,6 +2065,8 @@ sp_decl: ...@@ -2055,6 +2065,8 @@ sp_decl:
} }
i= new sp_instr_cpush(sp->instructions(), ctx, $5, i= new sp_instr_cpush(sp->instructions(), ctx, $5,
ctx->current_cursor_count()); ctx->current_cursor_count());
if ( i==NULL )
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
ctx->push_cursor(&$2); ctx->push_cursor(&$2);
$$.vars= $$.conds= $$.hndlrs= 0; $$.vars= $$.conds= $$.hndlrs= 0;
...@@ -2064,7 +2076,8 @@ sp_decl: ...@@ -2064,7 +2076,8 @@ sp_decl:
sp_cursor_stmt: sp_cursor_stmt:
{ {
Lex->sphead->reset_lex(YYTHD); if(Lex->sphead->reset_lex(YYTHD))
MYSQL_YYABORT;
/* We use statement here just be able to get a better /* We use statement here just be able to get a better
error message. Using 'select' works too, but will then error message. Using 'select' works too, but will then
...@@ -2230,7 +2243,8 @@ sp_proc_stmt: ...@@ -2230,7 +2243,8 @@ sp_proc_stmt:
LEX *lex= thd->lex; LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip; Lex_input_stream *lip= thd->m_lip;
lex->sphead->reset_lex(thd); if (lex->sphead->reset_lex(thd))
MYSQL_YYABORT;
lex->sphead->m_tmp_query= lip->tok_start; lex->sphead->m_tmp_query= lip->tok_start;
} }
statement statement
...@@ -2255,9 +2269,10 @@ sp_proc_stmt: ...@@ -2255,9 +2269,10 @@ sp_proc_stmt:
lex->var_list.is_empty()); lex->var_list.is_empty());
if (lex->sql_command != SQLCOM_SET_OPTION) if (lex->sql_command != SQLCOM_SET_OPTION)
{ {
sp_instr_stmt *i=new sp_instr_stmt(sp->instructions(), sp_instr_stmt *i= new sp_instr_stmt(sp->instructions(),
lex->spcont, lex); lex->spcont, lex);
if (i == NULL)
MYSQL_YYABORT;
/* /*
Extract the query statement from the tokenizer. The Extract the query statement from the tokenizer. The
end is either lex->ptr, if there was no lookahead, end is either lex->ptr, if there was no lookahead,
...@@ -2275,7 +2290,10 @@ sp_proc_stmt: ...@@ -2275,7 +2290,10 @@ sp_proc_stmt:
sp->restore_lex(thd); sp->restore_lex(thd);
} }
| RETURN_SYM | RETURN_SYM
{ Lex->sphead->reset_lex(YYTHD); } {
if(Lex->sphead->reset_lex(YYTHD))
MYSQL_YYABORT;
}
expr expr
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -2292,6 +2310,8 @@ sp_proc_stmt: ...@@ -2292,6 +2310,8 @@ sp_proc_stmt:
i= new sp_instr_freturn(sp->instructions(), lex->spcont, $3, i= new sp_instr_freturn(sp->instructions(), lex->spcont, $3,
sp->m_return_field_def.sql_type, lex); sp->m_return_field_def.sql_type, lex);
if (i == NULL)
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
sp->m_flags|= sp_head::HAS_RETURN; sp->m_flags|= sp_head::HAS_RETURN;
} }
...@@ -2334,12 +2354,23 @@ sp_proc_stmt: ...@@ -2334,12 +2354,23 @@ sp_proc_stmt:
uint n; uint n;
n= ctx->diff_handlers(lab->ctx, TRUE); /* Exclusive the dest. */ n= ctx->diff_handlers(lab->ctx, TRUE); /* Exclusive the dest. */
if (n) if (n)
sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); {
sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n);
if (hpop == NULL)
MYSQL_YYABORT;
sp->add_instr(hpop);
}
n= ctx->diff_cursors(lab->ctx, TRUE); /* Exclusive the dest. */ n= ctx->diff_cursors(lab->ctx, TRUE); /* Exclusive the dest. */
if (n) if (n)
sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); {
sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n);
sp->add_instr(cpop);
}
i= new sp_instr_jump(ip, ctx); i= new sp_instr_jump(ip, ctx);
if (i == NULL)
MYSQL_YYABORT;
sp->push_backpatch(i, lab); /* Jumping forward */ sp->push_backpatch(i, lab); /* Jumping forward */
sp->add_instr(i); sp->add_instr(i);
} }
...@@ -2364,11 +2395,19 @@ sp_proc_stmt: ...@@ -2364,11 +2395,19 @@ sp_proc_stmt:
n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */ n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
if (n) if (n)
sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); {
sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n);
sp->add_instr(hpop);
}
n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */ n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
if (n) if (n)
sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); {
sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n);
sp->add_instr(cpop);
}
i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
if (i == NULL)
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
} }
} }
...@@ -2385,6 +2424,8 @@ sp_proc_stmt: ...@@ -2385,6 +2424,8 @@ sp_proc_stmt:
MYSQL_YYABORT; MYSQL_YYABORT;
} }
i= new sp_instr_copen(sp->instructions(), lex->spcont, offset); i= new sp_instr_copen(sp->instructions(), lex->spcont, offset);
if (i == NULL)
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
} }
| FETCH_SYM sp_opt_fetch_noise ident INTO | FETCH_SYM sp_opt_fetch_noise ident INTO
...@@ -2400,6 +2441,8 @@ sp_proc_stmt: ...@@ -2400,6 +2441,8 @@ sp_proc_stmt:
MYSQL_YYABORT; MYSQL_YYABORT;
} }
i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset); i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
if (i == NULL)
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
} }
sp_fetch_list sp_fetch_list
...@@ -2417,6 +2460,8 @@ sp_proc_stmt: ...@@ -2417,6 +2460,8 @@ sp_proc_stmt:
MYSQL_YYABORT; MYSQL_YYABORT;
} }
i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset); i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset);
if (i == NULL)
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
} }
; ;
...@@ -2472,7 +2517,10 @@ sp_fetch_list: ...@@ -2472,7 +2517,10 @@ sp_fetch_list:
; ;
sp_if: sp_if:
{ Lex->sphead->reset_lex(YYTHD); } {
if (Lex->sphead->reset_lex(YYTHD))
MYSQL_YYABORT;
}
expr THEN_SYM expr THEN_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -2481,7 +2529,8 @@ sp_if: ...@@ -2481,7 +2529,8 @@ sp_if:
uint ip= sp->instructions(); uint ip= sp->instructions();
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx, sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx,
$2, lex); $2, lex);
if (i == NULL)
MYSQL_YYABORT;
sp->push_backpatch(i, ctx->push_label((char *)"", 0)); sp->push_backpatch(i, ctx->push_label((char *)"", 0));
sp->add_cont_backpatch(i); sp->add_cont_backpatch(i);
sp->add_instr(i); sp->add_instr(i);
...@@ -2493,7 +2542,8 @@ sp_if: ...@@ -2493,7 +2542,8 @@ sp_if:
sp_pcontext *ctx= Lex->spcont; sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions(); uint ip= sp->instructions();
sp_instr_jump *i = new sp_instr_jump(ip, ctx); sp_instr_jump *i = new sp_instr_jump(ip, ctx);
if (i == NULL)
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
sp->backpatch(ctx->pop_label()); sp->backpatch(ctx->pop_label());
sp->push_backpatch(i, ctx->push_label((char *)"", 0)); sp->push_backpatch(i, ctx->push_label((char *)"", 0));
...@@ -2522,7 +2572,8 @@ simple_case_stmt: ...@@ -2522,7 +2572,8 @@ simple_case_stmt:
{ {
LEX *lex= Lex; LEX *lex= Lex;
case_stmt_action_case(lex); case_stmt_action_case(lex);
lex->sphead->reset_lex(YYTHD); /* For expr $3 */ if (lex->sphead->reset_lex(YYTHD))
MYSQL_YYABORT; /* For expr $3 */
} }
expr expr
{ {
...@@ -2571,7 +2622,8 @@ searched_when_clause_list: ...@@ -2571,7 +2622,8 @@ searched_when_clause_list:
simple_when_clause: simple_when_clause:
WHEN_SYM WHEN_SYM
{ {
Lex->sphead->reset_lex(YYTHD); /* For expr $3 */ if (Lex->sphead->reset_lex(YYTHD))
MYSQL_YYABORT; /* For expr $3 */
} }
expr expr
{ {
...@@ -2592,7 +2644,8 @@ simple_when_clause: ...@@ -2592,7 +2644,8 @@ simple_when_clause:
searched_when_clause: searched_when_clause:
WHEN_SYM WHEN_SYM
{ {
Lex->sphead->reset_lex(YYTHD); /* For expr $3 */ if (Lex->sphead->reset_lex(YYTHD))
MYSQL_YYABORT; /* For expr $3 */
} }
expr expr
{ {
...@@ -2616,6 +2669,8 @@ else_clause_opt: ...@@ -2616,6 +2669,8 @@ else_clause_opt:
uint ip= sp->instructions(); uint ip= sp->instructions();
sp_instr_error *i= new sp_instr_error(ip, lex->spcont, sp_instr_error *i= new sp_instr_error(ip, lex->spcont,
ER_SP_CASE_NOT_FOUND); ER_SP_CASE_NOT_FOUND);
if (i == NULL)
MYSQL_YYABORT;
sp->add_instr(i); sp->add_instr(i);
} }
| ELSE sp_proc_stmts1 | ELSE sp_proc_stmts1
...@@ -2685,11 +2740,21 @@ sp_unlabeled_control: ...@@ -2685,11 +2740,21 @@ sp_unlabeled_control:
sp->backpatch(ctx->last_label()); /* We always have a label */ sp->backpatch(ctx->last_label()); /* We always have a label */
if ($3.hndlrs) if ($3.hndlrs)
sp->add_instr(new sp_instr_hpop(sp->instructions(), ctx, {
$3.hndlrs)); sp_instr_hpop *hpop= new sp_instr_hpop(sp->instructions(), ctx,
$3.hndlrs);
if (hpop == NULL)
MYSQL_YYABORT;
sp->add_instr(hpop);
}
if ($3.curs) if ($3.curs)
sp->add_instr(new sp_instr_cpop(sp->instructions(), ctx, {
$3.curs)); sp_instr_cpop *cpop= new sp_instr_cpop(sp->instructions(), ctx,
$3.curs);
if (cpop == NULL)
MYSQL_YYABORT;
sp->add_instr(cpop);
}
lex->spcont= ctx->pop_context(); lex->spcont= ctx->pop_context();
} }
| LOOP_SYM | LOOP_SYM
...@@ -2699,11 +2764,15 @@ sp_unlabeled_control: ...@@ -2699,11 +2764,15 @@ sp_unlabeled_control:
uint ip= lex->sphead->instructions(); uint ip= lex->sphead->instructions();
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */ sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip); sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL)
MYSQL_YYABORT;
lex->sphead->add_instr(i); lex->sphead->add_instr(i);
} }
| WHILE_SYM | WHILE_SYM
{ Lex->sphead->reset_lex(YYTHD); } {
if (Lex->sphead->reset_lex(YYTHD))
MYSQL_YYABORT;
}
expr DO_SYM expr DO_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -2711,7 +2780,8 @@ sp_unlabeled_control: ...@@ -2711,7 +2780,8 @@ sp_unlabeled_control:
uint ip= sp->instructions(); uint ip= sp->instructions();
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont, sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
$3, lex); $3, lex);
if (i == NULL)
MYSQL_YYABORT;
/* Jumping forward */ /* Jumping forward */
sp->push_backpatch(i, lex->spcont->last_label()); sp->push_backpatch(i, lex->spcont->last_label());
sp->new_cont_backpatch(i); sp->new_cont_backpatch(i);
...@@ -2724,12 +2794,16 @@ sp_unlabeled_control: ...@@ -2724,12 +2794,16 @@ sp_unlabeled_control:
uint ip= lex->sphead->instructions(); uint ip= lex->sphead->instructions();
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */ sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip); sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL)
MYSQL_YYABORT;
lex->sphead->add_instr(i); lex->sphead->add_instr(i);
lex->sphead->do_cont_backpatch(); lex->sphead->do_cont_backpatch();
} }
| REPEAT_SYM sp_proc_stmts1 UNTIL_SYM | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM
{ Lex->sphead->reset_lex(YYTHD); } {
if (Lex->sphead->reset_lex(YYTHD))
MYSQL_YYABORT;
}
expr END REPEAT_SYM expr END REPEAT_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -2738,6 +2812,8 @@ sp_unlabeled_control: ...@@ -2738,6 +2812,8 @@ sp_unlabeled_control:
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont, sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
$5, lab->ip, $5, lab->ip,
lex); lex);
if (i == NULL)
MYSQL_YYABORT;
lex->sphead->add_instr(i); lex->sphead->add_instr(i);
lex->sphead->restore_lex(YYTHD); lex->sphead->restore_lex(YYTHD);
/* We can shortcut the cont_backpatch here */ /* We can shortcut the cont_backpatch here */
...@@ -4271,6 +4347,8 @@ select_init2: ...@@ -4271,6 +4347,8 @@ select_init2:
select_part2 select_part2
{ {
LEX *lex= Lex; LEX *lex= Lex;
if (lex == NULL)
MYSQL_YYABORT;
SELECT_LEX * sel= lex->current_select; SELECT_LEX * sel= lex->current_select;
if (lex->current_select->set_braces(0)) if (lex->current_select->set_braces(0))
{ {
...@@ -4624,6 +4702,8 @@ predicate: ...@@ -4624,6 +4702,8 @@ predicate:
$7->push_front($5); $7->push_front($5);
$7->push_front($1); $7->push_front($1);
Item_func_in *item = new (YYTHD->mem_root) Item_func_in(*$7); Item_func_in *item = new (YYTHD->mem_root) Item_func_in(*$7);
if (item == NULL)
MYSQL_YYABORT;
item->negate(); item->negate();
$$= item; $$= item;
} }
...@@ -5084,7 +5164,8 @@ simple_expr: ...@@ -5084,7 +5164,8 @@ simple_expr:
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_name *name= new sp_name($1, $3, true); sp_name *name= new sp_name($1, $3, true);
if (name == NULL)
MYSQL_YYABORT;
name->init_qname(YYTHD); name->init_qname(YYTHD);
sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
if ($5) if ($5)
...@@ -5199,7 +5280,8 @@ simple_expr: ...@@ -5199,7 +5280,8 @@ simple_expr:
if (lex->copy_db_to(&db.str, &db.length)) if (lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT; MYSQL_YYABORT;
sp_name *name= new sp_name(db, $1, false); sp_name *name= new sp_name(db, $1, false);
if (name) if (name == NULL)
MYSQL_YYABORT;
name->init_qname(thd); name->init_qname(thd);
sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
...@@ -8422,7 +8504,8 @@ option_type_value: ...@@ -8422,7 +8504,8 @@ option_type_value:
QQ: May be we should simply prohibit group assignments in SP? QQ: May be we should simply prohibit group assignments in SP?
*/ */
Lex->sphead->reset_lex(thd); if (Lex->sphead->reset_lex(thd))
MYSQL_YYABORT;
lex= thd->lex; lex= thd->lex;
/* Set new LEX as if we at start of set rule. */ /* Set new LEX as if we at start of set rule. */
...@@ -8587,6 +8670,8 @@ sys_option_value: ...@@ -8587,6 +8670,8 @@ sys_option_value:
it= spv->dflt; it= spv->dflt;
else else
it= new Item_null(); it= new Item_null();
if (it == NULL)
MYSQL_YYABORT;
sp_set= new sp_instr_set(lex->sphead->instructions(), ctx, sp_set= new sp_instr_set(lex->sphead->instructions(), ctx,
spv->offset, it, spv->type, lex, TRUE); spv->offset, it, spv->type, lex, TRUE);
lex->sphead->add_instr(sp_set); lex->sphead->add_instr(sp_set);
...@@ -9832,6 +9917,8 @@ sp_tail: ...@@ -9832,6 +9917,8 @@ sp_tail:
/* Order is important here: new - reset - init */ /* Order is important here: new - reset - init */
sp= new sp_head(); sp= new sp_head();
if (sp == NULL)
MYSQL_YYABORT;
sp->reset_thd_mem_root(YYTHD); sp->reset_thd_mem_root(YYTHD);
sp->init(lex); sp->init(lex);
sp->m_type= TYPE_ENUM_PROCEDURE; sp->m_type= TYPE_ENUM_PROCEDURE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment