List:Internals« Previous MessageNext Message »
From:sanja Date:November 22 2005 11:50pm
Subject:bk commit into 5.0 tree (bell:1.2017) BUG#13549
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of bell. When bell does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2017 05/11/23 00:50:37 bell@stripped +16 -0
  Fix for BUG#13549 "Server crash with nested stored procedures
  if inner routine has more local variables than outer one, and
  one of its last variables was used as argument to NOT operator".
  
  THD::spcont was non-0 when we were parsing stored routine/trigger
  definition during execution of another stored routine. This confused
  methods of Item_splocal and forced them use wrong runtime context.
  Fix ensures that we always have THD::spcont equal to zero during
  routine/trigger body parsing. This also allows to avoid problems
  with errors which occur during parsing and SQL exception handlers.

  sql/sql_yacc.yy
    1.432 05/11/23 00:50:33 bell@stripped +17 -3
    Protection against using wrong context by SP local variable.

  sql/sql_trigger.cc
    1.30 05/11/23 00:50:33 bell@stripped +3 -0
    Do not allow Trigger which we are parsing to use
    other SP context (BUG#13549).

  sql/sql_class.h
    1.269 05/11/23 00:50:32 bell@stripped +7 -0
    Protection against using wrong context by SP local variable.

  sql/sql_class.cc
    1.214 05/11/23 00:50:32 bell@stripped +7 -1
    Protection against using wrong context by SP local variable.

  sql/sql_cache.h
    1.31 05/11/23 00:50:32 bell@stripped +1 -1
    An incorrect macro name fixed.

  sql/sp_rcontext.h
    1.26 05/11/23 00:50:32 bell@stripped +8 -0
    Protection against using wrong context by SP local variable.

  sql/sp_head.cc
    1.189 05/11/23 00:50:32 bell@stripped +9 -0
    Protection against using wrong context by SP local variable.

  sql/sp.cc
    1.96 05/11/23 00:50:32 bell@stripped +5 -1
    Do not allow SP which we are parsing to use other SP
    context (BUG#13549).

  sql/protocol.h
    1.31 05/11/23 00:50:32 bell@stripped +1 -1
    An incorrect macro name fixed.

  sql/protocol.cc
    1.109 05/11/23 00:50:32 bell@stripped +19 -19
    An incorrect macro name fixed.

  sql/item.h
    1.172 05/11/23 00:50:32 bell@stripped +9 -0
    Protection against using wrong context by SP local variable.

  sql/item.cc
    1.186 05/11/23 00:50:32 bell@stripped +6 -1
    Protection against using wrong context by SP local variable.

  mysql-test/t/trigger.test
    1.28 05/11/23 00:50:32 bell@stripped +28 -0
    Test suite for bug#13549.

  mysql-test/t/sp.test
    1.156 05/11/23 00:50:32 bell@stripped +27 -0
    Test suite for bug#13549.

  mysql-test/r/trigger.result
    1.21 05/11/23 00:50:32 bell@stripped +14 -0
    Test suite for bug#13549.

  mysql-test/r/sp.result
    1.160 05/11/23 00:50:32 bell@stripped +17 -0
    Test suite for bug#13549.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	bell
# Host:	sanja.is.com.ua
# Root:	/home/bell/mysql/bk/work-bug2-5.0

--- 1.185/sql/item.cc	2005-10-01 09:35:10 +03:00
+++ 1.186/sql/item.cc	2005-11-23 00:50:32 +02:00
@@ -868,7 +868,7 @@
 Item_splocal::this_item()
 {
   THD *thd= current_thd;
-
+  DBUG_ASSERT(owner == thd->spcont->owner);
   return thd->spcont->get_item(m_offset);
 }
 
@@ -876,6 +876,7 @@
 Item **
 Item_splocal::this_item_addr(THD *thd, Item **addr)
 {
+  DBUG_ASSERT(owner == thd->spcont->owner);
   return thd->spcont->get_item_addr(m_offset);
 }
 
@@ -884,6 +885,7 @@
 {
   THD *thd= current_thd;
 
+  DBUG_ASSERT(owner == thd->spcont->owner);
   return thd->spcont->get_item(m_offset);
 }
 
@@ -893,7 +895,10 @@
   THD *thd= current_thd;
 
   if (thd->spcont)
+  {
+    DBUG_ASSERT(owner == thd->spcont->owner);
     return thd->spcont->get_item(m_offset)->type();
+  }
   return NULL_ITEM;		// Anything but SUBSELECT_ITEM
 }
 

--- 1.171/sql/item.h	2005-10-03 22:02:18 +03:00
+++ 1.172/sql/item.h	2005-11-23 00:50:32 +02:00
@@ -703,6 +703,8 @@
 };
 
 
