15688738 problem in database/mysql s11-update
authorRamesh Maddali<ramesh.maddali@oracle.com>
Wed, 17 Jul 2013 00:17:02 -0700
branchs11-update
changeset 2680 70e041ba5b04
parent 2679 54a3a004ee1d
child 2681 f7ee98f5749e
15688738 problem in database/mysql
components/mysql-5-1/mysql-51test.p5m
components/mysql-5-1/patches/bug40980.patch
components/mysql-5-1/patches/bug68591.patch
--- a/components/mysql-5-1/mysql-51test.p5m	Mon Jul 15 23:01:56 2013 -0700
+++ b/components/mysql-5-1/mysql-51test.p5m	Wed Jul 17 00:17:02 2013 -0700
@@ -477,6 +477,7 @@
 file path=usr/mysql/5.1/mysql-test/r/bool.result
 file path=usr/mysql/5.1/mysql-test/r/bootstrap.result
 file path=usr/mysql/5.1/mysql-test/r/bug46080.result
+file path=usr/mysql/5.1/mysql-test/r/bug40980.result
 file path=usr/mysql/5.1/mysql-test/r/bulk_replace.result
 file path=usr/mysql/5.1/mysql-test/r/cache_innodb.result
 file path=usr/mysql/5.1/mysql-test/r/case.result
@@ -3297,6 +3298,7 @@
 file path=usr/mysql/5.1/mysql-test/t/bootstrap.test
 file path=usr/mysql/5.1/mysql-test/t/bug46080-master.opt
 file path=usr/mysql/5.1/mysql-test/t/bug46080.test
+file path=usr/mysql/5.1/mysql-test/t/bug40980.test
 file path=usr/mysql/5.1/mysql-test/t/bulk_replace.test
 file path=usr/mysql/5.1/mysql-test/t/cache_innodb-master.opt
 file path=usr/mysql/5.1/mysql-test/t/cache_innodb.test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/mysql-5-1/patches/bug40980.patch	Wed Jul 17 00:17:02 2013 -0700
