MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:marc.alff Date:April 27 2007 11:14pm
Subject:bk commit into 5.0 tree (malff:1.2440) BUG#21513
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of marcsql. When marcsql 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@stripped, 2007-04-27 17:14:25-06:00, malff@weblab.(none) +5 -0
  Bug#21513 (SP having body starting with quoted label rendered unusable)
  
  Before this fix, the parser would sometime change where a token starts by
  altering Lex_input_string::tok_start, which later confused the code in
  sql_yacc.yy that needs to capture the source code of a SQL statement,
  like to represent the body of a stored procedure.
  
  This line of code in sql_lex.cc :
  
  case MY_LEX_USER_VARIABLE_DELIMITER:
    lip->tok_start= lip->ptr; // Skip first `
  
  would <skip the first back quote> ... and cause the bug reported.
  
  In general, the responsibility of sql_lex.cc is to *find* where token are
  in the SQL text, but is *not* to make up fake or incomplete tokens.
  With a quoted label like `my_label`, the token starts on the first quote.
  Extracting the token value should not change that (it did).
  
  With this fix, the lexical analysis has been cleaned up to not change
  lip->tok_start (in the case found for this bug).
  
  The functions get_token() and get_quoted_token() now have an extra
  parameters, used when some characters from the beginning of the token need
  to be skipped when extracting a token value, like when extracting 'AB' from
  '0xAB', for example, for a HEX_NUM token.
  
  This exposed a bad assumption in Item_hex_string and Item_bin_string,
  which has been fixed:
  
  The assumption was that the string given, 'AB', was in fact preceded in
  memory by '0x', which might be false (it can be preceded by "x'" and
  followed by "'" -- or not be preceded by valid memory at all)
  
  If a name is needed for Item_hex_string or Item_bin_string, the name is
  taken from the original and true source code ('0xAB'), and assigned in
  the select_item rule, instead of relying on assumptions related to how
  memory is used.

  mysql-test/r/sp.result@stripped, 2007-04-27 17:14:22-06:00, malff@weblab.(none) +7 -0
    Lex_input_stream::tok_start must point at the real start of a token.

  mysql-test/t/sp.test@stripped, 2007-04-27 17:14:22-06:00, malff@weblab.(none) +11 -0
    Lex_input_stream::tok_start must point at the real start of a token.

  sql/item.cc@stripped, 2007-04-27 17:14:22-06:00, malff@weblab.(none) +0 -2
    Lex_input_stream::tok_start must point at the real start of a token.

  sql/sql_lex.cc@stripped, 2007-04-27 17:14:23-06:00, malff@weblab.(none) +30 -34
    Lex_input_stream::tok_start must point at the real start of a token.

  sql/sql_yacc.yy@stripped, 2007-04-27 17:14:23-06:00, malff@weblab.(none) +8 -6
    Lex_input_stream::tok_start must point at the real start of a token.

# 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:	malff
# Host:	weblab.(none)
# Root:	/home/marcsql/TREE/mysql-5.0-21513

