Re: problem with class accessiblity check in invoke (natMethod.cc)

Andrew Haley <[email protected]>
Newsgroups gmane.comp.gcc.java.devel
Message-ID <[email protected]>
On 12/23/2009 06:09 PM, Erik Groeneveld wrote:
> On Wed, Dec 23, 2009 at 17:44, Bryce McKinlay <[email protected]> wrote:
>> On Wed, Dec 23, 2009 at 3:58 PM, Erik J Groeneveld <[email protected]> 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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.