diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 5a542c393e0..2969f0f4783 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,27 @@ +2001-11-25 Tom Tromey + + Fix for PR libgcj/2024, plus other class name cleanups: + * include/jvm.h (_Jv_VerifyFieldSignature, + _Jv_VerifyMethodSignature, _Jv_VerifyClassName, + _Jv_VerifyIdentifier, _Jv_ClassNameSamePackage): Moved from ... + * include/java-interp.h: ... here. + * defineclass.cc (UTF8_PEEK): No longer conditional on + interpreter. + (_Jv_VerifyOne): Likewise. + (_Jv_VerifyFieldSignature): Likewise. + (_Jv_VerifyMethodSignature): Likewise. + (is_identifier_start): Likewise. + (is_identifier_part): Likewise. + (_Jv_VerifyIdentifier): Likewise. + (_Jv_VerifyClassName): Likewise. + (_Jv_VerifyClassName): Likewise. + (_Jv_ClassNameSamePackage): Likewise. + (_Jv_VerifyClassName): Fail if class name is too long. + * java/lang/natClassLoader.cc (_Jv_NewArrayClass): Disallow array + of void. + * java/lang/natClass.cc (forName): Check syntax of class name. + Include IllegalArgumentException.h. + 2001-11-22 Tom Tromey * verify.cc (_Jv_BytecodeVerifier::branch_prepass): Use diff --git a/libjava/defineclass.cc b/libjava/defineclass.cc index db37203e2c4..3a6eaba9227 100644 --- a/libjava/defineclass.cc +++ b/libjava/defineclass.cc @@ -22,8 +22,6 @@ details. */ #include -#ifdef INTERPRETER - #include #include #include @@ -43,6 +41,8 @@ details. */ using namespace gcj; +#ifdef INTERPRETER + // these go in some separate functions, to avoid having _Jv_InitClass // inserted all over the place. static void throw_internal_error (char *msg) @@ -1368,6 +1368,50 @@ void _Jv_ClassReader::throw_class_format_error (char *msg) ::throw_class_format_error (str); } +/** Here we define the exceptions that can be thrown */ + +static void +throw_no_class_def_found_error (jstring msg) +{ + throw (msg + ? new java::lang::NoClassDefFoundError (msg) + : new java::lang::NoClassDefFoundError); +} + +static void +throw_no_class_def_found_error (char *msg) +{ + throw_no_class_def_found_error (JvNewStringLatin1 (msg)); +} + +static void +throw_class_format_error (jstring msg) +{ + throw (msg + ? new java::lang::ClassFormatError (msg) + : new java::lang::ClassFormatError); +} + +static void +throw_internal_error (char *msg) +{ + throw new java::lang::InternalError (JvNewStringLatin1 (msg)); +} + +static void throw_incompatible_class_change_error (jstring msg) +{ + throw new java::lang::IncompatibleClassChangeError (msg); +} + +static void throw_class_circularity_error (jstring msg) +{ + throw new java::lang::ClassCircularityError (msg); +} + +#endif /* INTERPRETER */ + + + /** This section takes care of verifying integrity of identifiers, signatures, field ddescriptors, and class names */ @@ -1376,7 +1420,7 @@ void _Jv_ClassReader::throw_class_format_error (char *msg) int xxch = UTF8_GET(PTR,LIMIT); \ PTR = xxkeep; xxch; }) -/* verify one element of a type descriptor or signature */ +/* Verify one element of a type descriptor or signature. */ static unsigned char* _Jv_VerifyOne (unsigned char* ptr, unsigned char* limit, bool void_ok) { @@ -1388,7 +1432,8 @@ _Jv_VerifyOne (unsigned char* ptr, unsigned char* limit, bool void_ok) switch (ch) { case 'V': - if (! void_ok) return 0; + if (! void_ok) + return 0; case 'S': case 'B': case 'I': case 'J': case 'Z': case 'C': case 'F': case 'D': @@ -1397,16 +1442,18 @@ _Jv_VerifyOne (unsigned char* ptr, unsigned char* limit, bool void_ok) case 'L': { unsigned char *start = ptr, *end; - do { - if (ptr > limit) - return 0; - - end = ptr; - - if ((ch = UTF8_GET (ptr, limit)) == -1) - return 0; - - } while (ch != ';'); + do + { + if (ptr > limit) + return 0; + + end = ptr; + + if ((ch = UTF8_GET (ptr, limit)) == -1) + return 0; + + } + while (ch != ';'); if (! _Jv_VerifyClassName (start, (unsigned short) (end-start))) return 0; } @@ -1415,18 +1462,15 @@ _Jv_VerifyOne (unsigned char* ptr, unsigned char* limit, bool void_ok) case '[': return _Jv_VerifyOne (ptr, limit, false); break; - + default: return 0; } return ptr; - } - -/** verification and loading procedures **/ - +/* Verification and loading procedures. */ bool _Jv_VerifyFieldSignature (_Jv_Utf8Const*sig) { @@ -1449,7 +1493,7 @@ _Jv_VerifyMethodSignature (_Jv_Utf8Const*sig) while (ptr && UTF8_PEEK (ptr, limit) != ')') ptr = _Jv_VerifyOne (ptr, limit, false); - + if (UTF8_GET (ptr, limit) != ')') return false; @@ -1459,9 +1503,8 @@ _Jv_VerifyMethodSignature (_Jv_Utf8Const*sig) return ptr == limit; } -/* we try to avoid calling the Character methods all the time, - in fact, they will only be called for non-standard things */ - +/* We try to avoid calling the Character methods all the time, in + fact, they will only be called for non-standard things. */ static __inline__ int is_identifier_start (int c) { @@ -1522,7 +1565,10 @@ _Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length) if ('[' == UTF8_PEEK (ptr, limit)) { - if (! _Jv_VerifyOne (++ptr, limit, false)) + unsigned char *end = _Jv_VerifyOne (++ptr, limit, false); + // _Jv_VerifyOne must leave us looking at the terminating nul + // byte. + if (! end || *end) return false; else return true; @@ -1554,9 +1600,8 @@ _Jv_VerifyClassName (_Jv_Utf8Const *name) (_Jv_ushort) name->length); } -/** returns true, if name1 and name2 represents classes in the same - package. */ - +/* Returns true, if NAME1 and NAME2 represent classes in the same + package. */ bool _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2) { @@ -1571,22 +1616,22 @@ _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2) if (ch1 == '.') last1 = ptr1; - + else if (ch1 == -1) return false; } - // now the length of name1's package name is len + // Now the length of NAME1's package name is LEN. int len = last1 - (unsigned char*) name1->data; - // if this is longer than name2, then we're off + // If this is longer than NAME2, then we're off. if (len > name2->length) return false; - // then compare the first len bytes for equality + // Then compare the first len bytes for equality. if (memcmp ((void*) name1->data, (void*) name2->data, len) == 0) { - // check that there are no .'s after position len in name2 + // Check that there are no .'s after position LEN in NAME2. unsigned char* ptr2 = (unsigned char*) name2->data + len; unsigned char* limit2 = @@ -1602,48 +1647,3 @@ _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2) } return false; } - - - -/** Here we define the exceptions that can be thrown */ - -static void -throw_no_class_def_found_error (jstring msg) -{ - throw (msg - ? new java::lang::NoClassDefFoundError (msg) - : new java::lang::NoClassDefFoundError); -} - -static void -throw_no_class_def_found_error (char *msg) -{ - throw_no_class_def_found_error (JvNewStringLatin1 (msg)); -} - -static void -throw_class_format_error (jstring msg) -{ - throw (msg - ? new java::lang::ClassFormatError (msg) - : new java::lang::ClassFormatError); -} - -static void -throw_internal_error (char *msg) -{ - throw new java::lang::InternalError (JvNewStringLatin1 (msg)); -} - -static void throw_incompatible_class_change_error (jstring msg) -{ - throw new java::lang::IncompatibleClassChangeError (msg); -} - -static void throw_class_circularity_error (jstring msg) -{ - throw new java::lang::ClassCircularityError (msg); -} - -#endif /* INTERPRETER */ - diff --git a/libjava/include/java-interp.h b/libjava/include/java-interp.h index 8eeb0949378..bc1f3ca1cf4 100644 --- a/libjava/include/java-interp.h +++ b/libjava/include/java-interp.h @@ -33,12 +33,6 @@ _Jv_IsInterpretedClass (jclass c) struct _Jv_ResolvedMethod; -bool _Jv_VerifyFieldSignature (_Jv_Utf8Const*sig); -bool _Jv_VerifyMethodSignature (_Jv_Utf8Const*sig); -bool _Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length); -bool _Jv_VerifyClassName (_Jv_Utf8Const *name); -bool _Jv_VerifyIdentifier (_Jv_Utf8Const *); -bool _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2); void _Jv_DefineClass (jclass, jbyteArray, jint, jint); void _Jv_InitField (jobject, jclass, int); diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index 858d960bf20..1cba08cf675 100644 --- a/libjava/include/jvm.h +++ b/libjava/include/jvm.h @@ -341,6 +341,14 @@ void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *); struct _Jv_JavaVM; _Jv_JavaVM *_Jv_GetJavaVM (); +// Some verification functions from defineclass.cc. +bool _Jv_VerifyFieldSignature (_Jv_Utf8Const*sig); +bool _Jv_VerifyMethodSignature (_Jv_Utf8Const*sig); +bool _Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length); +bool _Jv_VerifyClassName (_Jv_Utf8Const *name); +bool _Jv_VerifyIdentifier (_Jv_Utf8Const *); +bool _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2); + #ifdef ENABLE_JVMPI #include "jvmpi.h" diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index 2ca7960466d..e7f9a35cc3c 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -34,6 +34,7 @@ details. */ #include #include #include +#include #include #include #include @@ -75,10 +76,11 @@ java::lang::Class::forName (jstring className, jboolean initialize, char buffer[length]; _Jv_GetStringUTFRegion (className, 0, length, buffer); - // FIXME: should check syntax of CLASSNAME and throw - // IllegalArgumentException on failure. _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length); + if (! _Jv_VerifyClassName (name)) + throw new java::lang::ClassNotFoundException (className); + // FIXME: should use bootstrap class loader if loader is null. jclass klass = (buffer[0] == '[' ? _Jv_FindClassFromSignature (name->data, loader) diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc index d94055e1cf0..c9a58726a3c 100644 --- a/libjava/java/lang/natClassLoader.cc +++ b/libjava/java/lang/natClassLoader.cc @@ -598,7 +598,11 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader, return; if (element->isPrimitive()) - len = 3; + { + if (element == JvPrimClass (void)) + throw new java::lang::ClassNotFoundException (); + len = 3; + } else len = element->name->length + 5;