@@ -0,0 +1,113 @@
+# Fixes Solaris bug #15688738
+# ===========================
+
+--- storage/myisam/mi_delete_table.c	2006-12-31 00:32:21 +0000
++++ storage/myisam/mi_delete_table.c	2010-04-01 14:49:02 +0000
+@@ -19,6 +19,41 @@
+ 
+ #include "fulltext.h"
+ 
++
++/**
++  Remove MyISAM data/index file safely
++
++  @details
++    If name is a symlink and file it is pointing to is not in
++    data directory, file is also removed.
++
++  @param name    file to remove
++  
++  @returns
++    0 on success or my_errno on failure
++*/
++
++static int _mi_safe_delete_file(const char *name)
++{
++  DBUG_ENTER("_mi_safe_delete_file");
++  if (my_is_symlink(name) && (*myisam_test_invalid_symlink)(name))
++  {
++    /*
++      Symlink is pointing to file in data directory.
++      Remove symlink, keep file.
++    */
++    if (my_delete(name, MYF(MY_WME)))
++      DBUG_RETURN(my_errno);
++  }
++  else
++  {
++    if (my_delete_with_symlink(name, MYF(MY_WME)))
++      DBUG_RETURN(my_errno);
++  }
++  DBUG_RETURN(0);
++}
++
++
+ int mi_delete_table(const char *name)
+ {
+   char from[FN_REFLEN];
+@@ -58,12 +93,12 @@ int mi_delete_table(const char *name)
+ #endif /* USE_RAID */
+ 
+   fn_format(from,name,"",MI_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
+-  if (my_delete_with_symlink(from, MYF(MY_WME)))
++  if (_mi_safe_delete_file(from))
+     DBUG_RETURN(my_errno);
+   fn_format(from,name,"",MI_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
+ #ifdef USE_RAID
+   if (raid_type)
+     DBUG_RETURN(my_raid_delete(from, raid_chunks, MYF(MY_WME)) ? my_errno : 0);
+ #endif
+-  DBUG_RETURN(my_delete_with_symlink(from, MYF(MY_WME)) ? my_errno : 0);
++  DBUG_RETURN(_mi_safe_delete_file(from));
+ }
+
+--- mysql-test/r/bug40980.result	1970-01-01 01:00:00.000000000 +0100
++++ mysql-test/r/bug40980.result	2013-06-20 21:42:12.280326900 +0200
+@@ -0,0 +1,14 @@
++drop table if exists t1,t2,t7,t8,t9;
++drop database if exists mysqltest;
++#
++# BUG#40980 - Drop table can remove another MyISAM table's
++#             data and index files
++#
++CREATE TABLE user(a INT) DATA DIRECTORY='MYSQL_TMP_DIR/mysql'
++                             INDEX DIRECTORY='MYSQL_TMP_DIR/mysql';
++FLUSH TABLE user;
++# Symlinking mysql database to tmpdir
++FLUSH TABLE mysql.user;
++DROP TABLE user;
++FLUSH TABLE mysql.user;
++SELECT * FROM mysql.user;
+
+--- mysql-test/t/bug40980.test	1970-01-01 01:00:00.000000000 +0100
++++ mysql-test/t/bug40980.test	2013-06-20 21:41:50.813398500 +0200
+@@ -0,0 +1,29 @@
++--source include/have_symlink.inc
++--source include/not_windows.inc
++
++--disable_warnings
++drop table if exists t1,t2,t7,t8,t9;
++drop database if exists mysqltest;
++--enable_warnings
++
++--echo #
++--echo # BUG#40980 - Drop table can remove another MyISAM table's
++--echo #             data and index files
++--echo #
++--mkdir $MYSQL_TMP_DIR/mysql 
++--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
++eval CREATE TABLE user(a INT) DATA DIRECTORY='$MYSQL_TMP_DIR/mysql'
++                             INDEX DIRECTORY='$MYSQL_TMP_DIR/mysql';
++FLUSH TABLE user;
++--echo # Symlinking mysql database to tmpdir
++--remove_file $MYSQL_TMP_DIR/mysql/user.MYD
++--remove_file $MYSQL_TMP_DIR/mysql/user.MYI
++--rmdir $MYSQL_TMP_DIR/mysql
++--exec ln -s $MYSQLD_DATADIR/mysql $MYSQL_TMP_DIR/mysql
++FLUSH TABLE mysql.user;
++DROP TABLE user;
++FLUSH TABLE mysql.user;
++--disable_result_log
++SELECT * FROM mysql.user;
++--enable_result_log
++--remove_file $MYSQL_TMP_DIR/mysql
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/mysql-5-1/patches/bug68591.patch	Wed Jul 17 00:17:02 2013 -0700
@@ -0,0 +1,287 @@
+# Fixes Solaris bug #15688738
+# ===========================
+
+--- sql/spatial.h	revid:[email protected]
++++ sql/spatial.h	2013-06-26 05:14:10 +0000
+@@ -324,6 +324,26 @@
+   {
+     return (cur_data + data_amount > m_data_end);
+   }
++
++  /**
++     Check if there're enough points remaining as requested
++
++     Need to perform the calculation in logical units, since multiplication
++     can overflow the size data type.
++
++     @arg data              pointer to the begining of the points array
++     @arg expected_points   number of points expected
++     @arg extra_point_space extra space for each point element in the array
++     @return               true if there are not enough points
++  */
++  inline bool not_enough_points(const char *data, uint32 expected_points,
++                                uint32 extra_point_space = 0) const
++  {
++    return (m_data_end < data ||
++            (expected_points > ((m_data_end - data) /
++                                (POINT_DATA_SIZE + extra_point_space))));
++  }
++
+   const char *m_data;
+   const char *m_data_end;
+ };
+
+=== modified file 'sql/spatial.cc'
+--- sql/spatial.cc	revid:[email protected]
++++ sql/spatial.cc	2013-06-26 05:14:10 +0000
+@@ -393,7 +393,7 @@
+   points= uint4korr(data);
+   data+= 4;
+ 
+-  if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points))
++  if (not_enough_points(data, points, offset))
+     return 0;
+ 
+   /* Calculate MBR for points */
+@@ -476,9 +476,16 @@
+ 
+ uint32 Gis_line_string::get_data_size() const 
+ {
++  size_t n_points;
+   if (no_data(m_data, 4))
+     return GET_SIZE_ERROR;
+-  return 4 + uint4korr(m_data) * POINT_DATA_SIZE;
++
++  n_points= uint4korr(m_data);
++
++  if (not_enough_points(m_data + 4, n_points))
++    return GET_SIZE_ERROR;
++
++  return 4 + n_points * POINT_DATA_SIZE;
+ }
+ 
+ 
+@@ -548,7 +555,7 @@
+   data += 4;
+ 
+   if (n_points < 1 ||
+-      no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) ||
++      not_enough_points(data, n_points) ||
+       txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
+     return 1;
+ 
+@@ -585,7 +592,7 @@
+     return 1;
+   n_points= uint4korr(data);
+   data+= 4;
+-  if (n_points < 1 || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
++  if (n_points < 1 || not_enough_points(data, n_points))
+     return 1;
+ 
+   get_point(&prev_x, &prev_y, data);
+@@ -619,7 +626,7 @@
+     return 0;
+   }
+   data+= 4;
+-  if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
++  if (n_points == 0 || not_enough_points(data, n_points))
+     return 1;
+ 
+   /* Get first point */
+@@ -690,9 +697,16 @@
+ 
+   while (n_linear_rings--)
+   {
++    size_t n_points;
+     if (no_data(data, 4))
+       return GET_SIZE_ERROR;
+-    data+= 4 + uint4korr(data)*POINT_DATA_SIZE;
++    n_points= uint4korr(data);
++    data+= 4;
++
++    if (not_enough_points(data, n_points))
++      return GET_SIZE_ERROR;
++
++    data+= n_points * POINT_DATA_SIZE;
+   }
+   return (uint32) (data - m_data);
+ }
+@@ -786,8 +800,9 @@
+       return 1;
+     n_points= uint4korr(data);
+     data+= 4;
+-    if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
+-	txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
++
++    if (not_enough_points(data, n_points) ||
++        txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+       return 1;
+     txt->qs_append('(');
+     data= append_points(txt, n_points, data, 0);
+@@ -840,7 +855,7 @@
+     if (no_data(data, 4))
+       return 1;
+     n_points= uint4korr(data);
+-    if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
++    if (not_enough_points(data, n_points))
+       return 1;
+     get_point(&prev_x, &prev_y, data+4);
+     data+= (4+SIZEOF_STORED_DOUBLE*2);
+@@ -876,7 +891,7 @@
+   n_points= uint4korr(data);
+   data+= 4;
+   length= n_points * POINT_DATA_SIZE;
+-  if (no_data(data, length) || result->reserve(1+4+4+ length))
++  if (not_enough_points(data, n_points) || result->reserve(1+4+4+ length))
+     return 1;
+ 
+   result->q_append((char) wkb_ndr);
+@@ -922,7 +937,7 @@
+   n_points= uint4korr(data);
+   points_size= n_points * POINT_DATA_SIZE;
+   data+= 4;
+-  if (no_data(data, points_size) || result->reserve(1+4+4+ points_size))
++  if (not_enough_points(data, n_points) || result->reserve(1+4+4+ points_size))
+     return 1;
+ 
+   result->q_append((char) wkb_ndr);
+@@ -964,7 +979,7 @@
+       return 1;
+     org_n_points= n_points= uint4korr(data);
+     data+= 4;
+-    if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
++    if (not_enough_points(data, n_points))
+       return 1;
+     get_point(&prev_x, &prev_y, data);
+     data+= (SIZEOF_STORED_DOUBLE*2);
+@@ -1021,14 +1036,21 @@
+ 
+ /***************************** MultiPoint *******************************/
+ 
+-uint32 Gis_multi_point::get_data_size() const 
++uint32 Gis_multi_point::get_data_size() const
+ {
++  size_t n_points;
++
+   if (no_data(m_data, 4))
+     return GET_SIZE_ERROR;
+-  return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE);
++
++  n_points= uint4korr(m_data);
++
++  if (not_enough_points(m_data + 4, n_points, WKB_HEADER_SIZE))
++    return GET_SIZE_ERROR;
++
++  return 4 + n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE);
+ }
+ 
+-
+ bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
+ {
+   uint32 n_points= 0;
+@@ -1085,24 +1107,26 @@
+   return proper_size;
+ }
+ 
+-
+ bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const
+ {
+   uint32 n_points;
+-  if (no_data(m_data, 4))
++  const char *data= m_data;
++
++  if (no_data(data, 4))
+     return 1;
+ 
+-  n_points= uint4korr(m_data);
+-  if (no_data(m_data+4,
+-	      n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) ||
++  n_points= uint4korr(data);
++  data+= 4;
++
++  if (not_enough_points(data, n_points, WKB_HEADER_SIZE) ||
+       txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+     return 1;
+-  *end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE);
+-  txt->length(txt->length()-1);			// Remove end ','
++
++  *end= append_points(txt, n_points, data, WKB_HEADER_SIZE);
++  txt->length(txt->length()-1);                 // Remove end ','
+   return 0;
+ }
+ 
+-
+ bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const
+ {
+   return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 0;
+@@ -1155,11 +1179,20 @@
+ 
+   while (n_line_strings--)
+   {
++    size_t n_points;
++
+     if (no_data(data, WKB_HEADER_SIZE + 4))
+       return GET_SIZE_ERROR;
+-    data+= (WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) *
+-	    POINT_DATA_SIZE);
++
++    n_points= uint4korr(data + WKB_HEADER_SIZE);
++    data+= WKB_HEADER_SIZE + 4;
++
++    if (not_enough_points(data, n_points))
++      return GET_SIZE_ERROR;
++
++    data+= n_points * POINT_DATA_SIZE;
+   }
++
+   return (uint32) (data - m_data);
+ }
+ 
+@@ -1251,7 +1284,7 @@
+       return 1;
+     n_points= uint4korr(data + WKB_HEADER_SIZE);
+     data+= WKB_HEADER_SIZE + 4;
+-    if (no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
++    if (not_enough_points(data, n_points) ||
+ 	txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+       return 1;
+     txt->qs_append('(');
+@@ -1312,7 +1345,7 @@
+       return 1;
+     n_points= uint4korr(data + WKB_HEADER_SIZE);
+     length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points;
+-    if (no_data(data, length))
++    if (not_enough_points(data + WKB_HEADER_SIZE + 4, n_points))
+       return 1;
+     if (!--num)
+       break;
+@@ -1410,9 +1443,16 @@
+ 
+     while (n_linear_rings--)
+     {
++      size_t n_points;
+       if (no_data(data, 4))
+-	return GET_SIZE_ERROR;
+-      data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
++        return GET_SIZE_ERROR;
++      n_points= uint4korr(data);
++      data+= 4;
++
++      if (not_enough_points(data, n_points))
++        return GET_SIZE_ERROR;
++
++      data+= n_points * POINT_DATA_SIZE;
+     }
+   }
+   return (uint32) (data - m_data);
+@@ -1512,7 +1552,7 @@
+         return 1;
+       uint32 n_points= uint4korr(data);
+       data+= 4;
+-      if (no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
++      if (not_enough_points(data, n_points) ||
+ 	  txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
+ 		       512))
+ 	return 1;
+
+=== modified file 'sql/spatial.h'