+class sp_head;
+
 /*
   A reference to local SP variable (incl. reference to SP parameter), used in
   runtime.
@@ -720,6 +722,13 @@
   uint m_offset;
 
 public:
+#ifndef DBUG_OFF
+  /*
+    Routine to which this Item_splocal belongs. Used for checking if correct
+    runtime context is used for variable handling.
+  */
+  sp_head *owner;
+#endif
   LEX_STRING m_name;
 
   /*

--- 1.108/sql/protocol.cc	2005-06-30 15:17:05 +03:00
+++ 1.109/sql/protocol.cc	2005-11-23 00:50:32 +02:00
@@ -494,7 +494,7 @@
   thd=thd_arg;
   packet= &thd->packet;
   convert= &thd->convert_buffer;
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   field_types= 0;
 #endif
 }
@@ -547,7 +547,7 @@
     (void) my_net_write(&thd->net, buff,(uint) (pos-buff));
   }
 
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
 					      list->elements);
   uint count= 0;
@@ -644,7 +644,7 @@
       item->send(&prot, &tmp);			// Send default value
     if (prot.write())
       break;					/* purecov: inspected */
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
     field_types[count++]= field.type;
 #endif
   }
@@ -728,14 +728,14 @@
 void Protocol_simple::prepare_for_resend()
 {
   packet->length(0);
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   field_pos= 0;
 #endif
 }
 
 bool Protocol_simple::store_null()
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   field_pos++;
 #endif
   char buff[1];
@@ -769,7 +769,7 @@
 bool Protocol_simple::store(const char *from, uint length,
 			    CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
               field_types[field_pos] == MYSQL_TYPE_BIT ||
@@ -786,7 +786,7 @@
 			    CHARSET_INFO *fromcs)
 {
   CHARSET_INFO *tocs= this->thd->variables.character_set_results;
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
               field_types[field_pos] == MYSQL_TYPE_BIT ||
@@ -801,7 +801,7 @@
 
 bool Protocol_simple::store_tiny(longlong from)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
   field_pos++;
 #endif
@@ -813,7 +813,7 @@
 
 bool Protocol_simple::store_short(longlong from)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_YEAR ||
 	      field_types[field_pos] == MYSQL_TYPE_SHORT);
@@ -827,7 +827,7 @@
 
 bool Protocol_simple::store_long(longlong from)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
               field_types[field_pos] == MYSQL_TYPE_INT24 ||
               field_types[field_pos] == MYSQL_TYPE_LONG);
@@ -841,7 +841,7 @@
 
 bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_LONGLONG);
   field_pos++;
@@ -856,7 +856,7 @@
 
 bool Protocol_simple::store_decimal(const my_decimal *d)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
               field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
   field_pos++;
@@ -870,7 +870,7 @@
 
 bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_FLOAT);
   field_pos++;
@@ -882,7 +882,7 @@
 
 bool Protocol_simple::store(double from, uint32 decimals, String *buffer)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_DOUBLE);
   field_pos++;
@@ -896,7 +896,7 @@
 {
   if (field->is_null())
     return store_null();
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   field_pos++;
 #endif
   char buff[MAX_FIELD_WIDTH];
@@ -917,7 +917,7 @@
 
 bool Protocol_simple::store(TIME *tm)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_DATETIME ||
 	      field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
@@ -940,7 +940,7 @@
 
 bool Protocol_simple::store_date(TIME *tm)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_DATE);
   field_pos++;
