Commit ffd94572 by Tom Tromey Committed by Tom Tromey

Runtime.java: Comment fix.

	* java/lang/Runtime.java: Comment fix.
	* java/lang/ClassLoader.java (isAncestorOf): New method.
	(getParent): Uncommented security check.  Use isAncestorOf.
	* include/jvm.h (_Jv_CheckAccess): Declare.
	* java/lang/reflect/natConstructor.cc (newInstance): Perform
	access check.
	Include IllegalAccessException.h, ArrayIndexOutOfBoundsException.h.
	* java/lang/reflect/natArray.cc (newInstance): Pass caller's
	class loader to _Jv_GetArrayClass.
	Include ArrayIndexOutOfBoundsException.h.
	* java/lang/reflect/Field.java: Update comment to reflect status.
	(equals): Fixed indentation.
	* java/lang/Class.h (Class): Declare memberAccessCheck, not
	checkMemberAccess.  Make _Jv_CheckAccess a friend.
	* java/lang/Class.java (memberAccessCheck): New method from
	Classpath.
	(checkMemberAccess): Removed.
	(getDeclaredMethod): Use memberAccessCheck.
	(getField): Likewise.
	(getMethod): Likewise.
	* resolve.cc (_Jv_ResolvePoolEntry): Use _Jv_CheckAccess.
	(_Jv_SearchMethodInClass): Likewise.
	* prims.cc (_Jv_CheckAccess): New function.
	* jni.cc (_Jv_JNI_FindClass): Use getClassLoaderInternal.
	(_Jv_JNI_GetAnyFieldID): Likewise.
	* java/lang/natClass.cc (forName): Use getClassLoaderInternal.
	(getClassLoader): Added security check.
	(getConstructor): Call memberAccessCheck.
	(getDeclaredClasses): Likewise.
	(getDeclaredField): Likewise.
	(getDeclaredFields): Likewise.
	(_getConstructors): Likewise.
	(getDeclaredConstructor): Likewise.
	(getDeclaredMethods): Likewise.
	(getFields): Likewise.
	(getMethods): Likewise.
	(newInstance): Likewise.
	(_Jv_MakeVTable): Put method name in exception.
	* java/lang/reflect/natMethod.cc (getType): Use
	getClassLoaderInternal.
	(_Jv_GetTypesFromSignature): Likewise.
	(invoke): Perform access check.
	(_Jv_CallAnyMethodA): Removed old FIXME comments.
	Include ArrayIndexOutOfBoundsException.h.
	* java/lang/reflect/natField.cc (getType): Use
	getClassLoaderInternal.
	(_Jv_CheckFieldAccessibility): Removed.
	(getAddr): Use _Jv_CheckAccess; find caller.
	Include ArrayIndexOutOfBoundsException.h.

