components/mysql-5-1/patches/bug68591.patch
author Sreedhar S <sreedhar.sreedhargadda@oracle.com>
Tue, 23 Jul 2013 11:30:45 -0700
branchs11u1-sru
changeset 2686 1362b3693ee1
permissions -rw-r--r--
15688738 problem in DATABASE/MYSQL

# 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'