Commit 30313d6e authored by marko's avatar marko

branches/zip: When freeing an uncompressed BLOB page, tolerate garbage in

FIL_PAGE_TYPE.  (Bug #43043, Issue #182)

btr_check_blob_fil_page_type(): New function.

btr_free_externally_stored_field(), btr_copy_blob_prefix():
Call btr_check_blob_fil_page_type() to check FIL_PAGE_TYPE.
parent e2196c34
2009-02-23 The InnoDB Team
* btr/btr0cur.c:
Fix Bug#43043 Crash on BLOB delete operation
When freeing an uncomrpressed BLOB page, tolerate an invalid value
in FIL_PAGE_TYPE. Old versions of MySQL did not initialize the
page type on BLOB pages.
2009-02-20 The InnoDB Team
* handler/ha_innodb.cc:
......
......@@ -4115,6 +4115,44 @@ next_zip_page:
return(DB_SUCCESS);
}
/***********************************************************************
Check the FIL_PAGE_TYPE on an uncompressed BLOB page. */
static
void
btr_check_blob_fil_page_type(
/*=========================*/
ulint space_id, /* in: space id */
ulint page_no, /* in: page number */
const page_t* page, /* in: page */
const char* op) /* in: operation (for diagnostics) */
{
ulint type = fil_page_get_type(page);
ut_a(space_id == page_get_space_id(page));
ut_a(page_no == page_get_page_no(page));
if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) {
ulint flags = fil_space_get_flags(space_id);
/* Old versions of InnoDB did not
initialize FIL_PAGE_TYPE on BLOB pages.
Ensure that this tablespace is in
an old format. */
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: FIL_PAGE_TYPE=%lu"
" on BLOB %s page %lu space %lu flags %lx\n",
(ulong) type, op,
(ulong) page_no, (ulong) space_id, (ulong) flags);
/* The garbage in FIL_PAGE_TYPE will
only be tolerated in tables in old
format. */
ut_a((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51);
}
}
/***********************************************************************
Frees the space in an externally stored field to the file space
management if the field in data is owned by the externally stored field,
......@@ -4268,8 +4306,9 @@ btr_free_externally_stored_field(
MLOG_4BYTES, &mtr);
}
} else {
ut_a(fil_page_get_type(page) == FIL_PAGE_TYPE_BLOB);
ut_a(!page_zip);
btr_check_blob_fil_page_type(space_id, page_no, page,
"free");
next_page_no = mach_read_from_4(
page + FIL_PAGE_DATA
......@@ -4279,9 +4318,6 @@ btr_free_externally_stored_field(
because we did not store it on the page (we save the
space overhead from an index page header. */
ut_a(space_id == page_get_space_id(page));
ut_a(page_no == page_get_page_no(page));
btr_page_free_low(index, ext_block, 0, &mtr);
mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO,
......@@ -4419,9 +4455,8 @@ btr_copy_blob_prefix(
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
page = buf_block_get_frame(block);
/* Unfortunately, FIL_PAGE_TYPE was uninitialized for
many pages until MySQL/InnoDB 5.1.7. */
/* ut_ad(fil_page_get_type(page) == FIL_PAGE_TYPE_BLOB); */
btr_check_blob_fil_page_type(space_id, page_no, page, "read");
blob_header = page + offset;
part_len = btr_blob_get_part_len(blob_header);
copy_len = ut_min(part_len, len - copied_len);
......
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