List:Commits« Previous MessageNext Message »
From:Alexander Barkov Date:June 7 2008 10:32am
Subject:commit into mysql-6.0-rpl branch (bar:2655) Bug#34391
View as plain text  
#At file:///home/bar/mysql-bzr/mysql-6.0.b34391/

 2655 Alexander Barkov	2008-06-07
      Bug#34391 Character sets: crash if char(), utf32, innodb
      Problem: mbminlen in dict_col_t and dtype_t uses 2 bits,
      which cannot store the value of "4" required for UTF32.
      Fix: adding macros to pack/unpack the range 1..4 to 0..3.
added:
  mysql-test/r/innodb-utf32.result
  mysql-test/t/innodb-utf32.test
modified:
  storage/innobase/data/data0type.c
  storage/innobase/dict/dict0mem.c
  storage/innobase/handler/ha_innodb.cc
  storage/innobase/include/data0type.h
  storage/innobase/include/data0type.ic
  storage/innobase/include/dict0dict.ic
  storage/innobase/include/dict0mem.h
  storage/innobase/row/row0ins.c
  storage/innobase/row/row0row.c
  storage/innobase/row/row0sel.c
  storage/innobase/row/row0upd.c

=== added file 'mysql-test/r/innodb-utf32.result'
--- a/mysql-test/r/innodb-utf32.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb-utf32.result	2008-06-07 08:28:10 +0000
@@ -0,0 +1,10 @@
+drop table if exists t1;
+create table t1 (s1 char(1) character set utf32) engine=innodb;
+insert into t1 values ('a'),('b'),('c');
+select s1, hex(s1) from t1 order by s1;
+s1	hex(s1)
+a	00000061
+b	00000062
+c	00000063
+drop table t1;
+End of 6.0 tests

=== added file 'mysql-test/t/innodb-utf32.test'
--- a/mysql-test/t/innodb-utf32.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb-utf32.test	2008-06-07 08:28:10 +0000
@@ -0,0 +1,16 @@
+-- source include/have_innodb.inc
+-- source include/have_utf32.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Bug#34391 Character sets: crash if char(), utf32, innodb
+#
+create table t1 (s1 char(1) character set utf32) engine=innodb;
+insert into t1 values ('a'),('b'),('c');
+select s1, hex(s1) from t1 order by s1;
+drop table t1;
+
+--echo End of 6.0 tests

=== modified file 'storage/innobase/data/data0type.c'
--- a/storage/innobase/data/data0type.c	2007-07-10 11:37:43 +0000
+++ b/storage/innobase/data/data0type.c	2008-06-07 08:28:10 +0000
@@ -197,7 +197,7 @@
 		ut_a((type->prtype & DATA_MYSQL_TYPE_MASK) < DATA_N_SYS_COLS);
 	}
 
-	ut_a(type->mbminlen <= type->mbmaxlen);
+	ut_a(dtype_unpack_mbminlen(type) <= dtype_unpack_mbmaxlen(type));
 
 	return(TRUE);
 }

=== modified file 'storage/innobase/dict/dict0mem.c'
--- a/storage/innobase/dict/dict0mem.c	2007-08-28 00:18:14 +0000
+++ b/storage/innobase/dict/dict0mem.c	2008-06-07 08:28:10 +0000
@@ -218,8 +218,8 @@
 
 	dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen);
 
-	col->mbminlen = (unsigned int) mbminlen;
-	col->mbmaxlen = (unsigned int) mbmaxlen;
+	dcol_pack_mbminlen(col, (unsigned int) mbminlen);
+	dcol_pack_mbmaxlen(col, (unsigned int) mbmaxlen);
 }
 
 /**************************************************************************

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2008-04-01 13:19:15 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2008-06-07 08:28:10 +0000
@@ -3235,8 +3235,8 @@
 
 		templ->charset = dtype_get_charset_coll_noninline(
 				index->table->cols[i].prtype);
-		templ->mbminlen = index->table->cols[i].mbminlen;
-		templ->mbmaxlen = index->table->cols[i].mbmaxlen;
+		templ->mbminlen = dcol_unpack_mbminlen(&(index->table->cols[i]));
+		templ->mbmaxlen = dcol_unpack_mbmaxlen(&(index->table->cols[i]));
 		templ->is_unsigned = index->table->cols[i].prtype
 							& DATA_UNSIGNED;
 		if (templ->type == DATA_BLOB) {

=== modified file 'storage/innobase/include/data0type.h'
--- a/storage/innobase/include/data0type.h	2006-09-21 09:48:26 +0000
+++ b/storage/innobase/include/data0type.h	2008-06-07 08:28:10 +0000
@@ -437,12 +437,18 @@
 					the string, MySQL uses 1 or 2
 					bytes to store the string length) */
 
-	unsigned	mbminlen:2;	/* minimum length of a
+	unsigned	mb_minlen:2;	/* minimum length of a
 					character, in bytes */
-	unsigned	mbmaxlen:3;	/* maximum length of a
+	unsigned	mb_maxlen:3;	/* maximum length of a
 					character, in bytes */
 };
 
