changeset 9046:faa71d8b8ab5

8211926: Catastrophic size_t underflow in BitMap::*_large methods Reviewed-by: kbarrett, stuefe
author shade
date Tue, 12 Feb 2019 11:58:44 +0100
parents c5e1abd2d0af
children 6384d7f8a123
files src/share/vm/utilities/bitMap.cpp src/share/vm/utilities/bitMap.hpp src/share/vm/utilities/bitMap.inline.hpp
diffstat 3 files changed, 28 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/utilities/bitMap.cpp	Mon Feb 11 17:00:04 2019 +0100
+++ b/src/share/vm/utilities/bitMap.cpp	Tue Feb 12 11:58:44 2019 +0100
@@ -154,14 +154,24 @@
   }
 }
 
+bool BitMap::is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word) {
+  // There is little point to call large version on small ranges.
+  // Need to check carefully, keeping potential idx_t underflow in mind.
+  // The threshold should be at least one word.
+  STATIC_ASSERT(small_range_words >= 1);
+  return (beg_full_word + small_range_words >= end_full_word);
+}
+
 void BitMap::set_large_range(idx_t beg, idx_t end) {
   verify_range(beg, end);
 
   idx_t beg_full_word = word_index_round_up(beg);
   idx_t end_full_word = word_index(end);
 
-  assert(end_full_word - beg_full_word >= 32,
-         "the range must include at least 32 bytes");
+  if (is_small_range_of_words(beg_full_word, end_full_word)) {
+    set_range(beg, end);
+    return;
+  }
 
   // The range includes at least one full word.
   set_range_within_word(beg, bit_index(beg_full_word));
@@ -175,8 +185,10 @@
   idx_t beg_full_word = word_index_round_up(beg);
   idx_t end_full_word = word_index(end);
 
-  assert(end_full_word - beg_full_word >= 32,
-         "the range must include at least 32 bytes");
+  if (is_small_range_of_words(beg_full_word, end_full_word)) {
+    clear_range(beg, end);
+    return;
+  }
 
   // The range includes at least one full word.
   clear_range_within_word(beg, bit_index(beg_full_word));
@@ -264,8 +276,10 @@
   idx_t beg_full_word = word_index_round_up(beg);
   idx_t end_full_word = word_index(end);
 
-  assert(end_full_word - beg_full_word >= 32,
-         "the range must include at least 32 bytes");
+  if (is_small_range_of_words(beg_full_word, end_full_word)) {
+    par_at_put_range(beg, end, value);
+    return;
+  }
 
   // The range includes at least one full word.
   par_put_range_within_word(beg, bit_index(beg_full_word), value);
--- a/src/share/vm/utilities/bitMap.hpp	Mon Feb 11 17:00:04 2019 +0100
+++ b/src/share/vm/utilities/bitMap.hpp	Tue Feb 12 11:58:44 2019 +0100
@@ -56,6 +56,10 @@
   // the bitmap appropriately if needed using factor-of-two expansion.
   void at_put_grow(idx_t index, bool value);
 
+  // Threshold for performing small range operation, even when large range
+  // operation was requested. Measured in words.
+  static const size_t small_range_words = 32;
+
  protected:
   // Return the position of bit within the word that contains it (e.g., if
   // bitmap words are 32 bits, return a number 0 <= n <= 31).
@@ -97,6 +101,8 @@
   void      set_large_range_of_words   (idx_t beg, idx_t end);
   void      clear_large_range_of_words (idx_t beg, idx_t end);
 
+  static bool is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word);
+
   // The index of the first full word in a range.
   idx_t word_index_round_up(idx_t bit) const;
 
--- a/src/share/vm/utilities/bitMap.inline.hpp	Mon Feb 11 17:00:04 2019 +0100
+++ b/src/share/vm/utilities/bitMap.inline.hpp	Tue Feb 12 11:58:44 2019 +0100
@@ -321,10 +321,12 @@
 }
 
 inline void BitMap::set_large_range_of_words(idx_t beg, idx_t end) {
+  assert(beg <= end, "underflow");
   memset(_map + beg, ~(unsigned char)0, (end - beg) * sizeof(uintptr_t));
 }
 
 inline void BitMap::clear_large_range_of_words(idx_t beg, idx_t end) {
+  assert(beg <= end, "underflow");
   memset(_map + beg, 0, (end - beg) * sizeof(uintptr_t));
 }