summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYasufumi Kinoshita <yasufumi.kinoshita@oracle.com>2013-01-23 14:59:36 +0900
committerYasufumi Kinoshita <yasufumi.kinoshita@oracle.com>2013-01-23 14:59:36 +0900
commit65cb30b3b94d1a0cca207623519f711d7ff11d17 (patch)
tree2cd746865fd6c7ae4983409410cac1af901f5619
parente7283ceaf034072dcd9ad01b2377ee2101eb1b4d (diff)
downloadmariadb-git-65cb30b3b94d1a0cca207623519f711d7ff11d17.tar.gz
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
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c43
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c11
-rw-r--r--storage/innodb_plugin/include/page0zip.ic6
3 files changed, 37 insertions, 23 deletions
diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
index e38b8a9bf53..4392fc16a5b 100644
--- a/storage/innodb_plugin/btr/btr0cur.c
+++ b/storage/innodb_plugin/btr/btr0cur.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-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.
Portions of this file contain modifications contributed and copyrighted by
@@ -1146,27 +1146,13 @@ btr_cur_optimistic_insert(
Subtract one byte for the encoded heap_no in the
modification log. */
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);
ut_ad(dict_table_is_comp(index->table));
- /* There should be enough room for two node pointer
- records on an empty non-leaf page. This prevents
- infinite page splits. */
-
- if (UNIV_LIKELY(entry->n_fields >= n_uniq)
- && UNIV_UNLIKELY(REC_NODE_PTR_SIZE
- + rec_get_converted_size_comp_prefix(
- index, entry->fields, n_uniq,
- NULL)
- /* On a compressed page, there is
- a two-byte entry in the dense
- page directory for every record.
- But there is no record header. */
- - (REC_N_NEW_EXTRA_BYTES - 2)
- > free_space_zip / 2)) {
-
+ if (free_space_zip == 0) {
+too_big:
if (big_rec_vec) {
dtuple_convert_back_big_rec(
index, entry, big_rec_vec);
@@ -1174,6 +1160,27 @@ btr_cur_optimistic_insert(
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
+ records on an empty non-leaf page. This prevents
+ infinite page splits. */
+
+ if (entry->n_fields >= n_uniq
+ && (REC_NODE_PTR_SIZE
+ + rec_get_converted_size_comp_prefix(
+ index, entry->fields, n_uniq, NULL)
+ /* On a compressed page, there is
+ a two-byte entry in the dense
+ page directory for every record.
+ But there is no record header. */
+ - (REC_N_NEW_EXTRA_BYTES - 2)
+ > free_space_zip / 2)) {
+ goto too_big;
+ }
}
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page),
diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
index 56c71cefa05..9cd0f51d72b 100644
--- a/storage/innodb_plugin/dict/dict0dict.c
+++ b/storage/innodb_plugin/dict/dict0dict.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-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
the terms of the GNU General Public License as published by the Free Software
@@ -1415,6 +1415,10 @@ dict_index_too_big_for_tree(
/* maximum allowed size of a node pointer record */
ulint page_ptr_max;
+ DBUG_EXECUTE_IF(
+ "ib_force_create_table",
+ return(FALSE););
+
comp = dict_table_is_comp(table);
zip_size = dict_table_zip_size(table);
@@ -1429,7 +1433,10 @@ dict_index_too_big_for_tree(
number in the page modification log. The maximum
allowed node pointer size is half that. */
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;
/* On a compressed page, there is a two-byte entry in
the dense page directory for every record. But there
diff --git a/storage/innodb_plugin/include/page0zip.ic b/storage/innodb_plugin/include/page0zip.ic
index 75cc7a9fcc4..b5480604bdf 100644
--- a/storage/innodb_plugin/include/page0zip.ic
+++ b/storage/innodb_plugin/include/page0zip.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-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
the terms of the GNU General Public License as published by the Free Software
@@ -188,8 +188,8 @@ page_zip_rec_needs_ext(
one record on an empty leaf page. Subtract 1 byte for
the encoded heap number. Check also the available space
on the uncompressed page. */
- return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2)
- >= (page_zip_empty_size(n_fields, zip_size) - 1)
+ return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2 - 1)
+ >= page_zip_empty_size(n_fields, zip_size)
|| rec_size >= page_get_free_space_of_empty(TRUE) / 2);
}