List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:March 16 2011 5:49pm
Subject:bzr commit into mysql-5.5 branch (alexander.nozdrin:3374) Bug#11763413
View as plain text  
#At file:///home/alik/MySQL/bzr/00/bug56115/mysql-5.5-bug56115/ based on revid:build@stripped

 3374 Alexander Nozdrin	2011-03-16
      A patch for Bug#11763413 (invalid memory reads when PS selecting
      from information_schema tables).
      
      The problem was a bug in Materialized-cursor implementation.
      Materialized_cursor::open() called send_result_metadata() with items
      pointing to already closed table.
      
      The fix is to send metadata when the table is still open.
      
      NOTE: this is a "partial" fix: metadata are different with and without
      --cursor-protocol, but that's a different large problem, one indication
      of which is reported as Bug 24176.

    modified:
      mysql-test/r/ps.result
      mysql-test/t/ps.test
      sql/sql_cursor.cc
      tests/mysql_client_test.c
=== modified file 'mysql-test/r/ps.result'
--- a/mysql-test/r/ps.result	2010-11-13 15:05:02 +0000
+++ b/mysql-test/r/ps.result	2011-03-16 17:49:47 +0000
@@ -3731,5 +3731,17 @@ CREATE TABLE t1 (a INT);
 BEGIN;
 PREPARE stmt1 FROM "SELECT * FROM t1";
 DROP TABLE t1;
+
 #
-# End of 6.0 tests.
+# Bug#56115: invalid memory reads when PS selecting from
+#            information_schema tables
+# Bug#58701: crash in Field::make_field, cursor-protocol
+#
+
+SELECT *
+FROM (SELECT 1 UNION SELECT 2) t;
+1
+1
+2
+#
+# End of 5.5 tests.

=== modified file 'mysql-test/t/ps.test'
--- a/mysql-test/t/ps.test	2010-11-13 15:05:02 +0000
+++ b/mysql-test/t/ps.test	2011-03-16 17:49:47 +0000
@@ -3344,7 +3344,19 @@ connection default;
 DROP TABLE t1;
 disconnect con1;
 
+--echo
 --echo #
---echo # End of 6.0 tests.
+--echo # Bug#56115: invalid memory reads when PS selecting from
+--echo #            information_schema tables
+--echo # Bug#58701: crash in Field::make_field, cursor-protocol
+--echo #
+--echo
+
+SELECT *
+FROM (SELECT 1 UNION SELECT 2) t;
+
+
+--echo #
+--echo # End of 5.5 tests.
 
 ###########################################################################

=== modified file 'sql/sql_cursor.cc'
--- a/sql/sql_cursor.cc	2010-12-08 16:47:21 +0000
+++ b/sql/sql_cursor.cc	2011-03-16 17:49:47 +0000
@@ -46,7 +46,7 @@ class Materialized_cursor: public Server
 public:
   Materialized_cursor(select_result *result, TABLE *table);
 
-  int fill_item_list(THD *thd, List<Item> &send_result_set_metadata);
+  int send_result_set_metadata(THD *thd, List<Item> &send_result_set_metadata);
   virtual bool is_open() const { return table != 0; }
   virtual int open(JOIN *join __attribute__((unused)));
   virtual void fetch(ulong num_rows);
