Commit 4f4b404e authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#11849231 inflateInit() invoked without initializing all memory

According to the zlib documentation, next_in and avail_in
must be initialized before invoking inflateInit or inflateInit2.
Furthermore, the zalloc function must clear the allocated memory.

btr_copy_zblob_prefix(): Replace the d_stream parameter with buf,len
and return the copied length.

page_zip_decompress(): Invoke inflateInit2 a little later.

page_zip_zalloc(): Rename from page_zip_alloc().
Invoke mem_heap_zalloc() instead of mem_heap_alloc().

rb:619 approved by Jimmy Yang
parent 71be1473
2011-03-15 The InnoDB Team
* btr/btr0cur.c, page/page0zip.c:
Fix Bug#11849231 inflateInit() invoked without initializing all memory
2011-02-28 The InnoDB Team 2011-02-28 The InnoDB Team
* btr/btr0sea.c, buf/buf0buf.c, buf/buf0lru.c: * btr/btr0sea.c, buf/buf0buf.c, buf/buf0lru.c:
......
...@@ -4627,27 +4627,45 @@ btr_copy_blob_prefix( ...@@ -4627,27 +4627,45 @@ btr_copy_blob_prefix(
/*******************************************************************//** /*******************************************************************//**
Copies the prefix of a compressed BLOB. The clustered index record Copies the prefix of a compressed BLOB. The clustered index record
that points to this BLOB must be protected by a lock or a page latch. */ that points to this BLOB must be protected by a lock or a page latch.
@return number of bytes written to buf */
static static
void ulint
btr_copy_zblob_prefix( btr_copy_zblob_prefix(
/*==================*/ /*==================*/
z_stream* d_stream,/*!< in/out: the decompressing stream */ byte* buf, /*!< out: the externally stored part of
the field, or a prefix of it */
ulint len, /*!< in: length of buf, in bytes */
ulint zip_size,/*!< in: compressed BLOB page size */ ulint zip_size,/*!< in: compressed BLOB page size */
ulint space_id,/*!< in: space id of the BLOB pages */ ulint space_id,/*!< in: space id of the BLOB pages */
ulint page_no,/*!< in: page number of the first BLOB page */ ulint page_no,/*!< in: page number of the first BLOB page */
ulint offset) /*!< in: offset on the first BLOB page */ ulint offset) /*!< in: offset on the first BLOB page */
{ {
ulint page_type = FIL_PAGE_TYPE_ZBLOB; ulint page_type = FIL_PAGE_TYPE_ZBLOB;
mem_heap_t* heap;
int err;
z_stream d_stream;
d_stream.next_out = buf;
d_stream.avail_out = len;
d_stream.next_in = Z_NULL;
d_stream.avail_in = 0;
/* Zlib inflate needs 32 kilobytes for the default
window size, plus a few kilobytes for small objects. */
heap = mem_heap_create(40000);
page_zip_set_alloc(&d_stream, heap);
ut_ad(ut_is_2pow(zip_size)); ut_ad(ut_is_2pow(zip_size));
ut_ad(zip_size >= PAGE_ZIP_MIN_SIZE); ut_ad(zip_size >= PAGE_ZIP_MIN_SIZE);
ut_ad(zip_size <= UNIV_PAGE_SIZE); ut_ad(zip_size <= UNIV_PAGE_SIZE);
ut_ad(space_id); ut_ad(space_id);
err = inflateInit(&d_stream);
ut_a(err == Z_OK);
for (;;) { for (;;) {
buf_page_t* bpage; buf_page_t* bpage;
int err;
ulint next_page_no; ulint next_page_no;
/* There is no latch on bpage directly. Instead, /* There is no latch on bpage directly. Instead,
...@@ -4663,7 +4681,7 @@ btr_copy_zblob_prefix( ...@@ -4663,7 +4681,7 @@ btr_copy_zblob_prefix(
" compressed BLOB" " compressed BLOB"
" page %lu space %lu\n", " page %lu space %lu\n",
(ulong) page_no, (ulong) space_id); (ulong) page_no, (ulong) space_id);
return; goto func_exit;
} }
if (UNIV_UNLIKELY if (UNIV_UNLIKELY
...@@ -4689,13 +4707,13 @@ btr_copy_zblob_prefix( ...@@ -4689,13 +4707,13 @@ btr_copy_zblob_prefix(
offset += 4; offset += 4;
} }
d_stream->next_in = bpage->zip.data + offset; d_stream.next_in = bpage->zip.data + offset;
d_stream->avail_in = zip_size - offset; d_stream.avail_in = zip_size - offset;
err = inflate(d_stream, Z_NO_FLUSH); err = inflate(&d_stream, Z_NO_FLUSH);
switch (err) { switch (err) {
case Z_OK: case Z_OK:
if (!d_stream->avail_out) { if (!d_stream.avail_out) {
goto end_of_blob; goto end_of_blob;
} }
break; break;
...@@ -4712,13 +4730,13 @@ btr_copy_zblob_prefix( ...@@ -4712,13 +4730,13 @@ btr_copy_zblob_prefix(
" compressed BLOB" " compressed BLOB"
" page %lu space %lu returned %d (%s)\n", " page %lu space %lu returned %d (%s)\n",
(ulong) page_no, (ulong) space_id, (ulong) page_no, (ulong) space_id,
err, d_stream->msg); err, d_stream.msg);
case Z_BUF_ERROR: case Z_BUF_ERROR:
goto end_of_blob; goto end_of_blob;
} }
if (next_page_no == FIL_NULL) { if (next_page_no == FIL_NULL) {
if (!d_stream->avail_in) { if (!d_stream.avail_in) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: unexpected end of" " InnoDB: unexpected end of"
...@@ -4727,7 +4745,7 @@ btr_copy_zblob_prefix( ...@@ -4727,7 +4745,7 @@ btr_copy_zblob_prefix(
(ulong) page_no, (ulong) page_no,
(ulong) space_id); (ulong) space_id);
} else { } else {
err = inflate(d_stream, Z_FINISH); err = inflate(&d_stream, Z_FINISH);
switch (err) { switch (err) {
case Z_STREAM_END: case Z_STREAM_END:
case Z_BUF_ERROR: case Z_BUF_ERROR:
...@@ -4739,7 +4757,7 @@ btr_copy_zblob_prefix( ...@@ -4739,7 +4757,7 @@ btr_copy_zblob_prefix(
end_of_blob: end_of_blob:
buf_page_release_zip(bpage); buf_page_release_zip(bpage);
return; goto func_exit;
} }
buf_page_release_zip(bpage); buf_page_release_zip(bpage);
...@@ -4751,6 +4769,12 @@ btr_copy_zblob_prefix( ...@@ -4751,6 +4769,12 @@ btr_copy_zblob_prefix(
offset = FIL_PAGE_NEXT; offset = FIL_PAGE_NEXT;
page_type = FIL_PAGE_TYPE_ZBLOB2; page_type = FIL_PAGE_TYPE_ZBLOB2;
} }
func_exit:
inflateEnd(&d_stream);
mem_heap_free(heap);
UNIV_MEM_ASSERT_RW(buf, d_stream.total_out);
return(d_stream.total_out);
} }
/*******************************************************************//** /*******************************************************************//**
...@@ -4776,28 +4800,8 @@ btr_copy_externally_stored_field_prefix_low( ...@@ -4776,28 +4800,8 @@ btr_copy_externally_stored_field_prefix_low(
} }
if (UNIV_UNLIKELY(zip_size)) { if (UNIV_UNLIKELY(zip_size)) {
int err; return(btr_copy_zblob_prefix(buf, len, zip_size,
z_stream d_stream; space_id, page_no, offset));
mem_heap_t* heap;
/* Zlib inflate needs 32 kilobytes for the default
window size, plus a few kilobytes for small objects. */
heap = mem_heap_create(40000);
page_zip_set_alloc(&d_stream, heap);
err = inflateInit(&d_stream);
ut_a(err == Z_OK);
d_stream.next_out = buf;
d_stream.avail_out = len;
d_stream.avail_in = 0;
btr_copy_zblob_prefix(&d_stream, zip_size,
space_id, page_no, offset);
inflateEnd(&d_stream);
mem_heap_free(heap);
UNIV_MEM_ASSERT_RW(buf, d_stream.total_out);
return(d_stream.total_out);
} else { } else {
return(btr_copy_blob_prefix(buf, len, space_id, return(btr_copy_blob_prefix(buf, len, space_id,
page_no, offset)); page_no, offset));
......
...@@ -653,13 +653,13 @@ page_zip_dir_encode( ...@@ -653,13 +653,13 @@ page_zip_dir_encode(
Allocate memory for zlib. */ Allocate memory for zlib. */
static static
void* void*
page_zip_malloc( page_zip_zalloc(
/*============*/ /*============*/
void* opaque, /*!< in/out: memory heap */ void* opaque, /*!< in/out: memory heap */
uInt items, /*!< in: number of items to allocate */ uInt items, /*!< in: number of items to allocate */
uInt size) /*!< in: size of an item in bytes */ uInt size) /*!< in: size of an item in bytes */
{ {
return(mem_heap_alloc(opaque, items * size)); return(mem_heap_zalloc(opaque, items * size));
} }
/**********************************************************************//** /**********************************************************************//**
...@@ -684,7 +684,7 @@ page_zip_set_alloc( ...@@ -684,7 +684,7 @@ page_zip_set_alloc(
{ {
z_stream* strm = stream; z_stream* strm = stream;
strm->zalloc = page_zip_malloc; strm->zalloc = page_zip_zalloc;
strm->zfree = page_zip_free; strm->zfree = page_zip_free;
strm->opaque = heap; strm->opaque = heap;
} }
...@@ -2912,19 +2912,18 @@ page_zip_decompress( ...@@ -2912,19 +2912,18 @@ page_zip_decompress(
page_zip_set_alloc(&d_stream, heap); page_zip_set_alloc(&d_stream, heap);
if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
!= Z_OK)) {
ut_error;
}
d_stream.next_in = page_zip->data + PAGE_DATA; d_stream.next_in = page_zip->data + PAGE_DATA;
/* Subtract the space reserved for /* Subtract the space reserved for
the page header and the end marker of the modification log. */ the page header and the end marker of the modification log. */
d_stream.avail_in = page_zip_get_size(page_zip) - (PAGE_DATA + 1); d_stream.avail_in = page_zip_get_size(page_zip) - (PAGE_DATA + 1);
d_stream.next_out = page + PAGE_ZIP_START; d_stream.next_out = page + PAGE_ZIP_START;
d_stream.avail_out = UNIV_PAGE_SIZE - PAGE_ZIP_START; d_stream.avail_out = UNIV_PAGE_SIZE - PAGE_ZIP_START;
if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
!= Z_OK)) {
ut_error;
}
/* Decode the zlib header and the index information. */ /* Decode the zlib header and the index information. */
if (UNIV_UNLIKELY(inflate(&d_stream, Z_BLOCK) != Z_OK)) { if (UNIV_UNLIKELY(inflate(&d_stream, Z_BLOCK) != Z_OK)) {
......
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