This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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.



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]