Tue, 12 Feb 2019 11:58:44 +0100
8211926: Catastrophic size_t underflow in BitMap::*_large methods
Reviewed-by: kbarrett, stuefe
1.1 --- a/src/share/vm/utilities/bitMap.cpp Mon Feb 11 17:00:04 2019 +0100 1.2 +++ b/src/share/vm/utilities/bitMap.cpp Tue Feb 12 11:58:44 2019 +0100 1.3 @@ -154,14 +154,24 @@ 1.4 } 1.5 } 1.6 1.7 +bool BitMap::is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word) { 1.8 + // There is little point to call large version on small ranges. 1.9 + // Need to check carefully, keeping potential idx_t underflow in mind. 1.10 + // The threshold should be at least one word. 1.11 + STATIC_ASSERT(small_range_words >= 1); 1.12 + return (beg_full_word + small_range_words >= end_full_word); 1.13 +} 1.14 + 1.15 void BitMap::set_large_range(idx_t beg, idx_t end) { 1.16 verify_range(beg, end); 1.17 1.18 idx_t beg_full_word = word_index_round_up(beg); 1.19 idx_t end_full_word = word_index(end); 1.20 1.21 - assert(end_full_word - beg_full_word >= 32, 1.22 - "the range must include at least 32 bytes"); 1.23 + if (is_small_range_of_words(beg_full_word, end_full_word)) { 1.24 + set_range(beg, end); 1.25 + return; 1.26 + } 1.27 1.28 // The range includes at least one full word. 1.29 set_range_within_word(beg, bit_index(beg_full_word)); 1.30 @@ -175,8 +185,10 @@ 1.31 idx_t beg_full_word = word_index_round_up(beg); 1.32 idx_t end_full_word = word_index(end); 1.33 1.34 - assert(end_full_word - beg_full_word >= 32, 1.35 - "the range must include at least 32 bytes"); 1.36 + if (is_small_range_of_words(beg_full_word, end_full_word)) { 1.37 + clear_range(beg, end); 1.38 + return; 1.39 + } 1.40 1.41 // The range includes at least one full word. 1.42 clear_range_within_word(beg, bit_index(beg_full_word)); 1.43 @@ -264,8 +276,10 @@ 1.44 idx_t beg_full_word = word_index_round_up(beg); 1.45 idx_t end_full_word = word_index(end); 1.46 1.47 - assert(end_full_word - beg_full_word >= 32, 1.48 - "the range must include at least 32 bytes"); 1.49 + if (is_small_range_of_words(beg_full_word, end_full_word)) { 1.50 + par_at_put_range(beg, end, value); 1.51 + return; 1.52 + } 1.53 1.54 // The range includes at least one full word. 1.55 par_put_range_within_word(beg, bit_index(beg_full_word), value);
2.1 --- a/src/share/vm/utilities/bitMap.hpp Mon Feb 11 17:00:04 2019 +0100 2.2 +++ b/src/share/vm/utilities/bitMap.hpp Tue Feb 12 11:58:44 2019 +0100 2.3 @@ -56,6 +56,10 @@ 2.4 // the bitmap appropriately if needed using factor-of-two expansion. 2.5 void at_put_grow(idx_t index, bool value); 2.6 2.7 + // Threshold for performing small range operation, even when large range 2.8 + // operation was requested. Measured in words. 2.9 + static const size_t small_range_words = 32; 2.10 + 2.11 protected: 2.12 // Return the position of bit within the word that contains it (e.g., if 2.13 // bitmap words are 32 bits, return a number 0 <= n <= 31). 2.14 @@ -97,6 +101,8 @@ 2.15 void set_large_range_of_words (idx_t beg, idx_t end); 2.16 void clear_large_range_of_words (idx_t beg, idx_t end); 2.17 2.18 + static bool is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word); 2.19 + 2.20 // The index of the first full word in a range. 2.21 idx_t word_index_round_up(idx_t bit) const; 2.22
3.1 --- a/src/share/vm/utilities/bitMap.inline.hpp Mon Feb 11 17:00:04 2019 +0100 3.2 +++ b/src/share/vm/utilities/bitMap.inline.hpp Tue Feb 12 11:58:44 2019 +0100 3.3 @@ -321,10 +321,12 @@ 3.4 } 3.5 3.6 inline void BitMap::set_large_range_of_words(idx_t beg, idx_t end) { 3.7 + assert(beg <= end, "underflow"); 3.8 memset(_map + beg, ~(unsigned char)0, (end - beg) * sizeof(uintptr_t)); 3.9 } 3.10 3.11 inline void BitMap::clear_large_range_of_words(idx_t beg, idx_t end) { 3.12 + assert(beg <= end, "underflow"); 3.13 memset(_map + beg, 0, (end - beg) * sizeof(uintptr_t)); 3.14 } 3.15