+#define dtype_unpack_mbminlen(x) ((x)->mb_minlen + 1)
+#define dtype_unpack_mbmaxlen(x) ((x)->mb_maxlen + 1)
+#define dtype_pack_mbminlen(x,l) ((x)->mb_minlen= l - 1)
+#define dtype_pack_mbmaxlen(x,l) ((x)->mb_maxlen= l - 1)
+
+
 #ifndef UNIV_NONINL
 #include "data0type.ic"
 #endif

=== modified file 'storage/innobase/include/data0type.ic'
--- a/storage/innobase/include/data0type.ic	2007-01-05 02:51:34 +0000
+++ b/storage/innobase/include/data0type.ic	2008-06-07 08:28:10 +0000
@@ -88,8 +88,9 @@
 	ulint	mbmaxlen;
 
 	dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen);
-	type->mbminlen = mbminlen;
-	type->mbmaxlen = mbmaxlen;
+	ut_ad(mbminlen > 0 && mbmaxlen > 0);
+	dtype_pack_mbminlen(type, mbminlen);
+	dtype_pack_mbmaxlen(type, mbmaxlen);
 
 	ut_ad(dtype_validate(type));
 }
@@ -179,7 +180,7 @@
 	const dtype_t*	type)	/* in: type */
 {
 	ut_ad(type);
-	return(type->mbminlen);
+	return(dtype_unpack_mbminlen(type));
 }
 /*************************************************************************
 Gets the maximum length of a character, in bytes. */
@@ -192,7 +193,7 @@
 	const dtype_t*	type)	/* in: type */
 {
 	ut_ad(type);
-	return(type->mbmaxlen);
+	return(dtype_unpack_mbmaxlen(type));
 }
 
 /*************************************************************************
@@ -558,5 +559,6 @@
 	const dtype_t*	type)	/* in: type */
 {
 	return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
-					type->mbminlen, type->mbmaxlen) > 0);
+					dtype_unpack_mbminlen(type),
+					dtype_unpack_mbmaxlen(type)) > 0);
 }

=== modified file 'storage/innobase/include/dict0dict.ic'
--- a/storage/innobase/include/dict0dict.ic	2007-07-10 14:34:21 +0000
+++ b/storage/innobase/include/dict0dict.ic	2008-06-07 08:28:10 +0000
@@ -26,8 +26,8 @@
 	type->mtype = col->mtype;
 	type->prtype = col->prtype;
 	type->len = col->len;
-	type->mbminlen = col->mbminlen;
-	type->mbmaxlen = col->mbmaxlen;
+	dtype_pack_mbminlen(type, dcol_unpack_mbminlen(col));
+	dtype_pack_mbmaxlen(type, dcol_unpack_mbmaxlen(col));
 }
 
 #ifdef UNIV_DEBUG
@@ -64,7 +64,8 @@
 	const dict_col_t*	col)	/* in: column */
 {
 	return(dtype_get_min_size_low(col->mtype, col->prtype, col->len,
-				      col->mbminlen, col->mbmaxlen));
+				      dcol_unpack_mbminlen(col),
+				      dcol_unpack_mbmaxlen(col)));
 }
 /***************************************************************************
 Returns the maximum size of the column. */
@@ -87,7 +88,8 @@
 	const dict_col_t*	col)	/* in: column */
 {
 	return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len,
-					col->mbminlen, col->mbmaxlen));
+					dcol_unpack_mbminlen(col),
+					dcol_unpack_mbmaxlen(col)));
 }
 /***************************************************************************
 Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.

=== modified file 'storage/innobase/include/dict0mem.h'
--- a/storage/innobase/include/dict0mem.h	2008-03-27 01:56:18 +0000
+++ b/storage/innobase/include/dict0mem.h	2008-06-07 08:28:10 +0000
@@ -145,9 +145,9 @@
 					the string, MySQL uses 1 or 2
 					bytes to store the string length) */
 
-	unsigned	mbminlen:2;	/* minimum length of a
+	unsigned	mb_minlen:2;	/* minimum length of a
 					character, in bytes */
-	unsigned	mbmaxlen:3;	/* maximum length of a
+	unsigned	mb_maxlen:3;	/* maximum length of a
 					character, in bytes */
 	/*----------------------*/
 	/* End of definitions copied from dtype_t */
@@ -159,6 +159,11 @@
 					of an index */
 };
 
