Mon, 09 Dec 2013 10:03:39 +0100
8029106: JVM crashes in Metachunk::Metachunk during parallel class redefinition (PrivateMLetController, anonymous-simple_copy_1)
Summary: Fixed overflow bug in VirtualSpaceNode::is_available
Reviewed-by: mgerdin, brutisso, coleenp, jmasa
src/share/vm/memory/metaspace.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/vm/memory/metaspace.cpp Tue Dec 10 10:31:00 2013 +0100 1.2 +++ b/src/share/vm/memory/metaspace.cpp Mon Dec 09 10:03:39 2013 +0100 1.3 @@ -287,7 +287,7 @@ 1.4 VirtualSpace* virtual_space() const { return (VirtualSpace*) &_virtual_space; } 1.5 1.6 // Returns true if "word_size" is available in the VirtualSpace 1.7 - bool is_available(size_t word_size) { return _top + word_size <= end(); } 1.8 + bool is_available(size_t word_size) { return word_size <= pointer_delta(end(), _top, sizeof(MetaWord)); } 1.9 1.10 MetaWord* top() const { return _top; } 1.11 void inc_top(size_t word_size) { _top += word_size; } 1.12 @@ -3641,10 +3641,82 @@ 1.13 } 1.14 1.15 } 1.16 + 1.17 +#define assert_is_available_positive(word_size) \ 1.18 + assert(vsn.is_available(word_size), \ 1.19 + err_msg(#word_size ": " PTR_FORMAT " bytes were not available in " \ 1.20 + "VirtualSpaceNode [" PTR_FORMAT ", " PTR_FORMAT ")", \ 1.21 + (uintptr_t)(word_size * BytesPerWord), vsn.bottom(), vsn.end())); 1.22 + 1.23 +#define assert_is_available_negative(word_size) \ 1.24 + assert(!vsn.is_available(word_size), \ 1.25 + err_msg(#word_size ": " PTR_FORMAT " bytes should not be available in " \ 1.26 + "VirtualSpaceNode [" PTR_FORMAT ", " PTR_FORMAT ")", \ 1.27 + (uintptr_t)(word_size * BytesPerWord), vsn.bottom(), vsn.end())); 1.28 + 1.29 + static void test_is_available_positive() { 1.30 + // Reserve some memory. 1.31 + VirtualSpaceNode vsn(os::vm_allocation_granularity()); 1.32 + assert(vsn.initialize(), "Failed to setup VirtualSpaceNode"); 1.33 + 1.34 + // Commit some memory. 1.35 + size_t commit_word_size = os::vm_allocation_granularity() / BytesPerWord; 1.36 + bool expanded = vsn.expand_by(commit_word_size, commit_word_size); 1.37 + assert(expanded, "Failed to commit"); 1.38 + 1.39 + // Check that is_available accepts the committed size. 1.40 + assert_is_available_positive(commit_word_size); 1.41 + 1.42 + // Check that is_available accepts half the committed size. 1.43 + size_t expand_word_size = commit_word_size / 2; 1.44 + assert_is_available_positive(expand_word_size); 1.45 + } 1.46 + 1.47 + static void test_is_available_negative() { 1.48 + // Reserve some memory. 1.49 + VirtualSpaceNode vsn(os::vm_allocation_granularity()); 1.50 + assert(vsn.initialize(), "Failed to setup VirtualSpaceNode"); 1.51 + 1.52 + // Commit some memory. 1.53 + size_t commit_word_size = os::vm_allocation_granularity() / BytesPerWord; 1.54 + bool expanded = vsn.expand_by(commit_word_size, commit_word_size); 1.55 + assert(expanded, "Failed to commit"); 1.56 + 1.57 + // Check that is_available doesn't accept a too large size. 1.58 + size_t two_times_commit_word_size = commit_word_size * 2; 1.59 + assert_is_available_negative(two_times_commit_word_size); 1.60 + } 1.61 + 1.62 + static void test_is_available_overflow() { 1.63 + // Reserve some memory. 1.64 + VirtualSpaceNode vsn(os::vm_allocation_granularity()); 1.65 + assert(vsn.initialize(), "Failed to setup VirtualSpaceNode"); 1.66 + 1.67 + // Commit some memory. 1.68 + size_t commit_word_size = os::vm_allocation_granularity() / BytesPerWord; 1.69 + bool expanded = vsn.expand_by(commit_word_size, commit_word_size); 1.70 + assert(expanded, "Failed to commit"); 1.71 + 1.72 + // Calculate a size that will overflow the virtual space size. 1.73 + void* virtual_space_max = (void*)(uintptr_t)-1; 1.74 + size_t bottom_to_max = pointer_delta(virtual_space_max, vsn.bottom(), 1); 1.75 + size_t overflow_size = bottom_to_max + BytesPerWord; 1.76 + size_t overflow_word_size = overflow_size / BytesPerWord; 1.77 + 1.78 + // Check that is_available can handle the overflow. 1.79 + assert_is_available_negative(overflow_word_size); 1.80 + } 1.81 + 1.82 + static void test_is_available() { 1.83 + TestVirtualSpaceNodeTest::test_is_available_positive(); 1.84 + TestVirtualSpaceNodeTest::test_is_available_negative(); 1.85 + TestVirtualSpaceNodeTest::test_is_available_overflow(); 1.86 + } 1.87 }; 1.88 1.89 void TestVirtualSpaceNode_test() { 1.90 TestVirtualSpaceNodeTest::test(); 1.91 + TestVirtualSpaceNodeTest::test_is_available(); 1.92 } 1.93 1.94 #endif