From 1794242b24cc0f958af48db9019d95aed06cf589 Mon Sep 17 00:00:00 2001
From: "thek@adventure.(none)" <>
Date: Mon, 19 Nov 2007 17:59:44 +0100
Subject: [PATCH] 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      |  14 ++++-
 sql/sp_head.cc     |  38 +++++++++---
 sql/sp_head.h      |   6 +-
 sql/sql_base.cc    |   3 +-
 sql/sql_lex.h      |   5 +-
 sql/sql_prepare.cc |   2 +-
 sql/sql_yacc.yy    | 149 +++++++++++++++++++++++++++++++++++----------
 7 files changed, 168 insertions(+), 49 deletions(-)

diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 08c2b60fa79..89d7f3272ad 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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
 
     if (!thd->no_warnings_for_error)
+    {
+      thd->no_warnings_for_error= TRUE;
       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
       (not query command (COM_QUERY))
@@ -4295,8 +4300,13 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
 			  sock == unix_sock ? VIO_LOCALHOST: 0)) ||
 	my_net_init(&thd->net,vio_tmp))
     {
-      if (vio_tmp)
-	vio_delete(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);
       else
       {
 	(void) shutdown(new_sock, SHUT_RDWR);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 5ad6625efb8..3049ae5ccd3 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -411,14 +411,16 @@ check_routine_name(LEX_STRING ident)
  */
 
 void *
-sp_head::operator new(size_t size)
+sp_head::operator new(size_t size) throw()
 {
   DBUG_ENTER("sp_head::operator new");
   MEM_ROOT own_root;
   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);
+  if (sp == NULL)
+    return NULL;
   sp->main_mem_root= own_root;
   DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root));
   DBUG_RETURN(sp);
@@ -429,6 +431,10 @@ sp_head::operator delete(void *ptr, size_t size)
 {
   DBUG_ENTER("sp_head::operator delete");
   MEM_ROOT own_root;
+
+  if (ptr == NULL)
+    DBUG_VOID_RETURN;
+
   sp_head *sp= (sp_head *) ptr;
 
   /* Make a copy of main_mem_root as free_root will free the sp */
@@ -472,6 +478,9 @@ sp_head::init(LEX *lex)
 
   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
     types of stored procedures to simplify reset_lex()/restore_lex() code.
@@ -973,7 +982,7 @@ sp_head::execute(THD *thd)
     DBUG_RETURN(TRUE);
 
   /* 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));
   m_flags|= IS_INVOKED;
@@ -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)
 {
   DBUG_ENTER("sp_head::reset_lex");
   LEX *sublex;
   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);
-  thd->lex= sublex= new st_lex;
 
   /* Reset most stuff. */
   lex_start(thd);
@@ -1827,7 +1849,7 @@ sp_head::reset_lex(THD *thd)
   sublex->interval_list.empty();
   sublex->type= 0;
 
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(FALSE);
 }
 
 // Restore lex during parsing, after we have parsed a sub statement.
@@ -3703,7 +3725,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
 
   if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
   {
-    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(TABLE_LIST));
+    thd->fatal_error();
     return NULL;
   }
   table->db_length= strlen(db);
diff --git a/sql/sp_head.h b/sql/sp_head.h
index ebe40ce9c87..cb243dd2503 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -191,10 +191,10 @@ public:
   Security_context m_security_ctx;
 
   static void *
-  operator new(size_t size);
+  operator new(size_t size) throw ();
 
   static void
-  operator delete(void *ptr, size_t size);
+  operator delete(void *ptr, size_t size) throw ();
 
   sp_head();
 
@@ -254,7 +254,7 @@ public:
   }
 
   // Resets lex in 'thd' and keeps a copy of the old one.
-  void
+  bool
   reset_lex(THD *thd);
 
   // Restores lex in 'thd' from our copy, but keeps some status from the
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 289924ff418..7ceed4e15d2 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -80,7 +80,6 @@ bool Prelock_error_handler::safely_trapped_errors()
   return ((m_handled_errors > 0) && (m_unhandled_errors == 0));
 }
 
-
 TABLE *unused_tables;				/* 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)
     temporary mem_root for new .frm parsing.
     TODO: variables for size
   */