From-SVN: r69621
parent 3c87bc22
2003-07-20 Tom Tromey <tromey@redhat.com>
* java/lang/Runtime.java: Comment fix.
* java/lang/ClassLoader.java (isAncestorOf): New method.
(getParent): Uncommented security check. Use isAncestorOf.
* include/jvm.h (_Jv_CheckAccess): Declare.
* java/lang/reflect/natConstructor.cc (newInstance): Perform
access check.
Include IllegalAccessException.h, ArrayIndexOutOfBoundsException.h.
* java/lang/reflect/natArray.cc (newInstance): Pass caller's
class loader to _Jv_GetArrayClass.
Include ArrayIndexOutOfBoundsException.h.
* java/lang/reflect/Field.java: Update comment to reflect status.
(equals): Fixed indentation.
* java/lang/Class.h (Class): Declare memberAccessCheck, not
checkMemberAccess. Make _Jv_CheckAccess a friend.
* java/lang/Class.java (memberAccessCheck): New method from
Classpath.
(checkMemberAccess): Removed.
(getDeclaredMethod): Use memberAccessCheck.
(getField): Likewise.
(getMethod): Likewise.
* resolve.cc (_Jv_ResolvePoolEntry): Use _Jv_CheckAccess.
(_Jv_SearchMethodInClass): Likewise.
* prims.cc (_Jv_CheckAccess): New function.
* jni.cc (_Jv_JNI_FindClass): Use getClassLoaderInternal.
(_Jv_JNI_GetAnyFieldID): Likewise.
* java/lang/natClass.cc (forName): Use getClassLoaderInternal.
(getClassLoader): Added security check.
(getConstructor): Call memberAccessCheck.
(getDeclaredClasses): Likewise.
(getDeclaredField): Likewise.
(getDeclaredFields): Likewise.
(_getConstructors): Likewise.
(getDeclaredConstructor): Likewise.
(getDeclaredMethods): Likewise.
(getFields): Likewise.
(getMethods): Likewise.
(newInstance): Likewise.
(_Jv_MakeVTable): Put method name in exception.
* java/lang/reflect/natMethod.cc (getType): Use
getClassLoaderInternal.
(_Jv_GetTypesFromSignature): Likewise.
(invoke): Perform access check.
(_Jv_CallAnyMethodA): Removed old FIXME comments.
Include ArrayIndexOutOfBoundsException.h.
* java/lang/reflect/natField.cc (getType): Use
getClassLoaderInternal.
(_Jv_CheckFieldAccessibility): Removed.
(getAddr): Use _Jv_CheckAccess; find caller.
Include ArrayIndexOutOfBoundsException.h.
2003-07-20 Michael Koch <konqueror@gmx.de> 2003-07-20 Michael Koch <konqueror@gmx.de>
* java/net/URL.java * java/net/URL.java
(URL): Fixed documentation to name an argument correcty, Reformatted (URL): Fixed documentation to name an argument correcty, Reformatted
one method declaration. one method declaration.
(getURLStreamHandler): Added documentation from classpath. (getURLStreamHandler): Added documentation from classpath.
2003-07-19 Tom Tromey <tromey@redhat.com> 2003-07-19 Tom Tromey <tromey@redhat.com>
* mauve-libgcj: Don't run CollationElementIterator tests. * mauve-libgcj: Don't run CollationElementIterator tests.
......
// jvm.h - Header file for private implementation information. -*- c++ -*- // jvm.h - Header file for private implementation information. -*- c++ -*-
/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -326,6 +326,9 @@ extern void _Jv_GetTypesFromSignature (jmethodID method, ...@@ -326,6 +326,9 @@ extern void _Jv_GetTypesFromSignature (jmethodID method,
JArray<jclass> **arg_types_out, JArray<jclass> **arg_types_out,
jclass *return_type_out); jclass *return_type_out);
extern jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
jint flags);
extern jobject _Jv_CallAnyMethodA (jobject obj, jclass return_type, extern jobject _Jv_CallAnyMethodA (jobject obj, jclass return_type,
jmethodID meth, jboolean is_constructor, jmethodID meth, jboolean is_constructor,
JArray<jclass> *parameter_types, JArray<jclass> *parameter_types,
......
...@@ -243,7 +243,7 @@ public: ...@@ -243,7 +243,7 @@ public:
private: private:
void checkMemberAccess (jint flags); void memberAccessCheck (jint flags);
void initializeClass (void); void initializeClass (void);
...@@ -328,6 +328,9 @@ private: ...@@ -328,6 +328,9 @@ private:
friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *); friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
friend void _Jv_MakeVTable (jclass); friend void _Jv_MakeVTable (jclass);
friend jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
jint flags);
// Return array class corresponding to element type KLASS, creating it if // Return array class corresponding to element type KLASS, creating it if
// necessary. // necessary.
inline friend jclass inline friend jclass
......
...@@ -72,14 +72,7 @@ public final class Class implements Serializable ...@@ -72,14 +72,7 @@ public final class Class implements Serializable
public Method getDeclaredMethod (String methodName, Class[] parameterTypes) public Method getDeclaredMethod (String methodName, Class[] parameterTypes)
throws NoSuchMethodException, SecurityException throws NoSuchMethodException, SecurityException
{ {
SecurityManager sm = System.getSecurityManager(); memberAccessCheck(Member.DECLARED);
if (sm != null)
{
sm.checkMemberAccess(this, Member.DECLARED);
Package p = getPackage();
if (p != null)
sm.checkPackageAccess(p.getName());
}
if ("<init>".equals(methodName) || "<clinit>".equals(methodName)) if ("<init>".equals(methodName) || "<clinit>".equals(methodName))
throw new NoSuchMethodException(methodName); throw new NoSuchMethodException(methodName);
...@@ -101,9 +94,7 @@ public final class Class implements Serializable ...@@ -101,9 +94,7 @@ public final class Class implements Serializable
public Field getField (String fieldName) public Field getField (String fieldName)
throws NoSuchFieldException, SecurityException throws NoSuchFieldException, SecurityException
{ {
SecurityManager s = System.getSecurityManager(); memberAccessCheck (Member.PUBLIC);
if (s != null)
s.checkMemberAccess (this, java.lang.reflect.Member.DECLARED);
Field fld = getField(fieldName, fieldName.hashCode()); Field fld = getField(fieldName, fieldName.hashCode());
if (fld == null) if (fld == null)
throw new NoSuchFieldException(fieldName); throw new NoSuchFieldException(fieldName);
...@@ -148,14 +139,7 @@ public final class Class implements Serializable ...@@ -148,14 +139,7 @@ public final class Class implements Serializable
public Method getMethod (String methodName, Class[] parameterTypes) public Method getMethod (String methodName, Class[] parameterTypes)
throws NoSuchMethodException, SecurityException throws NoSuchMethodException, SecurityException
{ {
SecurityManager sm = System.getSecurityManager(); memberAccessCheck(Member.PUBLIC);
if (sm != null)
{
sm.checkMemberAccess(this, Member.PUBLIC);
Package p = getPackage();
if (p != null)
sm.checkPackageAccess(p.getName());
}
if ("<init>".equals(methodName) || "<clinit>".equals(methodName)) if ("<init>".equals(methodName) || "<clinit>".equals(methodName))
throw new NoSuchMethodException(methodName); throw new NoSuchMethodException(methodName);
...@@ -334,14 +318,6 @@ public final class Class implements Serializable ...@@ -334,14 +318,6 @@ public final class Class implements Serializable
{ {
} }
// Do a security check.
private void checkMemberAccess (int flags)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkMemberAccess(this, flags);
}
// Initialize the class. // Initialize the class.
private native void initializeClass (); private native void initializeClass ();
...@@ -361,4 +337,20 @@ public final class Class implements Serializable ...@@ -361,4 +337,20 @@ public final class Class implements Serializable
return ""; return "";
return name.substring(0, lastInd); return name.substring(0, lastInd);
} }
/**
* Perform security checks common to all of the methods that
* get members of this Class.
*/
private void memberAccessCheck(int which)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
sm.checkMemberAccess(this, which);
Package pkg = getPackage();
if (pkg != null)
sm.checkPackageAccess(pkg.getName());
}
}
} }
...@@ -162,12 +162,10 @@ public abstract class ClassLoader ...@@ -162,12 +162,10 @@ public abstract class ClassLoader
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) if (sm != null)
{ {
/* FIXME: security, getClassContext() not implemented.
Class c = VMSecurityManager.getClassContext()[1]; Class c = VMSecurityManager.getClassContext()[1];
ClassLoader cl = c.getClassLoader(); ClassLoader cl = c.getClassLoader();
if (cl != null && cl != this) if (cl != null && ! cl.isAncestorOf(this))
sm.checkPermission(new RuntimePermission("getClassLoader")); sm.checkPermission(new RuntimePermission("getClassLoader"));
*/
} }
return parent; return parent;
} }
...@@ -996,4 +994,20 @@ public abstract class ClassLoader ...@@ -996,4 +994,20 @@ public abstract class ClassLoader
packageAssertionStatus = new HashMap(); packageAssertionStatus = new HashMap();
classAssertionStatus = new HashMap(); classAssertionStatus = new HashMap();
} }
/**
* Return true if this loader is either the specified class loader
* or an ancestor thereof.
* @param loader the class loader to check
*/
final boolean isAncestorOf(ClassLoader loader)
{
while (loader != null)
{
if (this == loader)
return true;
loader = loader.parent;
}
return false;
}
} }
/* Runtime.java -- access to the VM process /* Runtime.java -- access to the VM process
Copyright (C) 1998, 2002 Free Software Foundation Copyright (C) 1998, 2002, 2003 Free Software Foundation
This file is part of GNU Classpath. This file is part of GNU Classpath.
...@@ -65,7 +65,7 @@ public class Runtime ...@@ -65,7 +65,7 @@ public class Runtime
/** /**
* The current security manager. This is located here instead of in * The current security manager. This is located here instead of in
* Runtime, to avoid security problems, as well as bootstrap issues. * System, to avoid security problems, as well as bootstrap issues.
* Make sure to access it in a thread-safe manner; it is package visible * Make sure to access it in a thread-safe manner; it is package visible
* to avoid overhead in java.lang. * to avoid overhead in java.lang.
*/ */
......
...@@ -101,7 +101,7 @@ java::lang::Class::forName (jstring className) ...@@ -101,7 +101,7 @@ java::lang::Class::forName (jstring className)
{ {
klass = t->classAt (i); klass = t->classAt (i);
} }
loader = klass->getClassLoader(); loader = klass->getClassLoaderInternal();
} }
catch (::java::lang::ArrayIndexOutOfBoundsException *e) catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{ {
...@@ -113,13 +113,31 @@ java::lang::Class::forName (jstring className) ...@@ -113,13 +113,31 @@ java::lang::Class::forName (jstring className)
java::lang::ClassLoader * java::lang::ClassLoader *
java::lang::Class::getClassLoader (void) java::lang::Class::getClassLoader (void)
{ {
#if 0
// FIXME: the checks we need to do are more complex. See the spec.
// Currently we can't implement them.
java::lang::SecurityManager *s = java::lang::System::getSecurityManager(); java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
if (s != NULL) if (s != NULL)
s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader"))); {
#endif gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
ClassLoader *caller_loader = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
caller_loader = caller->getClassLoaderInternal();
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
// If the caller has a non-null class loader, and that loader
// is not this class' loader or an ancestor thereof, then do a
// security check.
if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader))
s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
}
// The spec requires us to return `null' for primitive classes. In // The spec requires us to return `null' for primitive classes. In
// other cases we have the option of returning `null' for classes // other cases we have the option of returning `null' for classes
...@@ -136,13 +154,14 @@ java::lang::Class::getClassLoader (void) ...@@ -136,13 +154,14 @@ java::lang::Class::getClassLoader (void)
java::lang::reflect::Constructor * java::lang::reflect::Constructor *
java::lang::Class::getConstructor (JArray<jclass> *param_types) java::lang::Class::getConstructor (JArray<jclass> *param_types)
{ {
memberAccessCheck(java::lang::reflect::Member::PUBLIC);
jstring partial_sig = getSignature (param_types, true); jstring partial_sig = getSignature (param_types, true);
jint hash = partial_sig->hashCode (); jint hash = partial_sig->hashCode ();
int i = isPrimitive () ? 0 : method_count; int i = isPrimitive () ? 0 : method_count;
while (--i >= 0) while (--i >= 0)
{ {
// FIXME: access checks.
if (_Jv_equalUtf8Consts (methods[i].name, init_name) if (_Jv_equalUtf8Consts (methods[i].name, init_name)
&& _Jv_equal (methods[i].signature, partial_sig, hash)) && _Jv_equal (methods[i].signature, partial_sig, hash))
{ {
...@@ -163,7 +182,7 @@ java::lang::Class::getConstructor (JArray<jclass> *param_types) ...@@ -163,7 +182,7 @@ java::lang::Class::getConstructor (JArray<jclass> *param_types)
JArray<java::lang::reflect::Constructor *> * JArray<java::lang::reflect::Constructor *> *
java::lang::Class::_getConstructors (jboolean declared) java::lang::Class::_getConstructors (jboolean declared)
{ {
// FIXME: this method needs access checks. memberAccessCheck(java::lang::reflect::Member::PUBLIC);
int numConstructors = 0; int numConstructors = 0;
int max = isPrimitive () ? 0 : method_count; int max = isPrimitive () ? 0 : method_count;
...@@ -206,13 +225,14 @@ java::lang::Class::_getConstructors (jboolean declared) ...@@ -206,13 +225,14 @@ java::lang::Class::_getConstructors (jboolean declared)
java::lang::reflect::Constructor * java::lang::reflect::Constructor *
java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types) java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
{ {
memberAccessCheck(java::lang::reflect::Member::DECLARED);
jstring partial_sig = getSignature (param_types, true); jstring partial_sig = getSignature (param_types, true);
jint hash = partial_sig->hashCode (); jint hash = partial_sig->hashCode ();
int i = isPrimitive () ? 0 : method_count; int i = isPrimitive () ? 0 : method_count;
while (--i >= 0) while (--i >= 0)
{ {
// FIXME: access checks.
if (_Jv_equalUtf8Consts (methods[i].name, init_name) if (_Jv_equalUtf8Consts (methods[i].name, init_name)
&& _Jv_equal (methods[i].signature, partial_sig, hash)) && _Jv_equal (methods[i].signature, partial_sig, hash))
{ {
...@@ -256,9 +276,7 @@ java::lang::Class::getField (jstring name, jint hash) ...@@ -256,9 +276,7 @@ java::lang::Class::getField (jstring name, jint hash)
java::lang::reflect::Field * java::lang::reflect::Field *
java::lang::Class::getDeclaredField (jstring name) java::lang::Class::getDeclaredField (jstring name)
{ {
java::lang::SecurityManager *s = java::lang::System::getSecurityManager(); memberAccessCheck(java::lang::reflect::Member::DECLARED);
if (s != NULL)
s->checkMemberAccess (this, java::lang::reflect::Member::DECLARED);
int hash = name->hashCode(); int hash = name->hashCode();
for (int i = 0; i < field_count; i++) for (int i = 0; i < field_count; i++)
{ {
...@@ -277,9 +295,7 @@ java::lang::Class::getDeclaredField (jstring name) ...@@ -277,9 +295,7 @@ java::lang::Class::getDeclaredField (jstring name)
JArray<java::lang::reflect::Field *> * JArray<java::lang::reflect::Field *> *
java::lang::Class::getDeclaredFields (void) java::lang::Class::getDeclaredFields (void)
{ {
java::lang::SecurityManager *s = java::lang::System::getSecurityManager(); memberAccessCheck(java::lang::reflect::Member::DECLARED);
if (s != NULL)
s->checkMemberAccess (this, java::lang::reflect::Member::DECLARED);
JArray<java::lang::reflect::Field *> *result JArray<java::lang::reflect::Field *> *result
= (JArray<java::lang::reflect::Field *> *) = (JArray<java::lang::reflect::Field *> *)
JvNewObjectArray (field_count, &java::lang::reflect::Field::class$, NULL); JvNewObjectArray (field_count, &java::lang::reflect::Field::class$, NULL);
...@@ -361,6 +377,8 @@ java::lang::Class::_getDeclaredMethod (jstring name, ...@@ -361,6 +377,8 @@ java::lang::Class::_getDeclaredMethod (jstring name,
JArray<java::lang::reflect::Method *> * JArray<java::lang::reflect::Method *> *
java::lang::Class::getDeclaredMethods (void) java::lang::Class::getDeclaredMethods (void)
{ {
memberAccessCheck(java::lang::reflect::Member::DECLARED);
int numMethods = 0; int numMethods = 0;
int max = isPrimitive () ? 0 : method_count; int max = isPrimitive () ? 0 : method_count;
int i; int i;
...@@ -424,7 +442,7 @@ java::lang::Class::getClasses (void) ...@@ -424,7 +442,7 @@ java::lang::Class::getClasses (void)
JArray<jclass> * JArray<jclass> *
java::lang::Class::getDeclaredClasses (void) java::lang::Class::getDeclaredClasses (void)
{ {
checkMemberAccess (java::lang::reflect::Member::DECLARED); memberAccessCheck (java::lang::reflect::Member::DECLARED);
// Until we have inner classes, it always makes sense to return an // Until we have inner classes, it always makes sense to return an
// empty array. // empty array.
JArray<jclass> *result JArray<jclass> *result
...@@ -482,9 +500,7 @@ java::lang::Class::_getFields (JArray<java::lang::reflect::Field *> *result, ...@@ -482,9 +500,7 @@ java::lang::Class::_getFields (JArray<java::lang::reflect::Field *> *result,
JArray<java::lang::reflect::Field *> * JArray<java::lang::reflect::Field *> *
java::lang::Class::getFields (void) java::lang::Class::getFields (void)
{ {
// FIXME: security checking. memberAccessCheck(java::lang::reflect::Member::PUBLIC);
using namespace java::lang::reflect;
int count = _getFields (NULL, 0); int count = _getFields (NULL, 0);
...@@ -518,7 +534,6 @@ java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types) ...@@ -518,7 +534,6 @@ java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
int i = klass->isPrimitive () ? 0 : klass->method_count; int i = klass->isPrimitive () ? 0 : klass->method_count;
while (--i >= 0) while (--i >= 0)
{ {
// FIXME: access checks.
if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name) if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
&& _Jv_equaln (klass->methods[i].signature, partial_sig, p_len) && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
&& (klass->methods[i].accflags && (klass->methods[i].accflags
...@@ -642,7 +657,7 @@ java::lang::Class::getMethods (void) ...@@ -642,7 +657,7 @@ java::lang::Class::getMethods (void)
{ {
using namespace java::lang::reflect; using namespace java::lang::reflect;
// FIXME: security checks. memberAccessCheck(Member::PUBLIC);
// This will overestimate the size we need. // This will overestimate the size we need.
jint count = _getMethods (NULL, 0); jint count = _getMethods (NULL, 0);
...@@ -696,12 +711,7 @@ java::lang::Class::isInstance (jobject obj) ...@@ -696,12 +711,7 @@ java::lang::Class::isInstance (jobject obj)
jobject jobject
java::lang::Class::newInstance (void) java::lang::Class::newInstance (void)
{ {
// FIXME: do accessibility checks here. There currently doesn't memberAccessCheck(java::lang::reflect::Member::PUBLIC);
// seem to be any way to do these.
// FIXME: we special-case one check here just to pass a Plum Hall
// test. Once access checking is implemented, remove this.
if (this == &java::lang::Class::class$)
throw new java::lang::IllegalAccessException;
if (isPrimitive () if (isPrimitive ()
|| isInterface () || isInterface ()
...@@ -1744,7 +1754,26 @@ _Jv_MakeVTable (jclass klass) ...@@ -1744,7 +1754,26 @@ _Jv_MakeVTable (jclass klass)
{ {
for (int i = 0; i < klass->vtable_method_count; ++i) for (int i = 0; i < klass->vtable_method_count; ++i)
if (! flags[i]) if (! flags[i])
// FIXME: messsage. {
throw new java::lang::AbstractMethodError (); using namespace java::lang;
while (klass != NULL)
{
for (int j = 0; j < klass->method_count; ++j)
{
if (klass->methods[i].index == i)
{
StringBuffer *buf = new StringBuffer ();
buf->append (_Jv_NewStringUtf8Const (klass->methods[i].name));
buf->append ((jchar) ' ');
buf->append (_Jv_NewStringUtf8Const (klass->methods[i].signature));
throw new AbstractMethodError (buf->toString ());
}
}
klass = klass->getSuperclass ();
}
// Couldn't find the name, which is weird.
// But we still must throw the error.
throw new AbstractMethodError ();
}
} }
} }
/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation /* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -12,15 +12,6 @@ package java.lang.reflect; ...@@ -12,15 +12,6 @@ package java.lang.reflect;
* @author Per Bothner <bothner@cygnus.com> * @author Per Bothner <bothner@cygnus.com>
* @date September 1998; February 1999. * @date September 1998; February 1999.
*/ */
/* Status: Mostly implemented.
* However, access checks are not implemented. See natField.cc for
* _Jv_CheckFieldAccessibility as well as the missing getCaller.
* Note that the idea is to have to compiler convert calls to
* setXXX(...) and getXXX(...) to setXXX(CALLER, ...) and getXXX(CALLER, ...),
* where CALLER is reference to the class that contains the calls to
* setXXX or getXXX. This is easy for the compiler, and replaces
* expensive stack and table searching with a constant.
*/
public final class Field extends AccessibleObject implements Member public final class Field extends AccessibleObject implements Member
{ {
...@@ -39,12 +30,12 @@ public final class Field extends AccessibleObject implements Member ...@@ -39,12 +30,12 @@ public final class Field extends AccessibleObject implements Member
} }
public boolean equals (Object fld) public boolean equals (Object fld)
{ {
if (! (fld instanceof Field)) if (! (fld instanceof Field))
return false; return false;
Field f = (Field) fld; Field f = (Field) fld;
return declaringClass == f.declaringClass && offset == f.offset; return declaringClass == f.declaringClass && offset == f.offset;
} }
public Class getDeclaringClass () public Class getDeclaringClass ()
{ {
...@@ -62,11 +53,6 @@ public final class Field extends AccessibleObject implements Member ...@@ -62,11 +53,6 @@ public final class Field extends AccessibleObject implements Member
return (declaringClass.hashCode() ^ offset); return (declaringClass.hashCode() ^ offset);
} }
// The idea is that the compiler will magically translate
// fld.getShort(obj) to fld.getShort(THISCLASS, obj).
// This makes checking assessiblity more efficient,
// since we don't have to do any stack-walking.
public boolean getBoolean (Object obj) public boolean getBoolean (Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
......
// natField.cc - Implementation of java.lang.reflect.Field native methods. // natField.cc - Implementation of java.lang.reflect.Field native methods.
/* Copyright (C) 1999, 2000, 2001 Free Software Foundation /* Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -15,6 +15,7 @@ details. */ ...@@ -15,6 +15,7 @@ details. */
#include <jvm.h> #include <jvm.h>
#include <gcj/cni.h> #include <gcj/cni.h>
#include <java/lang/reflect/Array.h> #include <java/lang/reflect/Array.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/IllegalArgumentException.h> #include <java/lang/IllegalArgumentException.h>
#include <java/lang/Byte.h> #include <java/lang/Byte.h>
#include <java/lang/Short.h> #include <java/lang/Short.h>
...@@ -38,8 +39,8 @@ java::lang::reflect::Array::newInstance (jclass componentType, jint length) ...@@ -38,8 +39,8 @@ java::lang::reflect::Array::newInstance (jclass componentType, jint length)
return _Jv_NewPrimArray (componentType, length); return _Jv_NewPrimArray (componentType, length);
} }
else else
// FIXME: class loader?
return JvNewObjectArray (length, componentType, NULL); return JvNewObjectArray (length, componentType, NULL);
} }
jobject jobject
...@@ -52,10 +53,26 @@ java::lang::reflect::Array::newInstance (jclass componentType, ...@@ -52,10 +53,26 @@ java::lang::reflect::Array::newInstance (jclass componentType,
jint* dims = elements (dimensions); jint* dims = elements (dimensions);
if (ndims == 1) if (ndims == 1)
return newInstance (componentType, dims[0]); return newInstance (componentType, dims[0]);
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
ClassLoader *caller_loader = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
caller_loader = caller->getClassLoaderInternal();
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
jclass arrayType = componentType; jclass arrayType = componentType;
for (int i = 0; i < ndims; i++) // FIXME 2nd arg should for (int i = 0; i < ndims; i++)
// be "current" loader arrayType = _Jv_GetArrayClass (arrayType, caller_loader);
arrayType = _Jv_GetArrayClass (arrayType, 0);
return _Jv_NewMultiArray (arrayType, ndims, dims); return _Jv_NewMultiArray (arrayType, ndims, dims);
} }
...@@ -343,8 +360,10 @@ java::lang::reflect::Array::setBoolean (jobject array, ...@@ -343,8 +360,10 @@ java::lang::reflect::Array::setBoolean (jobject array,
void void
java::lang::reflect::Array::set (jobject array, jint index, java::lang::reflect::Array::set (jobject array, jint index,
jobject value, jclass elType) jobject value, jclass elType)
{ {
// We don't have to call getElementType here, or check INDEX,
// because it was already done in the Java wrapper.
if (! _Jv_IsInstanceOf (value, elType)) if (! _Jv_IsInstanceOf (value, elType))
throw new java::lang::IllegalArgumentException; throw new java::lang::IllegalArgumentException;
elements ((jobjectArray) array) [index] = value; elements ((jobjectArray) array) [index] = value;
......
// natConstructor.cc - Native code for Constructor class. // natConstructor.cc - Native code for Constructor class.
/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation /* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -13,6 +13,8 @@ details. */ ...@@ -13,6 +13,8 @@ details. */
#include <gcj/cni.h> #include <gcj/cni.h>
#include <jvm.h> #include <jvm.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/IllegalAccessException.h>
#include <java/lang/reflect/Constructor.h> #include <java/lang/reflect/Constructor.h>
#include <java/lang/reflect/Method.h> #include <java/lang/reflect/Method.h>
#include <java/lang/reflect/InvocationTargetException.h> #include <java/lang/reflect/InvocationTargetException.h>
...@@ -46,6 +48,24 @@ java::lang::reflect::Constructor::newInstance (jobjectArray args) ...@@ -46,6 +48,24 @@ java::lang::reflect::Constructor::newInstance (jobjectArray args)
if (parameter_types == NULL) if (parameter_types == NULL)
getType (); getType ();
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
if (! isAccessible() && ! _Jv_CheckAccess(caller, declaringClass,
declaringClass->getModifiers()))
throw new java::lang::IllegalAccessException;
using namespace java::lang::reflect; using namespace java::lang::reflect;
if (Modifier::isAbstract (declaringClass->getModifiers())) if (Modifier::isAbstract (declaringClass->getModifiers()))
throw new InstantiationException; throw new InstantiationException;
......
// natField.cc - Implementation of java.lang.reflect.Field native methods. // natField.cc - Implementation of java.lang.reflect.Field native methods.
/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation /* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -15,6 +15,7 @@ details. */ ...@@ -15,6 +15,7 @@ details. */
#include <jvm.h> #include <jvm.h>
#include <java/lang/reflect/Field.h> #include <java/lang/reflect/Field.h>
#include <java/lang/reflect/Modifier.h> #include <java/lang/reflect/Modifier.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/IllegalArgumentException.h> #include <java/lang/IllegalArgumentException.h>
#include <java/lang/IllegalAccessException.h> #include <java/lang/IllegalAccessException.h>
#include <java/lang/NullPointerException.h> #include <java/lang/NullPointerException.h>
...@@ -46,31 +47,36 @@ java::lang::reflect::Field::getType () ...@@ -46,31 +47,36 @@ java::lang::reflect::Field::getType ()
{ {
jfieldID fld = _Jv_FromReflectedField (this); jfieldID fld = _Jv_FromReflectedField (this);
JvSynchronize sync (declaringClass); JvSynchronize sync (declaringClass);
_Jv_ResolveField (fld, declaringClass->getClassLoader ()); _Jv_ResolveField (fld, declaringClass->getClassLoaderInternal ());
return fld->type; return fld->type;
} }
static void
_Jv_CheckFieldAccessibility (jfieldID /*fld*/, jclass /*caller*/)
{
#if 0
if (caller == NULL)
caller = getCaller();
#endif
#if 0
_Jv_ushort flags = fld->getModifiers();
check accesss;
#endif
}
static void* static void*
getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj) getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj)
{ {
// FIXME: we know CALLER is NULL here. At one point we planned to
// have the compiler insert the caller as a hidden argument in some
// calls. However, we never implemented that, so we have to find
// the caller by hand instead.
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
jfieldID fld = _Jv_FromReflectedField (field); jfieldID fld = _Jv_FromReflectedField (field);
_Jv_ushort flags = fld->getModifiers(); _Jv_ushort flags = fld->getModifiers();
if (! (flags & java::lang::reflect::Modifier::PUBLIC) if (! field->isAccessible ()
&& ! field->isAccessible ()) && ! _Jv_CheckAccess (caller, field->getDeclaringClass(), flags))
_Jv_CheckFieldAccessibility (fld, caller); throw new java::lang::IllegalAccessException;
if (flags & java::lang::reflect::Modifier::STATIC) if (flags & java::lang::reflect::Modifier::STATIC)
{ {
jclass fldClass = field->getDeclaringClass (); jclass fldClass = field->getDeclaringClass ();
......
// natMethod.cc - Native code for Method class. // natMethod.cc - Native code for Method class.
/* Copyright (C) 1998, 1999, 2000, 2001 , 2002 Free Software Foundation /* Copyright (C) 1998, 1999, 2000, 2001 , 2002, 2003 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -30,6 +30,7 @@ details. */ ...@@ -30,6 +30,7 @@ details. */
#include <java/lang/Double.h> #include <java/lang/Double.h>
#include <java/lang/IllegalArgumentException.h> #include <java/lang/IllegalArgumentException.h>
#include <java/lang/NullPointerException.h> #include <java/lang/NullPointerException.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/Class.h> #include <java/lang/Class.h>
#include <gcj/method.h> #include <gcj/method.h>
#include <gnu/gcj/RawData.h> #include <gnu/gcj/RawData.h>
...@@ -142,19 +143,33 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args) ...@@ -142,19 +143,33 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
if (parameter_types == NULL) if (parameter_types == NULL)
getType (); getType ();
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
jmethodID meth = _Jv_FromReflectedMethod (this); jmethodID meth = _Jv_FromReflectedMethod (this);
jclass klass;
if (! java::lang::reflect::Modifier::isStatic(meth->accflags)) if (! java::lang::reflect::Modifier::isStatic(meth->accflags))
{ {
jclass k = obj ? obj->getClass() : NULL;
if (! obj) if (! obj)
throw new java::lang::NullPointerException; throw new java::lang::NullPointerException;
if (! declaringClass->isAssignableFrom(k)) klass = obj->getClass();
if (! declaringClass->isAssignableFrom(klass))
throw new java::lang::IllegalArgumentException; throw new java::lang::IllegalArgumentException;
// FIXME: access checks.
// Find the possibly overloaded method based on the runtime type // Find the possibly overloaded method based on the runtime type
// of the object. // of the object.
meth = _Jv_LookupDeclaredMethod (k, meth->name, meth->signature); meth = _Jv_LookupDeclaredMethod (klass, meth->name, meth->signature);
} }
else else
{ {
...@@ -162,8 +177,12 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args) ...@@ -162,8 +177,12 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
// here and not in _Jv_CallAnyMethodA because JNI initializes a // here and not in _Jv_CallAnyMethodA because JNI initializes a
// class whenever a method lookup is done. // class whenever a method lookup is done.
_Jv_InitClass (declaringClass); _Jv_InitClass (declaringClass);
klass = declaringClass;
} }
if (! isAccessible() && ! _Jv_CheckAccess(caller, klass, meth->accflags))
throw new IllegalArgumentException;
return _Jv_CallAnyMethodA (obj, return_type, meth, false, return _Jv_CallAnyMethodA (obj, return_type, meth, false,
parameter_types, args); parameter_types, args);
} }
...@@ -207,7 +226,7 @@ java::lang::reflect::Method::getType () ...@@ -207,7 +226,7 @@ java::lang::reflect::Method::getType ()
jclass *elts = elements (exception_types); jclass *elts = elements (exception_types);
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
elts[i] = _Jv_FindClass (method->throws[i], elts[i] = _Jv_FindClass (method->throws[i],
declaringClass->getClassLoader ()); declaringClass->getClassLoaderInternal ());
} }
void void
...@@ -218,7 +237,7 @@ _Jv_GetTypesFromSignature (jmethodID method, ...@@ -218,7 +237,7 @@ _Jv_GetTypesFromSignature (jmethodID method,
{ {
_Jv_Utf8Const* sig = method->signature; _Jv_Utf8Const* sig = method->signature;
java::lang::ClassLoader *loader = declaringClass->getClassLoader(); java::lang::ClassLoader *loader = declaringClass->getClassLoaderInternal();
char *ptr = sig->data; char *ptr = sig->data;
int numArgs = 0; int numArgs = 0;
/* First just count the number of parameters. */ /* First just count the number of parameters. */
...@@ -344,19 +363,11 @@ _Jv_CallAnyMethodA (jobject obj, ...@@ -344,19 +363,11 @@ _Jv_CallAnyMethodA (jobject obj,
jclass *paramelts = elements (parameter_types); jclass *paramelts = elements (parameter_types);
// FIXME: at some point the compiler is going to add extra arguments
// to some functions. In particular we are going to do this for
// handling access checks in reflection. We must add these hidden
// arguments here.
// Special case for the `this' argument of a constructor. Note that // Special case for the `this' argument of a constructor. Note that
// the JDK 1.2 docs specify that the new object must be allocated // the JDK 1.2 docs specify that the new object must be allocated
// before argument conversions are done. // before argument conversions are done.
if (is_constructor) if (is_constructor)
{ obj = JvAllocObject (return_type);
// FIXME: must special-case String, arrays, maybe others here.
obj = JvAllocObject (return_type);
}
const int size_per_arg = sizeof(jvalue); const int size_per_arg = sizeof(jvalue);
ffi_cif cif; ffi_cif cif;
...@@ -488,8 +499,6 @@ _Jv_CallAnyMethodA (jobject obj, ...@@ -488,8 +499,6 @@ _Jv_CallAnyMethodA (jobject obj,
JArray<jclass> *parameter_types, JArray<jclass> *parameter_types,
jobjectArray args) jobjectArray args)
{ {
// FIXME: access checks.
if (parameter_types->length == 0 && args == NULL) if (parameter_types->length == 0 && args == NULL)
{ {
// The JDK accepts this, so we do too. // The JDK accepts this, so we do too.
......
...@@ -491,7 +491,7 @@ static jclass ...@@ -491,7 +491,7 @@ static jclass
java::lang::ClassLoader *loader = NULL; java::lang::ClassLoader *loader = NULL;
if (env->klass != NULL) if (env->klass != NULL)
loader = env->klass->getClassLoader (); loader = env->klass->getClassLoaderInternal ();
if (loader == NULL) if (loader == NULL)
{ {
...@@ -1189,7 +1189,7 @@ static jfieldID ...@@ -1189,7 +1189,7 @@ static jfieldID
// FIXME: what if field_class == NULL? // FIXME: what if field_class == NULL?
java::lang::ClassLoader *loader = clazz->getClassLoader (); java::lang::ClassLoader *loader = clazz->getClassLoaderInternal ();
while (clazz != NULL) while (clazz != NULL)
{ {
// We acquire the class lock so that fields aren't resolved // We acquire the class lock so that fields aren't resolved
......
// prims.cc - Code for core of runtime environment. // prims.cc - Code for core of runtime environment.
/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -1137,3 +1137,21 @@ _Jv_remJ (jlong dividend, jlong divisor) ...@@ -1137,3 +1137,21 @@ _Jv_remJ (jlong dividend, jlong divisor)
return dividend % divisor; return dividend % divisor;
} }
// Return true if SELF_KLASS can access a field or method in
// OTHER_KLASS. The field or method's access flags are specified in
// FLAGS.
jboolean
_Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags)
{
using namespace java::lang::reflect;
return ((self_klass == other_klass)
|| ((flags & Modifier::PUBLIC) != 0)
|| (((flags & Modifier::PROTECTED) != 0)
&& other_klass->isAssignableFrom (self_klass))
|| (((flags & Modifier::PRIVATE) == 0)
&& _Jv_ClassNameSamePackage (self_klass->name,
other_klass->name)));
}
...@@ -166,15 +166,7 @@ _Jv_ResolvePoolEntry (jclass klass, int index) ...@@ -166,15 +166,7 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
if (! _Jv_equalUtf8Consts (field->name, field_name)) if (! _Jv_equalUtf8Consts (field->name, field_name))
continue; continue;
// now, check field access. if (_Jv_CheckAccess (klass, cls, field->flags))
if ( (cls == klass)
|| ((field->flags & Modifier::PUBLIC) != 0)
|| (((field->flags & Modifier::PROTECTED) != 0)
&& cls->isAssignableFrom (klass))
|| (((field->flags & Modifier::PRIVATE) == 0)
&& _Jv_ClassNameSamePackage (cls->name,
klass->name)))
{ {
/* resove the field using the class' own loader /* resove the field using the class' own loader
if necessary */ if necessary */
...@@ -347,20 +339,10 @@ _Jv_SearchMethodInClass (jclass cls, jclass klass, ...@@ -347,20 +339,10 @@ _Jv_SearchMethodInClass (jclass cls, jclass klass,
method_signature))) method_signature)))
continue; continue;
if (cls == klass if (_Jv_CheckAccess (klass, cls, method->accflags))
|| ((method->accflags & Modifier::PUBLIC) != 0) return method;
|| (((method->accflags & Modifier::PROTECTED) != 0)
&& cls->isAssignableFrom (klass))
|| (((method->accflags & Modifier::PRIVATE) == 0)
&& _Jv_ClassNameSamePackage (cls->name,
klass->name)))
{
return method;
}
else else
{ throw new java::lang::IllegalAccessError;
throw new java::lang::IllegalAccessError;
}
} }
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment