MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:October 26 2009 10:01am
Subject:bzr commit into mysql-5.1-bugteam branch (joro:3197) Bug#47412
View as plain text  
#At file:///home/kgeorge/mysql/work/B47412-5.1-bugteam/ based on revid:joro@stripped

 3197 Georgi Kodinov	2009-10-26
      Bug #47412: Valgrind warnings / user can read uninitalized memory using 
      SP variables
      
      A function call may end without throwing an error or without setting 
      the return value. This can happen when e.g. an error occurs while 
      calculating the return value.
      
      Fixed by setting the value to NULL when error occurs during evaluation
      of an expression.

    added:
      mysql-test/r/sp-bugs.result
      mysql-test/t/sp-bugs.test
    modified:
      sql/sp_head.cc
=== added file 'mysql-test/r/sp-bugs.result'
--- a/mysql-test/r/sp-bugs.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/sp-bugs.result	2009-10-26 09:55:57 +0000
@@ -0,0 +1,47 @@
+#
+# Bug #47412: Valgrind warnings / user can read uninitalized memory
+# using SP variables
+#
+CREATE SCHEMA testdb;
+USE testdb;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+RETURN f_not_exists () ;
+END|
+CREATE PROCEDURE p3 ( arg1 VARCHAR(32) )
+BEGIN
+CALL p_not_exists ( );
+END|
+# should not return valgrind warnings
+CALL p3 ( f2 () );
+ERROR 42000: PROCEDURE testdb.p_not_exists does not exist
+DROP SCHEMA testdb;
+CREATE SCHEMA testdb;
+USE testdb;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+RETURN f_not_exists () ;
+END|
+CREATE PROCEDURE p3 ( arg2 INTEGER )
+BEGIN
+CALL p_not_exists ( );
+END|
+# should not return valgrind warnings
+CALL p3 ( f2 () );
+ERROR 42000: PROCEDURE testdb.p_not_exists does not exist
+DROP SCHEMA testdb;
+CREATE SCHEMA testdb;
+USE testdb;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+RETURN f_not_exists () ;
+END|
+# should not return valgrind warnings
+SELECT f2 ();
+f2 ()
+NULL
+DROP SCHEMA testdb;
+End of 5.1 tests

=== added file 'mysql-test/t/sp-bugs.test'
--- a/mysql-test/t/sp-bugs.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/sp-bugs.test	2009-10-26 09:55:57 +0000
@@ -0,0 +1,61 @@
+# Test file for stored procedure bugfixes
+
+--echo #
+--echo # Bug #47412: Valgrind warnings / user can read uninitalized memory
+--echo # using SP variables
+--echo #
+
+CREATE SCHEMA testdb;
+USE testdb;
+DELIMITER |;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+   DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+   RETURN f_not_exists () ;
+END|
+CREATE PROCEDURE p3 ( arg1 VARCHAR(32) )
+BEGIN
+   CALL p_not_exists ( );
+END|
+DELIMITER ;|
+--echo # should not return valgrind warnings
+--error ER_SP_DOES_NOT_EXIST
+CALL p3 ( f2 () );
+
+DROP SCHEMA testdb;
+
+CREATE SCHEMA testdb;
+USE testdb;
+DELIMITER |;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+   DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+   RETURN f_not_exists () ;
+END|
+CREATE PROCEDURE p3 ( arg2 INTEGER )
+BEGIN
+   CALL p_not_exists ( );
+END|
+DELIMITER ;|
+--echo # should not return valgrind warnings
+--error ER_SP_DOES_NOT_EXIST
+CALL p3 ( f2 () );
+
+DROP SCHEMA testdb;
+
+CREATE SCHEMA testdb;
+USE testdb;
+DELIMITER |;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+   DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+   RETURN f_not_exists () ;
+END|
+DELIMITER ;|
+--echo # should not return valgrind warnings
+SELECT f2 ();
+
+DROP SCHEMA testdb;
+
+
+--echo End of 5.1 tests

=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc	2009-10-16 10:29:42 +0000
+++ b/sql/sp_head.cc	2009-10-26 09:55:57 +0000
@@ -334,16 +334,18 @@ bool
 sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
 {
   Item *expr_item;
+  enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
+  bool save_abort_on_warning= thd->abort_on_warning;
+  bool save_stmt_modified_non_trans_table= 
+    thd->transaction.stmt.modified_non_trans_table;
 
   DBUG_ENTER("sp_eval_expr");
 
   if (!*expr_item_ptr)
-    DBUG_RETURN(TRUE);
+    goto error;
 
   if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr)))
-    DBUG_RETURN(TRUE);
-
-  bool err_status= FALSE;
+    goto error;
 
   /*
     Set THD flags to emit warnings/errors in case of overflow/type errors
@@ -352,10 +354,6 @@ sp_eval_expr(THD *thd, Field *result_fie
     Save original values and restore them after save.
   */
   
-  enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
-  bool save_abort_on_warning= thd->abort_on_warning;
-  bool save_stmt_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table;
-
   thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
   thd->abort_on_warning=
     thd->variables.sql_mode &
@@ -370,13 +368,18 @@ sp_eval_expr(THD *thd, Field *result_fie
   thd->abort_on_warning= save_abort_on_warning;
   thd->transaction.stmt.modified_non_trans_table= save_stmt_modified_non_trans_table;
 
-  if (thd->is_error())
-  {
-    /* Return error status if something went wrong. */
-    err_status= TRUE;
-  }
+  if (!thd->is_error())
+    DBUG_RETURN(FALSE);
 
-  DBUG_RETURN(err_status);
+error:
+  /*
+    In case of error during evaluation, leave the result field set to NULL.
+    Sic: we can't do it in the beginning of the function because the 
+    result field might be needed for its own re-evaluation, e.g. case of 
+    set x = x + 1;
+  */
+  result_field->set_null();
+  DBUG_RETURN (TRUE);
 }
 
 


Attachment: [text/bzr-bundle] bzr/joro@sun.com-20091026095557-euhe1z9oxtgkw35h.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (joro:3197) Bug#47412Georgi Kodinov26 Oct