-  init_alloc_root(&new_frm_mem, 8024, 8024);
+  init_sql_alloc(&new_frm_mem, 8024, 8024);
 
   thd->current_tablenr= 0;
  restart:
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index ce56be79744..f216f51b0e4 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1283,11 +1283,11 @@ typedef struct st_lex : public Query_tables_list
 
 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);
   }
-  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);
   }
@@ -1303,3 +1303,4 @@ extern void lex_start(THD *thd);
 extern void lex_end(LEX *lex);
 extern int MYSQLlex(void *arg, void *yythd);
 extern char *skip_rear_comments(CHARSET_INFO *cs, char *begin, char *end);
+
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index af3da834a7a..74cbd2c5505 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2659,7 +2659,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg)
   last_errno(0),
   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);
   *last_error= '\0';
 }
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 553cc6d24d5..3140ae4f7e3 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1628,6 +1628,8 @@ create_function_tail:
 	    }
 	    /* Order is important here: new - reset - init */
 	    sp= new sp_head();
+            if (sp == NULL)
+              MYSQL_YYABORT;
 	    sp->reset_thd_mem_root(thd);
 	    sp->init(lex);
             sp->init_sp_name(thd, lex->spname);
@@ -1929,7 +1931,8 @@ sp_decl:
           {
             LEX *lex= Lex;
 
-            lex->sphead->reset_lex(YYTHD);
+            if (lex->sphead->reset_lex(YYTHD))
+              MYSQL_YYABORT;
             lex->spcont->declare_var_boundary($2);
           }
           type
@@ -1937,6 +1940,10 @@ sp_decl:
           {
             LEX *lex= Lex;
             sp_pcontext *pctx= lex->spcont;
+            if (pctx == 0)
+            {
+              MYSQL_YYABORT;
+            }
             uint num_vars= pctx->context_var_count();
             enum enum_field_types var_type= (enum enum_field_types) $4;
             Item *dflt_value_item= $5;
@@ -2022,12 +2029,15 @@ sp_decl:
 	    {
 	      i= new sp_instr_hreturn(sp->instructions(), ctx,
 	                              ctx->current_var_count());
+              if (i == NULL )
+                MYSQL_YYABORT;
 	      sp->add_instr(i);
 	    }
 	    else
 	    {  /* EXIT or UNDO handler, just jump to the end of the block */
 	      i= new sp_instr_hreturn(sp->instructions(), ctx, 0);
-
+              if (i == NULL)
+                MYSQL_YYABORT;
 	      sp->add_instr(i);
 	      sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */
 	    }
@@ -2055,7 +2065,9 @@ sp_decl:
 	    }
             i= new sp_instr_cpush(sp->instructions(), ctx, $5,
                                   ctx->current_cursor_count());
-	    sp->add_instr(i);
+	    if ( i==NULL )
+              MYSQL_YYABORT;
+            sp->add_instr(i);
 	    ctx->push_cursor(&$2);
 	    $$.vars= $$.conds= $$.hndlrs= 0;
 	    $$.curs= 1;
@@ -2064,7 +2076,8 @@ sp_decl:
 
 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
 	       error message. Using 'select' works too, but will then
@@ -2230,7 +2243,8 @@ sp_proc_stmt:
 	    LEX *lex= thd->lex;
             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;
 	  }
 	  statement
@@ -2255,9 +2269,10 @@ sp_proc_stmt:
                         lex->var_list.is_empty());
             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);
-
+              if (i == NULL)
+                MYSQL_YYABORT;
               /*
                 Extract the query statement from the tokenizer.  The
                 end is either lex->ptr, if there was no lookahead,
@@ -2275,7 +2290,10 @@ sp_proc_stmt:
 	    sp->restore_lex(thd);
           }
           | RETURN_SYM 
-          { Lex->sphead->reset_lex(YYTHD); }
+          {
+            if(Lex->sphead->reset_lex(YYTHD))
+               MYSQL_YYABORT;
+          }
           expr
 	  {
 	    LEX *lex= Lex;
@@ -2292,6 +2310,8 @@ sp_proc_stmt:
 
 	      i= new sp_instr_freturn(sp->instructions(), lex->spcont, $3,
                                       sp->m_return_field_def.sql_type, lex);
+              if (i == NULL)
+                MYSQL_YYABORT;
 	      sp->add_instr(i);
 	      sp->m_flags|= sp_head::HAS_RETURN;
 	    }
@@ -2334,12 +2354,23 @@ sp_proc_stmt:
 	      uint n;
 
 	      n= ctx->diff_handlers(lab->ctx, TRUE);  /* Exclusive the dest. */