@@ -959,7 +959,7 @@
 
 bool Protocol_simple::store_time(TIME *tm)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_TIME);
   field_pos++;
@@ -1084,7 +1084,7 @@
 
 bool Protocol_prep::store_decimal(const my_decimal *d)
 {
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   DBUG_ASSERT(field_types == 0 ||
               field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
   field_pos++;

--- 1.213/sql/sql_class.cc	2005-09-22 23:46:50 +03:00
+++ 1.214/sql/sql_class.cc	2005-11-23 00:50:32 +02:00
@@ -1490,7 +1490,13 @@
   {
     my_var *mv= gl++;
     if (mv->local)
-      (void)local_vars.push_back(new Item_splocal(mv->s, mv->offset));
+    {
+      Item_splocal *var;
+      (void)local_vars.push_back(var= new Item_splocal(mv->s, mv->offset));
+#ifndef DEBUG_OFF
+      var->owner= mv->owner;
+#endif
+    }
     else
     {
       Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item);

--- 1.268/sql/sql_class.h	2005-09-22 23:46:50 +03:00
+++ 1.269/sql/sql_class.h	2005-11-23 00:50:32 +02:00
@@ -2075,6 +2075,13 @@
 class my_var : public Sql_alloc  {
 public:
   LEX_STRING s;
+#ifndef DEBUG_OFF
+  /*
+    Routine to which this Item_splocal belongs. Used for checking if correct
+    runtime context is used for variable handling.
+  */
+  sp_head *owner;
+#endif
   bool local;
   uint offset;
   enum_field_types type;

--- 1.431/sql/sql_yacc.yy	2005-09-23 10:18:52 +03:00
+++ 1.432/sql/sql_yacc.yy	2005-11-23 00:50:33 +02:00
@@ -2351,8 +2351,12 @@
 
 	      ivar.str= (char *)"_tmp_";
 	      ivar.length= 5;
-	      Item *var= (Item*) new Item_splocal(ivar, 
-						  ctx->current_pvars()-1);
+	      Item_splocal *var= new Item_splocal(ivar,
+                                                  ctx->current_pvars()-1);
+#ifndef DEBUG_OFF
+              if (var)
+                var->owner= sp;
+#endif
 	      Item *expr= new Item_func_eq(var, $2);
 
 	      i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
@@ -5925,7 +5929,13 @@
 	       YYABORT;
 	     else
 	     {
-	       ((select_dumpvar *)lex->result)->var_list.push_back( new
my_var($1,1,t->offset,t->type));
+               my_var *var;
+	       ((select_dumpvar *)lex->result)->
+                 var_list.push_back(var= new my_var($1,1,t->offset,t->type));
+#ifndef DEBUG_OFF
+	       if (var)
+		 var->owner= lex->sphead;
+#endif
 	     }
 	   }
            ;
@@ -7224,6 +7234,10 @@
             Item_splocal *splocal;
             splocal= new Item_splocal($1, spv->offset, lex->tok_start_prev - 
                                       lex->sphead->m_tmp_query);
+#ifndef DEBUG_OFF
+            if (splocal)
+              splocal->owner= lex->sphead;
+#endif
 	    $$ = (Item*) splocal;
             lex->variables_used= 1;
 	    lex->safe_to_cache_query=0;

--- 1.20/mysql-test/r/trigger.result	2005-09-03 02:13:09 +03:00
+++ 1.21/mysql-test/r/trigger.result	2005-11-23 00:50:32 +02:00
@@ -738,3 +738,17 @@
 1
 drop trigger t1_bi;
 drop tables t1, t2;
+create table t1 (a int);
+drop procedure if exists p2;
+CREATE PROCEDURE `p2`()
+begin
+insert into t1 values (1);
+end//
+create trigger trg before insert on t1 for each row 
+begin 
+declare done int default 0;
+set done= not done;
+end//
+CALL p2();
+drop procedure p2;
+drop table t1;

--- 1.27/mysql-test/t/trigger.test	2005-09-15 02:56:03 +03:00
+++ 1.28/mysql-test/t/trigger.test	2005-11-23 00:50:32 +02:00
@@ -875,3 +875,31 @@
 drop view v1;
 drop table t1, t2, t3;
 --enable_parsing
+
+#
+# BUG#13549 "Server crash with nested stored procedures".
+# Server should not crash when during execution of stored procedure
+# we have to parse trigger/function definition and this new trigger/
+# function has more local variables declared than invoking stored
+# procedure and last of these variables is used in argument of NOT
+# operator.
+#
+create table t1 (a int);
+--disable_warnings
+drop procedure if exists p2;
+--enable_warnings
+DELIMITER //;
+CREATE PROCEDURE `p2`()
+begin
+  insert into t1 values (1);
+end//
+create trigger trg before insert on t1 for each row 
+begin 
+  declare done int default 0;
+  set done= not done;
+end//
+DELIMITER ;//
+CALL p2();
+drop procedure p2;
+drop table t1;
+

--- 1.29/sql/sql_trigger.cc	2005-09-15 22:29:01 +03:00
+++ 1.30/sql/sql_trigger.cc	2005-11-23 00:50:33 +02:00
@@ -646,6 +646,7 @@
       char *trg_name_buff;
       List_iterator_fast<ulonglong> itm(triggers->definition_modes_list);
       LEX *old_lex= thd->lex, lex;
+      sp_rcontext *save_spcont= thd->spcont;
       ulong save_sql_mode= thd->variables.sql_mode;
 
       thd->lex= &lex;
@@ -660,6 +661,7 @@
         thd->variables.sql_mode= (ulong)*trg_sql_mode;
         lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
 
+	thd->spcont= 0;
         if (yyparse((void *)thd) || thd->is_fatal_error)
         {
           /*
@@ -712,6 +714,7 @@
       // QQ: anything else ?
       lex_end(&lex);
       thd->lex= old_lex;
+      thd->spcont= save_spcont;
       thd->variables.sql_mode= save_sql_mode;
       thd->db= save_db.str;
       thd->db_length= save_db.length;

--- 1.30/sql/sql_cache.h	2005-09-06 20:51:08 +03:00
+++ 1.31/sql/sql_cache.h	2005-11-23 00:50:32 +02:00
@@ -410,7 +410,7 @@
 
   /*
     The following functions are only used when debugging
-    We don't protect these with ifndef DEBUG_OFF to not have to recompile
+    We don't protect these with ifndef DBUG_OFF to not have to recompile
     everything if we want to add checks of the cache at some places.
   */
   void wreck(uint line, const char *message);

--- 1.30/sql/protocol.h	2005-09-22 01:10:57 +03:00
+++ 1.31/sql/protocol.h	2005-11-23 00:50:32 +02:00
@@ -31,7 +31,7 @@
   String *packet;
   String *convert;
   uint field_pos;
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
   enum enum_field_types *field_types;
 #endif
   uint field_count;

--- 1.159/mysql-test/r/sp.result	2005-10-03 20:00:47 +03:00
+++ 1.160/mysql-test/r/sp.result	2005-11-23 00:50:32 +02:00
@@ -3435,4 +3435,21 @@
 tm1	CREATE TEMPORARY TABLE `tm1` (
   `spv1` decimal(6,3) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop procedure bug12589_1|
+drop procedure bug12589_2|
+drop procedure bug12589_3|
+drop procedure if exists bug13549_1|
+drop procedure if exists bug13549_2|
+CREATE PROCEDURE `bug13549_2`()
+begin
+call bug13549_1();
+end|
+CREATE PROCEDURE `bug13549_1`()
+begin
+declare done int default 0;
+set done= not done;
+end|
+CALL bug13549_2()|
+drop procedure bug13549_2|
+drop procedure bug13549_1|
 drop table t1,t2;

--- 1.155/mysql-test/t/sp.test	2005-10-03 20:00:49 +03:00
+++ 1.156/mysql-test/t/sp.test	2005-11-23 00:50:32 +02:00
@@ -4313,7 +4313,34 @@
 # No warnings here
 call bug12589_2()|
 call bug12589_3()|
+drop procedure bug12589_1|
+drop procedure bug12589_2|
+drop procedure bug12589_3|
 
+#
+# BUG#13549 "Server crash with nested stored procedures".
+# Server should not crash when during execution of stored procedure
+# we have to parse trigger/function definition and this new trigger/
+# function has more local variables declared than invoking stored
+# procedure and last of these variables is used in argument of NOT
+# operator.
+#
+--disable_warnings
+drop procedure if exists bug13549_1|
+drop procedure if exists bug13549_2|
+--enable_warnings
+CREATE PROCEDURE `bug13549_2`()
+begin
+  call bug13549_1();
+end|
+CREATE PROCEDURE `bug13549_1`()
+begin
+  declare done int default 0;
+  set done= not done;
+end|
+CALL bug13549_2()|
+drop procedure bug13549_2|
+drop procedure bug13549_1|
 
 #
 # BUG#NNNN: New bug synopsis

--- 1.95/sql/sp.cc	2005-09-15 22:29:01 +03:00
+++ 1.96/sql/sp.cc	2005-11-23 00:50:32 +02:00
@@ -380,6 +380,7 @@
   {
     String defstr;
     LEX *oldlex= thd->lex;
+    sp_rcontext *save_spcont= thd->spcont;
     char olddb[128];
     bool dbchanged;
     enum enum_sql_command oldcmd= thd->lex->sql_command;
@@ -422,6 +423,7 @@
       thd->lex->found_semicolon= tmpfsc;
     }
 
+    thd->spcont= 0;
     if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
     {
       LEX *newlex= thd->lex;
@@ -439,12 +441,14 @@
     else
     {
       if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
-	goto done;
+	goto db_done;
       *sphp= thd->lex->sphead;
       (*sphp)->set_info((char *)definer, (uint)strlen(definer),
 			created, modified, &chistics, sql_mode);
       (*sphp)->optimize();
     }
+db_done:
+    thd->spcont= save_spcont;
     thd->lex->sql_command= oldcmd;
     thd->variables.sql_mode= old_sql_mode;
     thd->variables.select_limit= select_limit;

--- 1.188/sql/sp_head.cc	2005-09-26 19:21:53 +03:00
+++ 1.189/sql/sp_head.cc	2005-11-23 00:50:32 +02:00
@@ -1112,6 +1112,9 @@
   // QQ Should have some error checking here? (types, etc...)
   if (!(nctx= new sp_rcontext(csize, hmax, cmax)))
     goto end;
+#ifndef DBUG_OFF
+  nctx->owner= this;
+#endif
   for (i= 0 ; i < argcount ; i++)
   {
     sp_pvar_t *pvar = m_pcont->find_pvar(i);
@@ -1256,6 +1259,9 @@
   {				// Create a temporary old context
     if (!(octx= new sp_rcontext(csize, hmax, cmax)))
       DBUG_RETURN(-1);
+#ifndef DBUG_OFF
+    octx->owner= 0;
+#endif
     thd->spcont= octx;
 
     /* set callers_arena to thd, for upper-level function to work */
@@ -1267,6 +1273,9 @@
     thd->spcont= save_spcont;
     DBUG_RETURN(-1);
   }
+#ifndef DBUG_OFF
+  nctx->owner= this;
+#endif
 
   if (csize > 0 || hmax > 0 || cmax > 0)
   {

--- 1.25/sql/sp_rcontext.h	2005-09-26 19:21:53 +03:00
+++ 1.26/sql/sp_rcontext.h	2005-11-23 00:50:32 +02:00
@@ -66,6 +66,14 @@
   */
   Query_arena *callers_arena;
 
+#ifndef DBUG_OFF
+  /*
+    Routine to which this Item_splocal belongs. Used for checking if correct
+    runtime context is used for variable handling.
+  */
+  sp_head *owner;
+#endif
+
   sp_rcontext(uint fsize, uint hmax, uint cmax);
 
   ~sp_rcontext()
Thread
bk commit into 5.0 tree (bell:1.2017) BUG#13549sanja22 Nov