+#define dcol_unpack_mbminlen(x) ((x)->mb_minlen + 1)
+#define dcol_unpack_mbmaxlen(x) ((x)->mb_maxlen + 1)
+#define dcol_pack_mbminlen(x,l) ((x)->mb_minlen= l - 1)
+#define dcol_pack_mbmaxlen(x,l) ((x)->mb_maxlen= l - 1)
+
 /* DICT_MAX_INDEX_COL_LEN is measured in bytes and is the maximum
 indexed column length (or indexed prefix length). It is set to 3*256,
 so that one can create a column prefix index on 256 characters of a

=== modified file 'storage/innobase/row/row0ins.c'
--- a/storage/innobase/row/row0ins.c	2007-07-10 11:37:43 +0000
+++ b/storage/innobase/row/row0ins.c	2008-06-07 08:28:10 +0000
@@ -500,7 +500,8 @@
 				if (ufield->new_val.len != UNIV_SQL_NULL
 				    && dtype_get_at_most_n_mbchars(
 					col->prtype,
-					col->mbminlen, col->mbmaxlen,
+					dcol_unpack_mbminlen(col),
+					dcol_unpack_mbmaxlen(col),
 					col->len,
 					ufield->new_val.len,
 					ufield->new_val.data)
@@ -535,7 +536,7 @@
 						  parent_ufield->new_val.data,
 						  parent_ufield->new_val.len);
 
-					switch (UNIV_EXPECT(col->mbminlen,1)) {
+					switch (UNIV_EXPECT(dcol_unpack_mbminlen(col),1)) {
 					default:
 						ut_error;
 					case 1:
@@ -2226,7 +2227,9 @@
 				= dict_field_get_col(ind_field);
 
 			field->len = dtype_get_at_most_n_mbchars(
-				col->prtype, col->mbminlen, col->mbmaxlen,
+				col->prtype,
+				dcol_unpack_mbminlen(col),
+				dcol_unpack_mbmaxlen(col),
 				ind_field->prefix_len,
 				row_field->len, row_field->data);
 		} else {

=== modified file 'storage/innobase/row/row0row.c'
--- a/storage/innobase/row/row0row.c	2007-07-10 11:37:43 +0000
+++ b/storage/innobase/row/row0row.c	2008-06-07 08:28:10 +0000
@@ -146,7 +146,9 @@
 		    && dfield_get_len(dfield2) != UNIV_SQL_NULL) {
 
 			storage_len = dtype_get_at_most_n_mbchars(
-				col->prtype, col->mbminlen, col->mbmaxlen,
+				col->prtype,
+				dcol_unpack_mbminlen(col),
+				dcol_unpack_mbmaxlen(col),
 				ind_field->prefix_len,
 				dfield_get_len(dfield2), dfield2->data);
 
@@ -426,8 +428,8 @@
 				dfield_set_len(dfield,
 					       dtype_get_at_most_n_mbchars(
 						       dtype->prtype,
-						       dtype->mbminlen,
-						       dtype->mbmaxlen,
+						       dtype_unpack_mbminlen(dtype),
+						       dtype_unpack_mbmaxlen(dtype),
 						       clust_col_prefix_len,
 						       len, (char*) field));
 			}
@@ -530,8 +532,8 @@
 				dfield_set_len(dfield,
 					       dtype_get_at_most_n_mbchars(
 						       dtype->prtype,
-						       dtype->mbminlen,
-						       dtype->mbmaxlen,
+						       dtype_unpack_mbminlen(dtype),
+						       dtype_unpack_mbmaxlen(dtype),
 						       clust_col_prefix_len,
 						       len, (char*) field));
 			}
@@ -591,7 +593,9 @@
 		    && dfield->len != UNIV_SQL_NULL) {
 
 			dfield->len = dtype_get_at_most_n_mbchars(
-				col->prtype, col->mbminlen, col->mbmaxlen,
+				col->prtype,
+				dcol_unpack_mbminlen(col),
+				dcol_unpack_mbmaxlen(col),
 				field->prefix_len, dfield->len, dfield->data);
 		}
 	}

=== modified file 'storage/innobase/row/row0sel.c'
--- a/storage/innobase/row/row0sel.c	2008-04-01 13:19:15 +0000
+++ b/storage/innobase/row/row0sel.c	2008-06-07 08:28:10 +0000
@@ -107,7 +107,9 @@
 		if (ifield->prefix_len > 0 && clust_len != UNIV_SQL_NULL) {
 
 			clust_len = dtype_get_at_most_n_mbchars(
-				col->prtype, col->mbminlen, col->mbmaxlen,
+				col->prtype,
+				dcol_unpack_mbminlen(col),
+				dcol_unpack_mbmaxlen(col),
 				ifield->prefix_len,
 				clust_len, (char*) clust_field);
 		}

=== modified file 'storage/innobase/row/row0upd.c'
--- a/storage/innobase/row/row0upd.c	2007-01-05 02:51:34 +0000
+++ b/storage/innobase/row/row0upd.c	2008-06-07 08:28:10 +0000
@@ -929,8 +929,8 @@
 					dfield->len
 						= dtype_get_at_most_n_mbchars(
 							col->prtype,
-							col->mbminlen,
-							col->mbmaxlen,
+							dcol_unpack_mbminlen(col),
+							dcol_unpack_mbmaxlen(col),
 							field->prefix_len,
 							new_val->len,
 							new_val->data);
@@ -1005,8 +1005,8 @@
 					dfield->len
 						= dtype_get_at_most_n_mbchars(
 							col->prtype,
-							col->mbminlen,
-							col->mbmaxlen,
+							dcol_unpack_mbminlen(col),
+							dcol_unpack_mbmaxlen(col),
 							field->prefix_len,
 							new_val->len,
 							new_val->data);

Thread
commit into mysql-6.0-rpl branch (bar:2655) Bug#34391Alexander Barkov7 Jun