@@ -142,6 +142,12 @@ int mysql_open_cursor(THD *thd, select_r
     Materialized_cursor *materialized_cursor=
       result_materialize->materialized_cursor;
 
+    /*
+      NOTE: close_thread_tables() has been called in
+      mysql_execute_command(), so all tables except from the cursor
+      temporary table have been closed.
+    */
+
     if ((rc= materialized_cursor->open(0)))
     {
       delete materialized_cursor;
@@ -208,8 +214,8 @@ Materialized_cursor::Materialized_cursor
   @param send_result_set_metadata List of fields that would be sent.
 */
 
-int Materialized_cursor::fill_item_list(THD *thd,
-                                        List<Item> &send_result_set_metadata)
+int Materialized_cursor::send_result_set_metadata(
+  THD *thd, List<Item> &send_result_set_metadata)
 {
   Query_arena backup_arena;
   int rc;
@@ -241,6 +247,9 @@ int Materialized_cursor::fill_item_list(
     ident->db_name=    thd->strdup(send_field.db_name);
     ident->table_name= thd->strdup(send_field.table_name);
   }
+
+  rc= result->send_result_set_metadata(item_list, Protocol::SEND_NUM_ROWS);
+
 end:
   thd->restore_active_arena(this, &backup_arena);
   /* Check for thd->is_error() in case of OOM */
@@ -253,31 +262,29 @@ int Materialized_cursor::open(JOIN *join
   THD *thd= fake_unit.thd;
   int rc;
   Query_arena backup_arena;
+
   thd->set_n_backup_active_arena(this, &backup_arena);
-  /* Create a list of fields and start sequential scan */
+
+  /* Create a list of fields and start sequential scan. */
+
   rc= result->prepare(item_list, &fake_unit);
-  if (!rc && !(rc= table->file->ha_rnd_init(TRUE)))
-    is_rnd_inited= 1;
+  rc= !rc && table->file->ha_rnd_init(TRUE);
+  is_rnd_inited= !rc;
 
   thd->restore_active_arena(this, &backup_arena);
-  if (rc == 0)
-  {
-    /*
-      Now send the result set metadata to the client. We need to
-      do it here, as in Select_materialize::send_result_set_metadata the items
-      for column types are not yet created (send_result_set_metadata requires
-      a list of items). The new types may differ from the original
-      ones sent at prepare if some of them were altered by MySQL
-      HEAP tables mechanism -- used when create_tmp_field_from_item
-      may alter the original column type.
 
-      We can't simply supply SEND_EOF flag to send_result_set_metadata, because
-      send_result_set_metadata doesn't flush the network buffer.
-    */
-    rc= result->send_result_set_metadata(item_list, Protocol::SEND_NUM_ROWS);
+  /* Commit or rollback metadata in the client-server protocol. */
+
+  if (!rc)
+  {
     thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
     result->send_eof();
   }
+  else
+  {
+    result->abort_result_set();
+  }
+
   return rc;
 }
 
@@ -363,6 +370,7 @@ Materialized_cursor::~Materialized_curso
 bool Select_materialize::send_result_set_metadata(List<Item> &list, uint flags)
 {
   DBUG_ASSERT(table == 0);
+
   if (create_result_table(unit->thd, unit->get_unit_column_types(),
                           FALSE, thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS, ""))
     return TRUE;
@@ -370,13 +378,14 @@ bool Select_materialize::send_result_set
   materialized_cursor= new (&table->mem_root)
                        Materialized_cursor(result, table);
 
-  if (! materialized_cursor)
+  if (!materialized_cursor)
   {
     free_tmp_table(table->in_use, table);
     table= 0;
     return TRUE;
   }
-  if (materialized_cursor->fill_item_list(unit->thd, list))
+
+  if (materialized_cursor->send_result_set_metadata(unit->thd, list))
   {
     delete materialized_cursor;
     table= 0;

=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c	2011-03-15 12:57:36 +0000
+++ b/tests/mysql_client_test.c	2011-03-16 17:49:47 +0000
@@ -15682,8 +15682,11 @@ static void test_bug13488()
   check_execute(stmt1, rc);
 
   if (!opt_silent)
-    printf("data is: %s", (f1 == 1 && f2 == 1 && f3 == 2)?"OK":
-           "wrong");
+  {
+    printf("data: f1: %d; f2: %d; f3: %d\n", f1, f2, f3);
+    printf("data is: %s\n",
+           (f1 == 1 && f2 == 1 && f3 == 2) ? "OK" : "wrong");
+  }
   DIE_UNLESS(f1 == 1 && f2 == 1 && f3 == 2);
   rc= mysql_query(mysql, "drop table t1, t2");
   myquery(rc);


Attachment: [text/bzr-bundle] bzr/alexander.nozdrin@oracle.com-20110316174947-ir5172ohqbumynp4.bundle
Thread
bzr commit into mysql-5.5 branch (alexander.nozdrin:3374) Bug#11763413Alexander Nozdrin16 Mar