Commit c6d329b4 authored by unknown's avatar unknown

InnoDB: Remove crash in in-place update from NULL to non-NULL. (Bug #7591)

rem0rec.c:
  rec_init_offsets(): Make the function comment more accurate.
rem0rec.ic:
  rec_get_nth_field(): Return pointer to the field, even to NULL fields.
  rec_set_nth_field(): Make more accurate debug assertions.


innobase/include/rem0rec.ic:
  rec_get_nth_field(): Return pointer to the field, even to NULL fields.
  rec_set_nth_field(): Make more accurate debug assertions.
innobase/rem/rem0rec.c:
  rec_init_offsets(): Make the function comment more accurate.
parent ecf24c66
...@@ -880,7 +880,6 @@ rec_get_nth_field( ...@@ -880,7 +880,6 @@ rec_get_nth_field(
length = rec_offs_base(offsets)[1 + n]; length = rec_offs_base(offsets)[1 + n];
if (length & REC_OFFS_SQL_NULL) { if (length & REC_OFFS_SQL_NULL) {
field = NULL;
length = UNIV_SQL_NULL; length = UNIV_SQL_NULL;
} else { } else {
length &= REC_OFFS_MASK; length &= REC_OFFS_MASK;
...@@ -1185,6 +1184,7 @@ rec_set_nth_field( ...@@ -1185,6 +1184,7 @@ rec_set_nth_field(
byte* data2; byte* data2;
ulint len2; ulint len2;
ut_ad(rec);
ut_ad(rec_offs_validate(rec, NULL, offsets)); ut_ad(rec_offs_validate(rec, NULL, offsets));
if (len == UNIV_SQL_NULL) { if (len == UNIV_SQL_NULL) {
...@@ -1195,14 +1195,15 @@ rec_set_nth_field( ...@@ -1195,14 +1195,15 @@ rec_set_nth_field(
} }
data2 = rec_get_nth_field(rec, offsets, n, &len2); data2 = rec_get_nth_field(rec, offsets, n, &len2);
ut_ad(len2 == len);
ut_memcpy(data2, data, len);
if (len2 == UNIV_SQL_NULL) { if (len2 == UNIV_SQL_NULL) {
ut_ad(!rec_offs_comp(offsets)); ut_ad(!rec_offs_comp(offsets));
rec_set_nth_field_null_bit(rec, n, FALSE); rec_set_nth_field_null_bit(rec, n, FALSE);
ut_ad(len == rec_get_nth_field_size(rec, n));
} else {
ut_ad(len2 == len);
} }
ut_memcpy(data2, data, len);
} }
/************************************************************** /**************************************************************
......
...@@ -137,16 +137,18 @@ rec_validate_old( ...@@ -137,16 +137,18 @@ rec_validate_old(
rec_t* rec); /* in: physical record */ rec_t* rec); /* in: physical record */
/********************************************************** /**********************************************************
The following function determines the offsets to each field The following function determines the offsets to each field in the
in the record. The offsets are written to an array of record. The offsets are written to a previously allocated array of
ulint[n+2], with [0] being the number of fields (n), [1] being the ulint, where rec_offs_n_fields(offsets) has been initialized to the
extra size (if REC_OFFS_COMPACT is set, the record is in the new number of fields in the record. The rest of the array will be
format), and [2]..[n+1] being the offsets past the end of initialized by this function. rec_offs_base(offsets)[0] will be set
fields 0..n, or to the beginning of fields 1..n+1. When the to the extra size (if REC_OFFS_COMPACT is set, the record is in the
high-order bit of the offset at [n+1] is set (REC_OFFS_SQL_NULL), new format), and rec_offs_base(offsets)[1..n_fields] will be set to
the field n is NULL. When the second high-order bit of the offset offsets past the end of fields 0..n_fields, or to the beginning of
at [n+1] is set (REC_OFFS_EXTERNAL), the field n is being stored fields 1..n_fields+1. When the high-order bit of the offset at [i+1]
externally. */ is set (REC_OFFS_SQL_NULL), the field i is NULL. When the second
high-order bit of the offset at [i+1] is set (REC_OFFS_EXTERNAL), the
field i is being stored externally. */
static static
void void
rec_init_offsets( rec_init_offsets(
...@@ -154,8 +156,8 @@ rec_init_offsets( ...@@ -154,8 +156,8 @@ rec_init_offsets(
/* out: the offsets */ /* out: the offsets */
rec_t* rec, /* in: physical record */ rec_t* rec, /* in: physical record */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
ulint* offsets)/* in:/out: ulint[n+2]; ulint* offsets)/* in/out: array of offsets;
n=rec_offs_n_fields(offsets) */ in: n=rec_offs_n_fields(offsets) */
{ {
ulint n_fields = rec_offs_n_fields(offsets); ulint n_fields = rec_offs_n_fields(offsets);
ulint i = 0; ulint i = 0;
......
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