Commit f9b39084 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge mysql-5.1 to mysql-5.1-security.

parents c8c2daf1 1ba7ae75
...@@ -2468,6 +2468,8 @@ row_sel_field_store_in_mysql_format( ...@@ -2468,6 +2468,8 @@ row_sel_field_store_in_mysql_format(
ut_ad(len != UNIV_SQL_NULL); ut_ad(len != UNIV_SQL_NULL);
UNIV_MEM_ASSERT_RW(data, len); UNIV_MEM_ASSERT_RW(data, len);
UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
UNIV_MEM_INVALID(dest, templ->mysql_col_len);
if (templ->type == DATA_INT) { if (templ->type == DATA_INT) {
/* Convert integer data from Innobase to a little-endian /* Convert integer data from Innobase to a little-endian
...@@ -2502,14 +2504,16 @@ row_sel_field_store_in_mysql_format( ...@@ -2502,14 +2504,16 @@ row_sel_field_store_in_mysql_format(
dest = row_mysql_store_true_var_len( dest = row_mysql_store_true_var_len(
dest, len, templ->mysql_length_bytes); dest, len, templ->mysql_length_bytes);
/* Copy the actual data. Leave the rest of the
buffer uninitialized. */
ut_memcpy(dest, data, len);
return;
} }
/* Copy the actual data */ /* Copy the actual data */
ut_memcpy(dest, data, len); ut_memcpy(dest, data, len);
/* Pad with trailing spaces. We pad with spaces also the /* Pad with trailing spaces. */
unused end of a >= 5.0.3 true VARCHAR column, just in case
MySQL expects its contents to be deterministic. */
pad_ptr = dest + len; pad_ptr = dest + len;
...@@ -3012,6 +3016,39 @@ sel_restore_position_for_mysql( ...@@ -3012,6 +3016,39 @@ sel_restore_position_for_mysql(
return(TRUE); return(TRUE);
} }
/************************************************************************
Copies a cached field for MySQL from the fetch cache. */
static
void
row_sel_copy_cached_field_for_mysql(
/*================================*/
byte* buf, /* in/out: row buffer */
byte* cache, /* in: cached row */
const mysql_row_templ_t*templ) /* in: column template */
{
ulint len;
buf += templ->mysql_col_offset;
cache += templ->mysql_col_offset;
UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len);
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR
&& templ->type != DATA_INT) {
/* Check for != DATA_INT to make sure we do
not treat MySQL ENUM or SET as a true VARCHAR!
Find the actual length of the true VARCHAR field. */
row_mysql_read_true_varchar(
&len, cache, templ->mysql_length_bytes);
len += templ->mysql_length_bytes;
UNIV_MEM_INVALID(buf, templ->mysql_col_len);
} else {
len = templ->mysql_col_len;
}
ut_memcpy(buf, cache, len);
}
/************************************************************************ /************************************************************************
Pops a cached row for MySQL from the fetch cache. */ Pops a cached row for MySQL from the fetch cache. */
UNIV_INLINE UNIV_INLINE
...@@ -3028,22 +3065,18 @@ row_sel_pop_cached_row_for_mysql( ...@@ -3028,22 +3065,18 @@ row_sel_pop_cached_row_for_mysql(
ut_ad(prebuilt->n_fetch_cached > 0); ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len);
cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first];
if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) { if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) {
/* Copy cache record field by field, don't touch fields that /* Copy cache record field by field, don't touch fields that
are not covered by current key */ are not covered by current key */
cached_rec = prebuilt->fetch_cache[
prebuilt->fetch_cache_first];
for (i = 0; i < prebuilt->n_template; i++) { for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i; templ = prebuilt->mysql_template + i;
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */ row_sel_copy_cached_field_for_mysql(
UNIV_MEM_ASSERT_RW(cached_rec buf, cached_rec, templ);
+ templ->mysql_col_offset,
templ->mysql_col_len);
#endif
ut_memcpy(buf + templ->mysql_col_offset,
cached_rec + templ->mysql_col_offset,
templ->mysql_col_len);
/* Copy NULL bit of the current field from cached_rec /* Copy NULL bit of the current field from cached_rec
to buf */ to buf */
if (templ->mysql_null_bit_mask) { if (templ->mysql_null_bit_mask) {
...@@ -3053,17 +3086,24 @@ row_sel_pop_cached_row_for_mysql( ...@@ -3053,17 +3086,24 @@ row_sel_pop_cached_row_for_mysql(
& (byte)templ->mysql_null_bit_mask; & (byte)templ->mysql_null_bit_mask;
} }
} }
} else if (prebuilt->mysql_prefix_len > 63) {
/* The record is long. Copy it field by field, in case
there are some long VARCHAR column of which only a
small length is being used. */
UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len);
/* First copy the NULL bits. */
ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len);
/* Then copy the requested fields. */
for (i = 0; i < prebuilt->n_template; i++) {
row_sel_copy_cached_field_for_mysql(
buf, cached_rec, prebuilt->mysql_template + i);
}
} else {
ut_memcpy(buf, cached_rec, prebuilt->mysql_prefix_len);
} }
else {
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
[prebuilt->fetch_cache_first],
prebuilt->mysql_prefix_len);
#endif
ut_memcpy(buf,
prebuilt->fetch_cache[prebuilt->fetch_cache_first],
prebuilt->mysql_prefix_len);
}
prebuilt->n_fetch_cached--; prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++; prebuilt->fetch_cache_first++;
......
2011-08-08 The InnoDB Team
* row/row0sel.c:
Fix Bug#12835650 VARCHAR maximum length performance impact
2011-08-08 The InnoDB Team 2011-08-08 The InnoDB Team
* handler/ha_innodb.cc: * handler/ha_innodb.cc:
......
...@@ -2544,6 +2544,8 @@ row_sel_field_store_in_mysql_format( ...@@ -2544,6 +2544,8 @@ row_sel_field_store_in_mysql_format(
ut_ad(len != UNIV_SQL_NULL); ut_ad(len != UNIV_SQL_NULL);
UNIV_MEM_ASSERT_RW(data, len); UNIV_MEM_ASSERT_RW(data, len);
UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
UNIV_MEM_INVALID(dest, templ->mysql_col_len);
switch (templ->type) { switch (templ->type) {
case DATA_INT: case DATA_INT:
...@@ -2580,14 +2582,16 @@ row_sel_field_store_in_mysql_format( ...@@ -2580,14 +2582,16 @@ row_sel_field_store_in_mysql_format(
dest = row_mysql_store_true_var_len( dest = row_mysql_store_true_var_len(
dest, len, templ->mysql_length_bytes); dest, len, templ->mysql_length_bytes);
/* Copy the actual data. Leave the rest of the
buffer uninitialized. */
memcpy(dest, data, len);
break;
} }
/* Copy the actual data */ /* Copy the actual data */
ut_memcpy(dest, data, len); ut_memcpy(dest, data, len);
/* Pad with trailing spaces. We pad with spaces also the /* Pad with trailing spaces. */
unused end of a >= 5.0.3 true VARCHAR column, just in case
MySQL expects its contents to be deterministic. */
pad_ptr = dest + len; pad_ptr = dest + len;
...@@ -3119,6 +3123,39 @@ sel_restore_position_for_mysql( ...@@ -3119,6 +3123,39 @@ sel_restore_position_for_mysql(
return(TRUE); return(TRUE);
} }
/********************************************************************//**
Copies a cached field for MySQL from the fetch cache. */
static
void
row_sel_copy_cached_field_for_mysql(
/*================================*/
byte* buf, /*!< in/out: row buffer */
const byte* cache, /*!< in: cached row */
const mysql_row_templ_t*templ) /*!< in: column template */
{
ulint len;
buf += templ->mysql_col_offset;
cache += templ->mysql_col_offset;
UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len);
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR
&& templ->type != DATA_INT) {
/* Check for != DATA_INT to make sure we do
not treat MySQL ENUM or SET as a true VARCHAR!
Find the actual length of the true VARCHAR field. */
row_mysql_read_true_varchar(
&len, cache, templ->mysql_length_bytes);
len += templ->mysql_length_bytes;
UNIV_MEM_INVALID(buf, templ->mysql_col_len);
} else {
len = templ->mysql_col_len;
}
ut_memcpy(buf, cache, len);
}
/********************************************************************//** /********************************************************************//**
Pops a cached row for MySQL from the fetch cache. */ Pops a cached row for MySQL from the fetch cache. */
UNIV_INLINE UNIV_INLINE
...@@ -3131,26 +3168,22 @@ row_sel_pop_cached_row_for_mysql( ...@@ -3131,26 +3168,22 @@ row_sel_pop_cached_row_for_mysql(
{ {
ulint i; ulint i;
const mysql_row_templ_t*templ; const mysql_row_templ_t*templ;
byte* cached_rec; const byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0); ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len);
cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first];
if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) { if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) {
/* Copy cache record field by field, don't touch fields that /* Copy cache record field by field, don't touch fields that
are not covered by current key */ are not covered by current key */
cached_rec = prebuilt->fetch_cache[
prebuilt->fetch_cache_first];
for (i = 0; i < prebuilt->n_template; i++) { for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i; templ = prebuilt->mysql_template + i;
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */ row_sel_copy_cached_field_for_mysql(
UNIV_MEM_ASSERT_RW(cached_rec buf, cached_rec, templ);
+ templ->mysql_col_offset,
templ->mysql_col_len);
#endif
ut_memcpy(buf + templ->mysql_col_offset,
cached_rec + templ->mysql_col_offset,
templ->mysql_col_len);
/* Copy NULL bit of the current field from cached_rec /* Copy NULL bit of the current field from cached_rec
to buf */ to buf */
if (templ->mysql_null_bit_mask) { if (templ->mysql_null_bit_mask) {
...@@ -3160,17 +3193,24 @@ row_sel_pop_cached_row_for_mysql( ...@@ -3160,17 +3193,24 @@ row_sel_pop_cached_row_for_mysql(
& (byte)templ->mysql_null_bit_mask; & (byte)templ->mysql_null_bit_mask;
} }
} }
} else if (prebuilt->mysql_prefix_len > 63) {
/* The record is long. Copy it field by field, in case
there are some long VARCHAR column of which only a
small length is being used. */
UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len);
/* First copy the NULL bits. */
ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len);
/* Then copy the requested fields. */
for (i = 0; i < prebuilt->n_template; i++) {
row_sel_copy_cached_field_for_mysql(
buf, cached_rec, prebuilt->mysql_template + i);
}
} else {
ut_memcpy(buf, cached_rec, prebuilt->mysql_prefix_len);
} }
else {
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
[prebuilt->fetch_cache_first],
prebuilt->mysql_prefix_len);
#endif
ut_memcpy(buf,
prebuilt->fetch_cache[prebuilt->fetch_cache_first],
prebuilt->mysql_prefix_len);
}
prebuilt->n_fetch_cached--; prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++; prebuilt->fetch_cache_first++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment