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

Erik Groeneveld erik@cq2.nl
Wed Dec 23 13:34:00 GMT 2009


Hello Andrew,

Thanks for your quick reply. We include code below.

On Wed, Dec 23, 2009 at 11:46, Andrew Haley <aph@redhat.com> wrote:
> On 12/23/2009 10:38 AM, Erik Groeneveld wrote:
>
[...]
>>       else
>>       // Method is public, check to see if class is accessible.
>>       {
>>         jint flags = (declaringClass->accflags
>>                       & (Modifier::PUBLIC
>>                          | Modifier::PROTECTED
>>                          | Modifier::PRIVATE));
>>         if (flags == 0) // i.e. class is package private
>>           {
>>             Class *caller = _Jv_StackTrace::GetCallingClass (&Method::class$);
>>             if (! _Jv_ClassNameSamePackage (caller->name,
>>                                             declaringClass->name))
>>               throw new IllegalAccessException;
>>           }
>>       }
>>     }
>>
[...]

>> 1. The systems segfaults on the caller->name because there is no calling class.
>
> How can there be no calling class?

Because we call it from C++ not from Java.  We forgot to mention that.

>> 2. We believe class accessibility is not relevant here: there is no
>> reason why a Method object with public access should not be invokable,
>> or is there?
[...]
>
> Yes, but can you send a test case before we go any further?  Then at least
> we'll all know what you're talking about.

The following code demonstrates the problem.

#include <gcj/cni.h>
#include <java/util/ArrayList.h>
#include <java/util/Iterator.h>
#include <java/lang/reflect/Method.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
    JvCreateJavaVM(NULL);
    JvAttachCurrentThread(NULL, NULL);
    java::util::ArrayList* l = new java::util::ArrayList();
    java::util::Iterator* i = l->iterator();
    java::lang::reflect::Method* m = i->getClass()->getDeclaredMethod(
            JvNewStringUTF("hasNext"), NULL);
    printf("calling invoke, it'll dump core in natMethod.cc line 194\n");
    m->invoke(i, NULL);
    return 0;
}

$gcc problem.cpp -lgcj
$./a.out
calling invoke
Aborted (core dumped)

$gdb -core core a.out
(gdb) where
#0  0x00002adf9252bed5 in raise () from /lib/libc.so.6
#1  0x00002adf9252d3f3 in abort () from /lib/libc.so.6
#2  0x00002adf90bdeed8 in _Jv_Throw (value=0x2adf932cd370) at
../../../src/libjava/exception.cc:128
#3  0x00002adf90bd2a2a in _Jv_catch_segv (_p=<value optimized out>) at
../../../src/libjava/prims.cc:184
#4  <signal handler called>
#5  0x00002adf90c217d3 in java::lang::reflect::Method::invoke
(this=0x2adf932d1c80, obj=0x2adf93ba6e40,
    args=0x0) at ../../../src/libjava/java/lang/reflect/natMethod.cc:194
#6  0x0000000000400a5c in main ()

The top of the stack is from the NULL-pointer catching signal handler
we believe, so #5 and #6 are the relevant ones.

The point is that we believe that the scenario in the C++ code is
valid, both from Java and from C++, and we do not see the reasons for
the additional check that has been added to the invoke() method.

Erik
Jurjan-Paul



More information about the Java mailing list