--- 1.262/sql/item.cc	2007-04-27 17:14:32 -06:00
+++ 1.263/sql/item.cc	2007-04-27 17:14:32 -06:00
@@ -4602,7 +4602,6 @@ inline uint char_val(char X)
 
 Item_hex_string::Item_hex_string(const char *str, uint str_length)
 {
-  name=(char*) str-2;				// Lex makes this start with 0x
   max_length=(str_length+1)/2;
   char *ptr=(char*) sql_alloc(max_length+1);
   if (!ptr)
@@ -4713,7 +4712,6 @@ Item_bin_string::Item_bin_string(const c
   uchar bits= 0;
   uint power= 1;
 
-  name= (char*) str - 2;
   max_length= (str_length + 7) >> 3;
   char *ptr= (char*) sql_alloc(max_length + 1);
   if (!ptr)

--- 1.220/sql/sql_lex.cc	2007-04-27 17:14:32 -06:00
+++ 1.221/sql/sql_lex.cc	2007-04-27 17:14:32 -06:00
@@ -262,12 +262,12 @@ bool is_keyword(const char *name, uint l
 
 /* make a copy of token before ptr and set yytoklen */
 
-static LEX_STRING get_token(Lex_input_stream *lip, uint length)
+static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length)
 {
   LEX_STRING tmp;
   yyUnget();			// ptr points now after last token char
   tmp.length=lip->yytoklen=length;
-  tmp.str= lip->m_thd->strmake(lip->tok_start, tmp.length);
+  tmp.str= lip->m_thd->strmake(lip->tok_start + skip, tmp.length);
   return tmp;
 }
 
@@ -279,6 +279,7 @@ static LEX_STRING get_token(Lex_input_st
 */
 
 static LEX_STRING get_quoted_token(Lex_input_stream *lip,
+                                   uint skip,
                                    uint length, char quote)
 {
   LEX_STRING tmp;
@@ -286,9 +287,10 @@ static LEX_STRING get_quoted_token(Lex_i
   yyUnget();			// ptr points now after last token char
   tmp.length=lip->yytoklen=length;
   tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
-  for (from= (byte*) lip->tok_start, to= (byte*) tmp.str, end= to+length ;
-       to != end ;
-       )
+  from= (byte*) lip->tok_start + skip;
+  to= (byte*) tmp.str;
+  end= to+length;
+  for ( ; to != end; )
   {
     if ((*to++= *from++) == quote)
       from++;					// Skip double quotes
@@ -676,7 +678,7 @@ int MYSQLlex(void *arg, void *yythd)
 	}
 	yySkip();			// next state does a unget
       }
-      yylval->lex_str=get_token(lip, length);
+      yylval->lex_str=get_token(lip, 0, length);
 
       /* 
          Note: "SELECT _bla AS 'alias'"
@@ -718,7 +720,7 @@ int MYSQLlex(void *arg, void *yythd)
 	  {
 	    yySkip();
 	    while (my_isdigit(cs,yyGet())) ;
-	    yylval->lex_str=get_token(lip, yyLength());
+	    yylval->lex_str=get_token(lip, 0, yyLength());
 	    return(FLOAT_NUM);
 	  }
 	}
@@ -730,10 +732,8 @@ int MYSQLlex(void *arg, void *yythd)
 	while (my_isxdigit(cs,(c = yyGet()))) ;
 	if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c])
 	{
-	  yylval->lex_str=get_token(lip, yyLength());
-	  yylval->lex_str.str+=2;		// Skip 0x
-	  yylval->lex_str.length-=2;
-	  lip->yytoklen-=2;
+          /* skip '0x' */
+	  yylval->lex_str=get_token(lip, 2, yyLength()-2);
 	  return (HEX_NUM);
 	}
 	yyUnget();
@@ -744,10 +744,8 @@ int MYSQLlex(void *arg, void *yythd)
 	while (my_isxdigit(cs,(c = yyGet()))) ;
 	if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c])
 	{
-	  yylval->lex_str= get_token(lip, yyLength());
-	  yylval->lex_str.str+= 2;		// Skip 0x
-	  yylval->lex_str.length-= 2;
-	  lip->yytoklen-= 2;
+          /* Skip '0b' */
+	  yylval->lex_str= get_token(lip, 2, yyLength()-2);
 	  return (BIN_NUM);
 	}
 	yyUnget();
@@ -782,14 +780,13 @@ int MYSQLlex(void *arg, void *yythd)
       if (c == '.' && ident_map[yyPeek()])
 	lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
 
-      yylval->lex_str= get_token(lip, yyLength());
+      yylval->lex_str= get_token(lip, 0, yyLength());
       return(result_state);
 
     case MY_LEX_USER_VARIABLE_DELIMITER:	// Found quote char
     {
       uint double_quotes= 0;
       char quote_char= c;                       // Used char
-      lip->tok_start=lip->ptr;			// Skip first `
       while ((c=yyGet()))
       {
 	int var_length;
@@ -813,19 +810,20 @@ int MYSQLlex(void *arg, void *yythd)
 #endif
       }
       if (double_quotes)
-	yylval->lex_str=get_quoted_token(lip, yyLength() - double_quotes,
+	yylval->lex_str=get_quoted_token(lip, 1,
+                                         yyLength() - double_quotes -1,
 					 quote_char);
       else
-	yylval->lex_str=get_token(lip, yyLength());
+	yylval->lex_str=get_token(lip, 1, yyLength() -1);
       if (c == quote_char)
 	yySkip();			// Skip end `
       lip->next_state= MY_LEX_START;
       return(IDENT_QUOTED);
     }
-    case MY_LEX_INT_OR_REAL:		// Compleat int or incompleat real
+    case MY_LEX_INT_OR_REAL:		// Complete int or incomplete real
       if (c != '.')
       {					// Found complete integer number.
-	yylval->lex_str=get_token(lip, yyLength());
+	yylval->lex_str=get_token(lip, 0, yyLength());
 	return int_token(yylval->lex_str.str,yylval->lex_str.length);
       }
       // fall through
@@ -843,10 +841,10 @@ int MYSQLlex(void *arg, void *yythd)
 	  break;
 	}
 	while (my_isdigit(cs,yyGet())) ;
-	yylval->lex_str=get_token(lip, yyLength());
+	yylval->lex_str=get_token(lip, 0, yyLength());
 	return(FLOAT_NUM);
       }
-      yylval->lex_str=get_token(lip, yyLength());
+      yylval->lex_str=get_token(lip, 0, yyLength());
       return(DECIMAL_NUM);
 
     case MY_LEX_HEX_NUMBER:		// Found x'hexstring'
@@ -858,10 +856,9 @@ int MYSQLlex(void *arg, void *yythd)
 	return(ABORT_SYM);		// Illegal hex constant
       }
       yyGet();				// get_token makes an unget
