# HG changeset patch # User sla # Date 1367314122 25200 # Node ID 409d4b59e095af125afbb90fe58c801e45c5a349 # Parent 9f96b7a853bcc65af4eab4d5991a9bb924fbfa65# Parent f32b6c267d2e37d66cfdf58c00cbac43e6bdebfd Merge diff -r 9f96b7a853bc -r 409d4b59e095 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Tue Apr 30 10:53:58 2013 +0200 +++ b/src/os/bsd/vm/os_bsd.cpp Tue Apr 30 02:28:42 2013 -0700 @@ -2080,9 +2080,10 @@ flags |= MAP_FIXED; } - // Map uncommitted pages PROT_READ and PROT_WRITE, change access - // to PROT_EXEC if executable when we commit the page. - addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE, + // Map reserved/uncommitted pages PROT_NONE so we fail early if we + // touch an uncommitted page. Otherwise, the read/write might + // succeed if we have enough swap space to back the physical page. + addr = (char*)::mmap(requested_addr, bytes, PROT_NONE, flags, -1, 0); if (addr != MAP_FAILED) { diff -r 9f96b7a853bc -r 409d4b59e095 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Tue Apr 30 10:53:58 2013 +0200 +++ b/src/os/linux/vm/os_linux.cpp Tue Apr 30 02:28:42 2013 -0700 @@ -2906,9 +2906,10 @@ flags |= MAP_FIXED; } - // Map uncommitted pages PROT_READ and PROT_WRITE, change access - // to PROT_EXEC if executable when we commit the page. - addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE, + // Map reserved/uncommitted pages PROT_NONE so we fail early if we + // touch an uncommitted page. Otherwise, the read/write might + // succeed if we have enough swap space to back the physical page. + addr = (char*)::mmap(requested_addr, bytes, PROT_NONE, flags, -1, 0); if (addr != MAP_FAILED) { diff -r 9f96b7a853bc -r 409d4b59e095 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Tue Apr 30 10:53:58 2013 +0200 +++ b/src/share/vm/classfile/classFileParser.cpp Tue Apr 30 02:28:42 2013 -0700 @@ -2027,7 +2027,6 @@ u2 method_parameters_length = 0; u1* method_parameters_data = NULL; bool method_parameters_seen = false; - bool method_parameters_four_byte_flags; bool parsed_code_attribute = false; bool parsed_checked_exceptions_attribute = false; bool parsed_stackmap_attribute = false; @@ -2241,26 +2240,14 @@ } method_parameters_seen = true; method_parameters_length = cfs->get_u1_fast(); - // Track the actual size (note: this is written for clarity; a - // decent compiler will CSE and constant-fold this into a single - // expression) - // Use the attribute length to figure out the size of flags - if (method_attribute_length == (method_parameters_length * 6u) + 1u) { - method_parameters_four_byte_flags = true; - } else if (method_attribute_length == (method_parameters_length * 4u) + 1u) { - method_parameters_four_byte_flags = false; - } else { + if (method_attribute_length != (method_parameters_length * 4u) + 1u) { classfile_parse_error( "Invalid MethodParameters method attribute length %u in class file", method_attribute_length, CHECK_(nullHandle)); } method_parameters_data = cfs->get_u1_buffer(); cfs->skip_u2_fast(method_parameters_length); - if (method_parameters_four_byte_flags) { - cfs->skip_u4_fast(method_parameters_length); - } else { - cfs->skip_u2_fast(method_parameters_length); - } + cfs->skip_u2_fast(method_parameters_length); // ignore this attribute if it cannot be reflected if (!SystemDictionary::Parameter_klass_loaded()) method_parameters_length = 0; @@ -2423,13 +2410,8 @@ for (int i = 0; i < method_parameters_length; i++) { elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data); method_parameters_data += 2; - if (method_parameters_four_byte_flags) { - elem[i].flags = Bytes::get_Java_u4(method_parameters_data); - method_parameters_data += 4; - } else { - elem[i].flags = Bytes::get_Java_u2(method_parameters_data); - method_parameters_data += 2; - } + elem[i].flags = Bytes::get_Java_u2(method_parameters_data); + method_parameters_data += 2; } } diff -r 9f96b7a853bc -r 409d4b59e095 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Tue Apr 30 10:53:58 2013 +0200 +++ b/src/share/vm/classfile/javaClasses.cpp Tue Apr 30 02:28:42 2013 -0700 @@ -315,14 +315,18 @@ return string; } -jchar* java_lang_String::as_unicode_string(oop java_string, int& length) { +jchar* java_lang_String::as_unicode_string(oop java_string, int& length, TRAPS) { typeArrayOop value = java_lang_String::value(java_string); int offset = java_lang_String::offset(java_string); length = java_lang_String::length(java_string); - jchar* result = NEW_RESOURCE_ARRAY(jchar, length); - for (int index = 0; index < length; index++) { - result[index] = value->char_at(index + offset); + jchar* result = NEW_RESOURCE_ARRAY_RETURN_NULL(jchar, length); + if (result != NULL) { + for (int index = 0; index < length; index++) { + result[index] = value->char_at(index + offset); + } + } else { + THROW_MSG_0(vmSymbols::java_lang_OutOfMemoryError(), "could not allocate Unicode string"); } return result; } diff -r 9f96b7a853bc -r 409d4b59e095 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Tue Apr 30 10:53:58 2013 +0200 +++ b/src/share/vm/classfile/javaClasses.hpp Tue Apr 30 02:28:42 2013 -0700 @@ -153,7 +153,7 @@ static char* as_utf8_string(oop java_string, char* buf, int buflen); static char* as_utf8_string(oop java_string, int start, int len); static char* as_platform_dependent_str(Handle java_string, TRAPS); - static jchar* as_unicode_string(oop java_string, int& length); + static jchar* as_unicode_string(oop java_string, int& length, TRAPS); // produce an ascii string with all other values quoted using \u#### static char* as_quoted_ascii(oop java_string); diff -r 9f96b7a853bc -r 409d4b59e095 src/share/vm/classfile/symbolTable.cpp --- a/src/share/vm/classfile/symbolTable.cpp Tue Apr 30 10:53:58 2013 +0200 +++ b/src/share/vm/classfile/symbolTable.cpp Tue Apr 30 02:28:42 2013 -0700 @@ -735,7 +735,7 @@ ResourceMark rm(THREAD); int length; Handle h_string (THREAD, string); - jchar* chars = java_lang_String::as_unicode_string(string, length); + jchar* chars = java_lang_String::as_unicode_string(string, length, CHECK_NULL); oop result = intern(h_string, chars, length, CHECK_NULL); return result; } diff -r 9f96b7a853bc -r 409d4b59e095 src/share/vm/memory/allocation.hpp --- a/src/share/vm/memory/allocation.hpp Tue Apr 30 10:53:58 2013 +0200 +++ b/src/share/vm/memory/allocation.hpp Tue Apr 30 02:28:42 2013 -0700 @@ -539,6 +539,9 @@ #define NEW_RESOURCE_ARRAY(type, size)\ (type*) resource_allocate_bytes((size) * sizeof(type)) +#define NEW_RESOURCE_ARRAY_RETURN_NULL(type, size)\ + (type*) resource_allocate_bytes((size) * sizeof(type), AllocFailStrategy::RETURN_NULL) + #define NEW_RESOURCE_ARRAY_IN_THREAD(thread, type, size)\ (type*) resource_allocate_bytes(thread, (size) * sizeof(type)) diff -r 9f96b7a853bc -r 409d4b59e095 src/share/vm/oops/oop.cpp --- a/src/share/vm/oops/oop.cpp Tue Apr 30 10:53:58 2013 +0200 +++ b/src/share/vm/oops/oop.cpp Tue Apr 30 02:28:42 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,11 +103,17 @@ // When String table needs to rehash unsigned int oopDesc::new_hash(jint seed) { + EXCEPTION_MARK; ResourceMark rm; int length; - jchar* chars = java_lang_String::as_unicode_string(this, length); - // Use alternate hashing algorithm on the string - return AltHashing::murmur3_32(seed, chars, length); + jchar* chars = java_lang_String::as_unicode_string(this, length, THREAD); + if (chars != NULL) { + // Use alternate hashing algorithm on the string + return AltHashing::murmur3_32(seed, chars, length); + } else { + vm_exit_out_of_memory(length, "unable to create Unicode strings for String table rehash"); + return 0; + } } VerifyOopClosure VerifyOopClosure::verify_oop; diff -r 9f96b7a853bc -r 409d4b59e095 src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Tue Apr 30 10:53:58 2013 +0200 +++ b/src/share/vm/prims/whitebox.cpp Tue Apr 30 02:28:42 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -310,12 +310,8 @@ WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString)) ResourceMark rm(THREAD); int len; - jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len); - oop found_string = StringTable::the_table()->lookup(name, len); - if (found_string == NULL) { - return false; - } - return true; + jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false); + return (StringTable::lookup(name, len) != NULL); WB_END @@ -324,6 +320,11 @@ Universe::heap()->collect(GCCause::_last_ditch_collection); WB_END + +WB_ENTRY(jlong, WB_ReserveMemory(JNIEnv* env, jobject o, jlong size)) + return (jlong)os::reserve_memory(size, NULL, 0); +WB_END + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -425,6 +426,8 @@ CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState}, {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable }, {CC"fullGC", CC"()V", (void*)&WB_FullGC }, + + {CC"reserveMemory", CC"(J)J", (void*)&WB_ReserveMemory }, }; #undef CC diff -r 9f96b7a853bc -r 409d4b59e095 test/runtime/memory/ReserveMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/memory/ReserveMemory.java Tue Apr 30 02:28:42 2013 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key regression + * @bug 8012015 + * @summary Make sure reserved (but uncommitted) memory is not accessible + * @library /testlibrary /testlibrary/whitebox + * @build ReserveMemory + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main ReserveMemory + */ + +import com.oracle.java.testlibrary.*; + +import java.lang.reflect.Field; +import sun.hotspot.WhiteBox; +import sun.misc.Unsafe; + +public class ReserveMemory { + private static Unsafe getUnsafe() throws Exception { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + return (Unsafe)f.get(null); + } + + private static boolean isWindows() { + return System.getProperty("os.name").toLowerCase().startsWith("win"); + } + + public static void main(String args[]) throws Exception { + if (args.length > 0) { + long address = WhiteBox.getWhiteBox().reserveMemory(4096); + + System.out.println("Reserved memory at address: 0x" + Long.toHexString(address)); + System.out.println("Will now read from the address, expecting a crash!"); + + int x = getUnsafe().getInt(address); + + throw new Exception("Read of reserved/uncommitted memory unexpectedly succeeded, expected crash!"); + } + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "ReserveMemory", + "test"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + if (isWindows()) { + output.shouldContain("EXCEPTION_ACCESS_VIOLATION"); + } else { + output.shouldContain("SIGSEGV"); + } + } +} diff -r 9f96b7a853bc -r 409d4b59e095 test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Tue Apr 30 10:53:58 2013 +0200 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Tue Apr 30 02:28:42 2013 -0700 @@ -111,6 +111,9 @@ // Intered strings public native boolean isInStringTable(String str); + // Memory + public native long reserveMemory(long size); + // force Full GC public native void fullGC(); }