8230043: Lazily load libverify

8230140: Remove unused mutex and monitor declarations

Reviewed-by: hseigel, erikj, alanb, dholmes
This commit is contained in:
Claes Redestad 2019-10-07 16:55:24 +02:00
parent 204ed44122
commit fba19ffbb2
12 changed files with 74 additions and 152 deletions

View file

@ -35,12 +35,9 @@
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "check_classname.h"
#include "java_lang_Class.h"
/* defined in libverify.so/verify.dll (src file common/check_format.c) */
extern jboolean VerifyClassname(char *utf_name, jboolean arrayAllowed);
extern jboolean VerifyFixClassname(char *utf_name);
#define OBJ "Ljava/lang/Object;"
#define CLS "Ljava/lang/Class;"
#define CPL "Ljdk/internal/reflect/ConstantPool;"
@ -123,14 +120,14 @@ Java_java_lang_Class_forName0(JNIEnv *env, jclass this, jstring classname,
}
(*env)->GetStringUTFRegion(env, classname, 0, unicode_len, clname);
if (VerifyFixClassname(clname) == JNI_TRUE) {
if (verifyFixClassname(clname) == JNI_TRUE) {
/* slashes present in clname, use name b4 translation for exception */
(*env)->GetStringUTFRegion(env, classname, 0, unicode_len, clname);
JNU_ThrowClassNotFoundException(env, clname);
goto done;
}
if (!VerifyClassname(clname, JNI_TRUE)) { /* expects slashed name */
if (!verifyClassname(clname, JNI_TRUE)) { /* expects slashed name */
JNU_ThrowClassNotFoundException(env, clname);
goto done;
}

View file

@ -30,14 +30,11 @@
#include "jni_util.h"
#include "jlong.h"
#include "jvm.h"
#include "check_classname.h"
#include "java_lang_ClassLoader.h"
#include "java_lang_ClassLoader_NativeLibrary.h"
#include <string.h>
/* defined in libverify.so/verify.dll (src file common/check_format.c) */
extern jboolean VerifyClassname(char *utf_name, jboolean arrayAllowed);
extern jboolean VerifyFixClassname(char *utf_name);
static JNINativeMethod methods[] = {
{"retrieveDirectives", "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives}
};
@ -120,7 +117,7 @@ Java_java_lang_ClassLoader_defineClass1(JNIEnv *env,
if (utfName == NULL) {
goto free_body;
}
VerifyFixClassname(utfName);
fixClassname(utfName);
} else {
utfName = NULL;
}
@ -185,7 +182,7 @@ Java_java_lang_ClassLoader_defineClass2(JNIEnv *env,
JNU_ThrowOutOfMemoryError(env, NULL);
return result;
}
VerifyFixClassname(utfName);
fixClassname(utfName);
} else {
utfName = NULL;
}
@ -231,9 +228,9 @@ Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader,
JNU_ThrowOutOfMemoryError(env, NULL);
return NULL;
}
VerifyFixClassname(clname);
fixClassname(clname);
if (!VerifyClassname(clname, JNI_TRUE)) { /* expects slashed name */
if (!verifyClassname(clname, JNI_TRUE)) { /* expects slashed name */
goto done;
}

View file

@ -0,0 +1,292 @@
/*
* Copyright (c) 1997, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
#include <assert.h>
#include <limits.h>
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#include "jni.h"
#include "jvm.h"
#include "check_classname.h"
typedef unsigned short unicode;
static char *
skip_over_fieldname(char *name, jboolean slash_okay,
unsigned int len);
static char *
skip_over_field_signature(char *name, jboolean void_okay,
unsigned int len);
/*
* Return non-zero if the character is a valid in JVM class name, zero
* otherwise. The only characters currently disallowed from JVM class
* names are given in the table below:
*
* Character Hex Decimal
* '.' 0x2e 46
* '/' 0x2f 47
* ';' 0x3b 59
* '[' 0x5b 91
*
* (Method names have further restrictions dealing with the '<' and
* '>' characters.)
*/
static int isJvmIdentifier(unicode ch) {
if( ch > 91 || ch < 46 )
return 1; /* Lowercase ASCII letters are > 91 */
else { /* 46 <= ch <= 91 */
if (ch <= 90 && ch >= 60) {
return 1; /* Uppercase ASCII recognized here */
} else { /* ch == 91 || 46 <= ch <= 59 */
if (ch == 91 || ch == 59 || ch <= 47)
return 0;
else
return 1;
}
}
}
static unicode
next_utf2unicode(char **utfstring_ptr, int * valid)
{
unsigned char *ptr = (unsigned char *)(*utfstring_ptr);
unsigned char ch, ch2, ch3;
int length = 1; /* default length */
unicode result = 0x80; /* default bad result; */
*valid = 1;
switch ((ch = ptr[0]) >> 4) {
default:
result = ch;
break;
case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:
/* Shouldn't happen. */
*valid = 0;
break;
case 0xC: case 0xD:
/* 110xxxxx 10xxxxxx */
if (((ch2 = ptr[1]) & 0xC0) == 0x80) {
unsigned char high_five = ch & 0x1F;
unsigned char low_six = ch2 & 0x3F;
result = (high_five << 6) + low_six;
length = 2;
}
break;
case 0xE:
/* 1110xxxx 10xxxxxx 10xxxxxx */
if (((ch2 = ptr[1]) & 0xC0) == 0x80) {
if (((ch3 = ptr[2]) & 0xC0) == 0x80) {
unsigned char high_four = ch & 0x0f;
unsigned char mid_six = ch2 & 0x3f;
unsigned char low_six = ch3 & 0x3f;
result = (((high_four << 6) + mid_six) << 6) + low_six;
length = 3;
} else {
length = 2;
}
}
break;
} /* end of switch */
*utfstring_ptr = (char *)(ptr + length);
return result;
}
/* Take pointer to a string. Skip over the longest part of the string that
* could be taken as a fieldname. Allow '/' if slash_okay is JNI_TRUE.
*
* Return a pointer to just past the fieldname. Return NULL if no fieldname
* at all was found, or in the case of slash_okay being true, we saw
* consecutive slashes (meaning we were looking for a qualified path but
* found something that was badly-formed).
*/
static char *
skip_over_fieldname(char *name, jboolean slash_okay,
unsigned int length)
{
char *p;
unicode ch;
unicode last_ch = 0;
int valid = 1;
/* last_ch == 0 implies we are looking at the first char. */
for (p = name; p != name + length; last_ch = ch) {
char *old_p = p;
ch = *p;
if (ch < 128) {
p++;
if (isJvmIdentifier(ch)) {
continue;
}
} else {
char *tmp_p = p;
ch = next_utf2unicode(&tmp_p, &valid);
if (valid == 0)
return 0;
p = tmp_p;
if (isJvmIdentifier(ch)) {
continue;
}
}
if (slash_okay && ch == '/' && last_ch) {
if (last_ch == '/') {
return 0; /* Don't permit consecutive slashes */
}
} else if (ch == '_' || ch == '$') {
} else {
return last_ch ? old_p : 0;
}
}
return last_ch ? p : 0;
}
/* Take pointer to a string. Skip over the longest part of the string that
* could be taken as a field signature. Allow "void" if void_okay.
*
* Return a pointer to just past the signature. Return NULL if no legal
* signature is found.
*/
static char *
skip_over_field_signature(char *name, jboolean void_okay,
unsigned int length)
{
unsigned int array_dim = 0;
for (;length > 0;) {
switch (name[0]) {
case JVM_SIGNATURE_VOID:
if (!void_okay) return 0;
/* FALL THROUGH */
case JVM_SIGNATURE_BOOLEAN:
case JVM_SIGNATURE_BYTE:
case JVM_SIGNATURE_CHAR:
case JVM_SIGNATURE_SHORT:
case JVM_SIGNATURE_INT:
case JVM_SIGNATURE_FLOAT:
case JVM_SIGNATURE_LONG:
case JVM_SIGNATURE_DOUBLE:
return name + 1;
case JVM_SIGNATURE_CLASS: {
/* Skip over the classname, if one is there. */
char *p =
skip_over_fieldname(name + 1, JNI_TRUE, --length);
/* The next character better be a semicolon. */
if (p && p - name - 1 > 0 && p[0] == ';')
return p + 1;
return 0;
}
case JVM_SIGNATURE_ARRAY:
array_dim++;
/* JVMS 2nd ed. 4.10 */
/* The number of dimensions in an array is limited to 255 ... */
if (array_dim > 255) {
return 0;
}
/* The rest of what's there better be a legal signature. */
name++;
length--;
void_okay = JNI_FALSE;
break;
default:
return 0;
}
}
return 0;
}
/* Determine if the specified name is legal
* UTF name for a classname.
*
* Note that this routine expects the internal form of qualified classes:
* the dots should have been replaced by slashes.
*/
jboolean verifyClassname(char *name, jboolean allowArrayClass)
{
size_t s = strlen(name);
assert(s <= UINT_MAX);
unsigned int length = (unsigned int)s;
char *p;
if (length > 0 && name[0] == JVM_SIGNATURE_ARRAY) {
if (!allowArrayClass) {
return JNI_FALSE;
} else {
/* Everything that's left better be a field signature */
p = skip_over_field_signature(name, JNI_FALSE, length);
}
} else {
/* skip over the fieldname. Slashes are okay */
p = skip_over_fieldname(name, JNI_TRUE, length);
}
return (p != 0 && p - name == (ptrdiff_t)length);
}
/*
* Translates '.' to '/'. Returns JNI_TRUE if any / were present.
*/
jboolean verifyFixClassname(char *name)
{
char *p = name;
jboolean slashesFound = JNI_FALSE;
int valid = 1;
while (valid != 0 && *p != '\0') {
if (*p == '/') {
slashesFound = JNI_TRUE;
p++;
} else if (*p == '.') {
*p++ = '/';
} else {
next_utf2unicode(&p, &valid);
}
}
return slashesFound && valid != 0;
}
/*
* Translates '.' to '/'.
*/
void fixClassname(char *name)
{
char *p = name;
int valid = 1;
while (valid != 0 && *p != '\0') {
if (*p == '.') {
*p++ = '/';
} else {
next_utf2unicode(&p, &valid);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 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
@ -23,37 +23,12 @@
* questions.
*/
/*
* The real verifier now lives in libverifier.so/verifier.dll.
*
* This dummy exists so that HotSpot will run with the new
* libjava.so/java.dll which is where is it accustomed to finding the
* verifier.
*/
#include "jni.h"
struct struct_class_size_info;
typedef struct struct_class_size_info class_size_info;
/*
* Class name checking methods
*/
JNIIMPORT jboolean
VerifyClass(JNIEnv *env, jclass cb, char *buffer, jint len);
JNIIMPORT jboolean
VerifyClassForMajorVersion(JNIEnv *env, jclass cb, char *buffer, jint len,
jint major_version);
JNIEXPORT jboolean
VerifyClassCodes(JNIEnv *env, jclass cb, char *buffer, jint len)
{
return VerifyClass(env, cb, buffer, len);
}
JNIEXPORT jboolean
VerifyClassCodesForMajorVersion(JNIEnv *env, jclass cb, char *buffer,
jint len, jint major_version)
{
return VerifyClassForMajorVersion(env, cb, buffer, len, major_version);
}
jboolean verifyClassname(char *name, jboolean allowArrayClass);
jboolean verifyFixClassname(char *name);
void fixClassname(char *name);