+
 	      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. */
 	      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);
+              if (i == NULL)
+                MYSQL_YYABORT;
 	      sp->push_backpatch(i, lab);  /* Jumping forward */
               sp->add_instr(i);
 	    }
@@ -2364,11 +2395,19 @@ sp_proc_stmt:
 
 	      n= ctx->diff_handlers(lab->ctx, FALSE);  /* Inclusive the dest. */
 	      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. */
 	      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 */
+              if (i == NULL)
+                MYSQL_YYABORT;
               sp->add_instr(i);
 	    }
 	  }
@@ -2385,6 +2424,8 @@ sp_proc_stmt:
 	      MYSQL_YYABORT;
 	    }
 	    i= new sp_instr_copen(sp->instructions(), lex->spcont, offset);
+            if (i == NULL)
+              MYSQL_YYABORT;
 	    sp->add_instr(i);
 	  }
 	| FETCH_SYM sp_opt_fetch_noise ident INTO
@@ -2400,6 +2441,8 @@ sp_proc_stmt:
 	      MYSQL_YYABORT;
 	    }
 	    i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
+            if (i == NULL)
+              MYSQL_YYABORT;
 	    sp->add_instr(i);
 	  }
 	  sp_fetch_list
@@ -2417,6 +2460,8 @@ sp_proc_stmt:
 	      MYSQL_YYABORT;
 	    }
 	    i= new sp_instr_cclose(sp->instructions(), lex->spcont,  offset);
+            if (i == NULL)
+              MYSQL_YYABORT;
 	    sp->add_instr(i);
 	  }
 	;
@@ -2472,7 +2517,10 @@ sp_fetch_list:
 	;
 
 sp_if:
-          { Lex->sphead->reset_lex(YYTHD); }
+          {
+            if (Lex->sphead->reset_lex(YYTHD))
+              MYSQL_YYABORT;
+          }
           expr THEN_SYM
 	  {
 	    LEX *lex= Lex;
@@ -2481,7 +2529,8 @@ sp_if:
 	    uint ip= sp->instructions();
 	    sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx,
                                                                $2, lex);
-
+            if (i == NULL)
+              MYSQL_YYABORT;
 	    sp->push_backpatch(i, ctx->push_label((char *)"", 0));
             sp->add_cont_backpatch(i);
             sp->add_instr(i);
@@ -2493,7 +2542,8 @@ sp_if:
 	    sp_pcontext *ctx= Lex->spcont;
 	    uint ip= sp->instructions();
 	    sp_instr_jump *i = new sp_instr_jump(ip, ctx);
-
+            if (i == NULL)
+              MYSQL_YYABORT;
 	    sp->add_instr(i);
 	    sp->backpatch(ctx->pop_label());
 	    sp->push_backpatch(i, ctx->push_label((char *)"", 0));
@@ -2522,7 +2572,8 @@ simple_case_stmt:
           {
             LEX *lex= 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
           {
@@ -2571,7 +2622,8 @@ searched_when_clause_list:
 simple_when_clause:
           WHEN_SYM
           {
-            Lex->sphead->reset_lex(YYTHD); /* For expr $3 */
+            if (Lex->sphead->reset_lex(YYTHD))
+              MYSQL_YYABORT; /* For expr $3 */
           }
           expr
           {
@@ -2592,7 +2644,8 @@ simple_when_clause:
 searched_when_clause:
           WHEN_SYM
           {
-            Lex->sphead->reset_lex(YYTHD); /* For expr $3 */
+            if (Lex->sphead->reset_lex(YYTHD))
+              MYSQL_YYABORT; /* For expr $3 */
           }
           expr
           {
@@ -2616,6 +2669,8 @@ else_clause_opt:
             uint ip= sp->instructions();
             sp_instr_error *i= new sp_instr_error(ip, lex->spcont,
                                                   ER_SP_CASE_NOT_FOUND);
+            if (i == NULL)
+              MYSQL_YYABORT;
             sp->add_instr(i);
           }
         | ELSE sp_proc_stmts1
@@ -2685,11 +2740,21 @@ sp_unlabeled_control:
 
   	    sp->backpatch(ctx->last_label());	/* We always have a label */
 	    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)
-	      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();
 	  }
 	| LOOP_SYM
@@ -2699,11 +2764,15 @@ sp_unlabeled_control:
 	    uint ip= lex->sphead->instructions();
 	    sp_label_t *lab= lex->spcont->last_label();  /* Jumping back */
 	    sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
-
+            if (i == NULL)
+              MYSQL_YYABORT;
 	    lex->sphead->add_instr(i);
 	  }
         | WHILE_SYM 
