Commit 6083ae52 authored by Yasufumi Kinoshita's avatar Yasufumi Kinoshita

Bug #16089381 : POSSIBLE NUMBER UNDERFLOW AROUND CALLING PAGE_ZIP_EMPTY_SIZE()

some callers for page_zip_empty_size() ignored possibility its returning 0, and could cause underflow.

rb#1837 approved by Marko
parent f130ccc1
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc. Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
...@@ -1146,33 +1146,40 @@ btr_cur_optimistic_insert( ...@@ -1146,33 +1146,40 @@ btr_cur_optimistic_insert(
Subtract one byte for the encoded heap_no in the Subtract one byte for the encoded heap_no in the
modification log. */ modification log. */
ulint free_space_zip = page_zip_empty_size( ulint free_space_zip = page_zip_empty_size(
cursor->index->n_fields, zip_size) - 1; cursor->index->n_fields, zip_size);
ulint n_uniq = dict_index_get_n_unique_in_tree(index); ulint n_uniq = dict_index_get_n_unique_in_tree(index);
ut_ad(dict_table_is_comp(index->table)); ut_ad(dict_table_is_comp(index->table));
if (free_space_zip == 0) {
too_big:
if (big_rec_vec) {
dtuple_convert_back_big_rec(
index, entry, big_rec_vec);
}
return(DB_TOO_BIG_RECORD);
}
/* Subtract one byte for the encoded heap_no in the
modification log. */
free_space_zip--;
/* There should be enough room for two node pointer /* There should be enough room for two node pointer
records on an empty non-leaf page. This prevents records on an empty non-leaf page. This prevents
infinite page splits. */ infinite page splits. */
if (UNIV_LIKELY(entry->n_fields >= n_uniq) if (entry->n_fields >= n_uniq
&& UNIV_UNLIKELY(REC_NODE_PTR_SIZE && (REC_NODE_PTR_SIZE
+ rec_get_converted_size_comp_prefix( + rec_get_converted_size_comp_prefix(
index, entry->fields, n_uniq, index, entry->fields, n_uniq, NULL)
NULL)
/* On a compressed page, there is /* On a compressed page, there is
a two-byte entry in the dense a two-byte entry in the dense
page directory for every record. page directory for every record.
But there is no record header. */ But there is no record header. */
- (REC_N_NEW_EXTRA_BYTES - 2) - (REC_N_NEW_EXTRA_BYTES - 2)
> free_space_zip / 2)) { > free_space_zip / 2)) {
goto too_big;
if (big_rec_vec) {
dtuple_convert_back_big_rec(
index, entry, big_rec_vec);
}
return(DB_TOO_BIG_RECORD);
} }
} }
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -1415,6 +1415,10 @@ dict_index_too_big_for_tree( ...@@ -1415,6 +1415,10 @@ dict_index_too_big_for_tree(
/* maximum allowed size of a node pointer record */ /* maximum allowed size of a node pointer record */
ulint page_ptr_max; ulint page_ptr_max;
DBUG_EXECUTE_IF(
"ib_force_create_table",
return(FALSE););
comp = dict_table_is_comp(table); comp = dict_table_is_comp(table);
zip_size = dict_table_zip_size(table); zip_size = dict_table_zip_size(table);
...@@ -1429,7 +1433,10 @@ dict_index_too_big_for_tree( ...@@ -1429,7 +1433,10 @@ dict_index_too_big_for_tree(
number in the page modification log. The maximum number in the page modification log. The maximum
allowed node pointer size is half that. */ allowed node pointer size is half that. */
page_rec_max = page_zip_empty_size(new_index->n_fields, page_rec_max = page_zip_empty_size(new_index->n_fields,
zip_size) - 1; zip_size);
if (page_rec_max) {
page_rec_max--;
}
page_ptr_max = page_rec_max / 2; page_ptr_max = page_rec_max / 2;
/* On a compressed page, there is a two-byte entry in /* On a compressed page, there is a two-byte entry in
the dense page directory for every record. But there the dense page directory for every record. But there
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved. Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -188,8 +188,8 @@ page_zip_rec_needs_ext( ...@@ -188,8 +188,8 @@ page_zip_rec_needs_ext(
one record on an empty leaf page. Subtract 1 byte for one record on an empty leaf page. Subtract 1 byte for
the encoded heap number. Check also the available space the encoded heap number. Check also the available space
on the uncompressed page. */ on the uncompressed page. */
return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2) return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2 - 1)
>= (page_zip_empty_size(n_fields, zip_size) - 1) >= page_zip_empty_size(n_fields, zip_size)
|| rec_size >= page_get_free_space_of_empty(TRUE) / 2); || rec_size >= page_get_free_space_of_empty(TRUE) / 2);
} }
......
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