-      yylval->lex_str=get_token(lip, length);
-      yylval->lex_str.str+=2;		// Skip x'
-      yylval->lex_str.length-=3;	// Don't count x' and last '
-      lip->yytoklen-=3;
+      yylval->lex_str=get_token(lip,
+                                2,          // skip x'
+                                length-3);  // don't count x' and last '
       return (HEX_NUM);
 
     case MY_LEX_BIN_NUMBER:           // Found b'bin-string'
@@ -871,11 +868,10 @@ int MYSQLlex(void *arg, void *yythd)
       if (c != '\'')
       return(ABORT_SYM);              // Illegal hex constant
       yyGet();                        // get_token makes an unget
-      yylval->lex_str= get_token(lip, length);
-      yylval->lex_str.str+= 2;        // Skip b'
-      yylval->lex_str.length-= 3;     // Don't count b' and last '
-      lip->yytoklen-= 3;
-      return (BIN_NUM); 
+      yylval->lex_str= get_token(lip,
+                                 2,         // skip b'
+                                 length-3); // don't count b' and last '
+      return (BIN_NUM);
 
     case MY_LEX_CMP_OP:			// Incomplete comparison operator
       if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
@@ -1047,7 +1043,7 @@ int MYSQLlex(void *arg, void *yythd)
       for (c=yyGet() ; 
 	   my_isalnum(cs,c) || c == '.' || c == '_' ||  c == '$';
 	   c= yyGet()) ;
-      yylval->lex_str=get_token(lip, yyLength());
+      yylval->lex_str=get_token(lip, 0, yyLength());
       return(LEX_HOSTNAME);
     case MY_LEX_SYSTEM_VAR:
       yylval->lex_str.str=(char*) lip->ptr;
@@ -1079,7 +1075,7 @@ int MYSQLlex(void *arg, void *yythd)
 	yyUnget();				// Put back 'c'
 	return(tokval);				// Was keyword
       }
-      yylval->lex_str=get_token(lip, length);
+      yylval->lex_str=get_token(lip, 0, length);
       return(result_state);
     }
   }

--- 1.515/sql/sql_yacc.yy	2007-04-27 17:14:32 -06:00
+++ 1.516/sql/sql_yacc.yy	2007-04-27 17:14:32 -06:00
@@ -4439,20 +4439,22 @@ select_item_list:
 select_item:
 	  remember_name select_item2 remember_end select_alias
 	  {
-	    if (add_item_to_list(YYTHD, $2))
+            THD *thd= YYTHD;
+            DBUG_ASSERT($1 < $3);
+
+	    if (add_item_to_list(thd, $2))
 	      MYSQL_YYABORT;
 	    if ($4.str)
             {
               $2->is_autogenerated_name= FALSE;
 	      $2->set_name($4.str, $4.length, system_charset_info);
             }
-	    else if (!$2->name) {
-	      char *str = $1;
-	      if (str[-1] == '`')
-	        str--;
-	      $2->set_name(str,(uint) ($3 - str), YYTHD->charset());
+	    else if (!$2->name)
+            {
+	      $2->set_name($1, (uint) ($3 - $1), thd->charset());
 	    }
 	  };
+
 
 remember_name:
 	{

--- 1.226/mysql-test/r/sp.result	2007-04-27 17:14:32 -06:00
+++ 1.227/mysql-test/r/sp.result	2007-04-27 17:14:32 -06:00
@@ -6118,6 +6118,13 @@ Warning	1265	Data truncated for column '
 Warning	1265	Data truncated for column 'bug5274_f1' at row 1
 DROP FUNCTION bug5274_f1|
 DROP FUNCTION bug5274_f2|
+drop procedure if exists proc_21513|
+create procedure proc_21513()`my_label`:BEGIN END|
+show create procedure proc_21513|
+Procedure	sql_mode	Create Procedure
+proc_21513		CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_21513`()
+`my_label`:BEGIN END
+drop procedure proc_21513|
 End of 5.0 tests.
 drop table t1,t2;
 CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;

--- 1.216/mysql-test/t/sp.test	2007-04-27 17:14:32 -06:00
+++ 1.217/mysql-test/t/sp.test	2007-04-27 17:14:32 -06:00
@@ -7054,6 +7054,17 @@ SELECT bug5274_f2()|
 DROP FUNCTION bug5274_f1|
 DROP FUNCTION bug5274_f2|
 
+#
+# Bug#21513 (SP having body starting with quoted label rendered unusable)
+#
+--disable_warnings
+drop procedure if exists proc_21513|
+--enable_warnings
+
+create procedure proc_21513()`my_label`:BEGIN END|
+show create procedure proc_21513|
+
+drop procedure proc_21513|
 
 ###
 --echo End of 5.0 tests.
Thread
bk commit into 5.0 tree (malff:1.2440) BUG#21513marc.alff28 Apr