-          { Lex->sphead->reset_lex(YYTHD); }
+          {
+            if (Lex->sphead->reset_lex(YYTHD))
+              MYSQL_YYABORT;
+          }
           expr DO_SYM
 	  {
 	    LEX *lex= Lex;
@@ -2711,7 +2780,8 @@ sp_unlabeled_control:
 	    uint ip= sp->instructions();
 	    sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
 							       $3, lex);
-
+            if (i == NULL)
+              MYSQL_YYABORT;
 	    /* Jumping forward */
 	    sp->push_backpatch(i, lex->spcont->last_label());
             sp->new_cont_backpatch(i);
@@ -2724,12 +2794,16 @@ sp_unlabeled_control:
 	    uint ip= lex->sphead->instructions();
 	    sp_label_t *lab= lex->spcont->last_label();  /* Jumping back */
 	    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->do_cont_backpatch();
 	  }
         | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM 
-          { Lex->sphead->reset_lex(YYTHD); }
+          {
+            if (Lex->sphead->reset_lex(YYTHD))
+              MYSQL_YYABORT;
+          }
           expr END REPEAT_SYM
 	  {
 	    LEX *lex= Lex;
@@ -2738,6 +2812,8 @@ sp_unlabeled_control:
 	    sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
                                                                $5, lab->ip,
                                                                lex);
+            if (i == NULL)
+              MYSQL_YYABORT;
             lex->sphead->add_instr(i);
             lex->sphead->restore_lex(YYTHD);
             /* We can shortcut the cont_backpatch here */
@@ -4271,6 +4347,8 @@ select_init2:
 	select_part2
         {
 	  LEX *lex= Lex;
+          if (lex == NULL)
+            MYSQL_YYABORT;
           SELECT_LEX * sel= lex->current_select;
           if (lex->current_select->set_braces(0))
 	  {
@@ -4624,6 +4702,8 @@ predicate:
             $7->push_front($5);
             $7->push_front($1);
             Item_func_in *item = new (YYTHD->mem_root) Item_func_in(*$7);
+            if (item == NULL)
+              MYSQL_YYABORT;
             item->negate();
             $$= item;
           }
@@ -5084,7 +5164,8 @@ simple_expr:
 	  {
 	    LEX *lex= Lex;
 	    sp_name *name= new sp_name($1, $3, true);
-
+            if (name == NULL)
+              MYSQL_YYABORT;
 	    name->init_qname(YYTHD);
 	    sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
 	    if ($5)
@@ -5199,8 +5280,9 @@ simple_expr:
               if (lex->copy_db_to(&db.str, &db.length))
                 MYSQL_YYABORT;
               sp_name *name= new sp_name(db, $1, false);
-              if (name)
-                name->init_qname(thd);
+              if (name == NULL)
+                MYSQL_YYABORT;
+              name->init_qname(thd);
 
               sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
               if ($4)
@@ -8422,7 +8504,8 @@ option_type_value:
 
               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;
 
             /* Set new LEX as if we at start of set rule. */
@@ -8587,6 +8670,8 @@ sys_option_value:
               it= spv->dflt;
             else
               it= new Item_null();
+            if (it == NULL)
+              MYSQL_YYABORT;
             sp_set= new sp_instr_set(lex->sphead->instructions(), ctx,
                                      spv->offset, it, spv->type, lex, TRUE);
             lex->sphead->add_instr(sp_set);
@@ -9832,6 +9917,8 @@ sp_tail:
 
 	  /* Order is important here: new - reset - init */
 	  sp= new sp_head();
+          if (sp == NULL)
+            MYSQL_YYABORT;
 	  sp->reset_thd_mem_root(YYTHD);
 	  sp->init(lex);
 	  sp->m_type= TYPE_ENUM_PROCEDURE;