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 2009-02-20 The InnoDB Team
* handler/ha_innodb.cc: * handler/ha_innodb.cc:
......
...@@ -4115,6 +4115,44 @@ next_zip_page: ...@@ -4115,6 +4115,44 @@ next_zip_page:
return(DB_SUCCESS); 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 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, management if the field in data is owned by the externally stored field,
...@@ -4268,8 +4306,9 @@ btr_free_externally_stored_field( ...@@ -4268,8 +4306,9 @@ btr_free_externally_stored_field(
MLOG_4BYTES, &mtr); MLOG_4BYTES, &mtr);
} }
} else { } else {
ut_a(fil_page_get_type(page) == FIL_PAGE_TYPE_BLOB);
ut_a(!page_zip); ut_a(!page_zip);
btr_check_blob_fil_page_type(space_id, page_no, page,
"free");
next_page_no = mach_read_from_4( next_page_no = mach_read_from_4(
page + FIL_PAGE_DATA page + FIL_PAGE_DATA
...@@ -4279,9 +4318,6 @@ btr_free_externally_stored_field( ...@@ -4279,9 +4318,6 @@ btr_free_externally_stored_field(
because we did not store it on the page (we save the because we did not store it on the page (we save the
space overhead from an index page header. */ 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); btr_page_free_low(index, ext_block, 0, &mtr);
mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO, mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO,
...@@ -4419,9 +4455,8 @@ btr_copy_blob_prefix( ...@@ -4419,9 +4455,8 @@ btr_copy_blob_prefix(
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE); buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
page = buf_block_get_frame(block); page = buf_block_get_frame(block);
/* Unfortunately, FIL_PAGE_TYPE was uninitialized for btr_check_blob_fil_page_type(space_id, page_no, page, "read");
many pages until MySQL/InnoDB 5.1.7. */
/* ut_ad(fil_page_get_type(page) == FIL_PAGE_TYPE_BLOB); */
blob_header = page + offset; blob_header = page + offset;
part_len = btr_blob_get_part_len(blob_header); part_len = btr_blob_get_part_len(blob_header);
copy_len = ut_min(part_len, len - copied_len); 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