From 800f347c32b616bc4f830ddd7b280c40a0507454 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 5 Dec 2023 15:08:37 +0000 Subject: [PATCH] 8321216: SerialGC attempts to access the card table beyond the end of the heap during card table scan Co-authored-by: Albert Mingkun Yang Reviewed-by: ayang, iwalulya --- src/hotspot/share/gc/serial/cardTableRS.cpp | 13 ++++++++++++- src/hotspot/share/gc/shared/cardTable.hpp | 15 ++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/gc/serial/cardTableRS.cpp b/src/hotspot/share/gc/serial/cardTableRS.cpp index 375860c9a1f..4df9fbad212 100644 --- a/src/hotspot/share/gc/serial/cardTableRS.cpp +++ b/src/hotspot/share/gc/serial/cardTableRS.cpp @@ -392,6 +392,10 @@ CardTable::CardValue* CardTableRS::find_first_clean_card(CardValue* const start_ CardValue* const end_card, CardTableRS* ct, Func& object_start) { + + // end_card might be just beyond the heap, so need to use the _raw variant. + HeapWord* end_address = ct->addr_for_raw(end_card); + for (CardValue* current_card = start_card; current_card < end_card; /* empty */) { if (is_dirty(current_card)) { current_card++; @@ -414,8 +418,15 @@ CardTable::CardValue* CardTableRS::find_first_clean_card(CardValue* const start_ return current_card; } + // This might be the last object in this area, avoid trying to access the + // card beyond the allowed area. + HeapWord* next_address = obj_start_addr + obj->size(); + if (next_address >= end_address) { + break; + } + // Card occupied by next obj. - CardValue* next_obj_card = ct->byte_for(obj_start_addr + obj->size()); + CardValue* next_obj_card = ct->byte_for(next_address); if (is_clean(next_obj_card)) { return next_obj_card; } diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index dfa2fe39ccb..b9a7b516d8b 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -83,6 +83,14 @@ protected: return cards_required(_whole_heap.word_size()) - 1; } + // Mapping from card marking array entry to address of first word without checks. + HeapWord* addr_for_raw(const CardValue* p) const { + // As _byte_map_base may be "negative" (the card table has been allocated before + // the heap in memory), do not use pointer_delta() to avoid the assertion failure. + size_t delta = p - _byte_map_base; + return (HeapWord*) (delta << _card_shift); + } + private: void initialize_covered_region(void* region0_start, void* region1_start); @@ -144,16 +152,13 @@ public: return byte_after(p); } - // Mapping from card marking array entry to address of first word + // Mapping from card marking array entry to address of first word. HeapWord* addr_for(const CardValue* p) const { assert(p >= _byte_map && p < _byte_map + _byte_map_size, "out of bounds access to card marking array. p: " PTR_FORMAT " _byte_map: " PTR_FORMAT " _byte_map + _byte_map_size: " PTR_FORMAT, p2i(p), p2i(_byte_map), p2i(_byte_map + _byte_map_size)); - // As _byte_map_base may be "negative" (the card table has been allocated before - // the heap in memory), do not use pointer_delta() to avoid the assertion failure. - size_t delta = p - _byte_map_base; - HeapWord* result = (HeapWord*) (delta << _card_shift); + HeapWord* result = addr_for_raw(p); assert(_whole_heap.contains(result), "Returning result = " PTR_FORMAT " out of bounds of " " card marking array's _whole_heap = [" PTR_FORMAT "," PTR_FORMAT ")",