From 0d19cf96bc6fa29f725fa72def4c3b07e74e1077 Mon Sep 17 00:00:00 2001 From: shade Date: Tue, 12 Feb 2019 11:58:44 +0100 Subject: [PATCH] 8211926: Catastrophic size_t underflow in BitMap::*_large methods Reviewed-by: kbarrett, stuefe --- src/share/vm/utilities/bitMap.cpp | 26 ++++++++++++++++++------ src/share/vm/utilities/bitMap.hpp | 6 ++++++ src/share/vm/utilities/bitMap.inline.hpp | 2 ++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/share/vm/utilities/bitMap.cpp b/src/share/vm/utilities/bitMap.cpp index 4627a5321..e64add155 100644 --- a/src/share/vm/utilities/bitMap.cpp +++ b/src/share/vm/utilities/bitMap.cpp @@ -154,14 +154,24 @@ void BitMap::clear_range(idx_t beg, idx_t end) { } } +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 @@ void BitMap::clear_large_range(idx_t beg, idx_t 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)) { + 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 @@ void BitMap::par_at_put_large_range(idx_t beg, idx_t end, bool value) { 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); diff --git a/src/share/vm/utilities/bitMap.hpp b/src/share/vm/utilities/bitMap.hpp index e04f71843..51c58da8e 100644 --- a/src/share/vm/utilities/bitMap.hpp +++ b/src/share/vm/utilities/bitMap.hpp @@ -56,6 +56,10 @@ class BitMap VALUE_OBJ_CLASS_SPEC { // 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 @@ class BitMap VALUE_OBJ_CLASS_SPEC { 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; diff --git a/src/share/vm/utilities/bitMap.inline.hpp b/src/share/vm/utilities/bitMap.inline.hpp index 318b178f1..ef4c30930 100644 --- a/src/share/vm/utilities/bitMap.inline.hpp +++ b/src/share/vm/utilities/bitMap.inline.hpp @@ -321,10 +321,12 @@ BitMap::inverted_bit_mask_for_range(idx_t beg, idx_t end) const { } 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)); } -- GitLab