This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: problem with class accessiblity check in invoke (natMethod.cc)
On 12/23/2009 06:09 PM, Erik Groeneveld wrote:
> On Wed, Dec 23, 2009 at 17:44, Bryce McKinlay <bmckinlay@gmail.com> wrote:
>> On Wed, Dec 23, 2009 at 3:58 PM, Erik J Groeneveld <erik@cq2.nl> wrote:
> [...]
>
>> In your example, you aren't testing the accessibility of Iterator, but
>> rather that of the class which is returned by ArrayList.iterator(),
>> which is indeed a package-private class from a different package!
>
> That is true. But the code that uses invoke is generic. It calls a
> given method on a given object:
>
> java::lang::Object* callMethod(java::lang::Object* target,
> java::lang::String* methodname)
>
> It cannot do anything else than trying to find the method using the
> java::lang::Object pointer that has been passed to it. And it cannot
> tell from this pointer that the actual reference the application is
> using is of type Iterator (or any other interface for that matter).
> This is something the compiler can work out, but not the runtime.
> Indeed this works:
>
> java::util::ArrayList* l = new java::util::ArrayList();
> java::util::Iterator* i = l->iterator();
> i = l->iterator();
> i->hasNext();
Right, because CNI is bypassing the controls.
> But the fix below only works for the example I made up because a human
> can tell the reference is of type Iterator:
>
>> Another fix for your code would be to change:
>>
>> java::lang::reflect::Method* m = i->getClass()->getDeclaredMethod(
>> JvNewStringUTF("hasNext"), NULL);
>>
>> to something like:
>>
>> java::lang::reflect::Method* m =
>> &(java::util::Iterator::class$)->getDeclaredMethod(
>> JvNewStringUTF("hasNext"), NULL);
>
> So I wonder how the rules from 6.6 in the Java Language Specification
> can be implemented properly when the type of the reference is not
> known to invoke. Because the relevant part of the spec speaks about
> "members of a reference".
>
> "A member (class, interface, field, or method) of a reference (class,
> interface, or array) type or a constructor of a class type is
> accessible only if the type is accessible and the member or
> constructor is declared to permit access: ..."
>
> but invoke simply does not know the reference, and cannot get it from
> the Java call stack either (hence the core dump). All it knows is the
> actual object, and this object is of a type that is not accessible,
> although it implements an interface that is accessible.
>
> Is there a more gentle solution other than calling setAccessible() on
> the method object? (which works) Could it be done in GCJ?
I can't see any good reason why there should be. Unless the method
is marked accessible, java.lang.reflect.Method.invoke has to check the
class of the caller. There should not be a segfault, true, but an
IllegalAccessException wouldn't be unreasonable. That's what this
code does:
import java.lang.reflect.*;
import java.util.*;
public class Problem
{
public static void main(String[] args)
throws Throwable
{
ArrayList l = new ArrayList();
Iterator i = l.iterator();
Method m = (i.getClass().getDeclaredMethod
("hasNext", null));
m.invoke(i, null);
}
}
Andrew.