Skip to content

Possible local reference accumulation in native poll() #178

Description

@K-ANOY

There is a possible JNI local-reference leak in the native implementation of NativeUnixSocket.poll().

File: junixsocket-native/src/main/c/polling.c

Function: Java_org_newsclub_net_unix_NativeUnixSocket_poll

Relevant code:

(*env)->GetIntArrayRegion(env, opsObj, 0, nfds, buf);
for(int i=0; i<nfds;i++) {
    jobject fdObj = (*env)->GetObjectArrayElement(env, fdsObj, i);

    struct pollfd *pfd = &pollFd[i];
    if(fdObj) {
        int fd = _getFD(env, fdObj);
        pfd->fd = fd;
        pfd->events = opToEvent(buf[i]);
    } else {
        pfd->fd = 0;
        pfd->events = 0;
    }
}

GetObjectArrayElement() returns a new local reference:

jobject fdObj = (*env)->GetObjectArrayElement(env, fdsObj, i);

The reference is only needed during the current loop iteration to read the native file descriptor:

int fd = _getFD(env, fdObj);

But the loop never calls DeleteLocalRef(fdObj). Those local references are eventually released when the native method returns, so this is not a cross-call leak. However, poll() can receive an array containing many FileDescriptor objects from the Java selector implementation. In that case, one local reference is accumulated for each descriptor during a single native call, which can exhaust the JNI local reference table for large selector sets.

This method is reached from the Java selector path:

num = NativeUnixSocket.poll(pfd, timeout);

and the PollFd object contains the FileDescriptor[] passed to native code:

final FileDescriptor[] fds;

Suggested fix: delete the local reference after _getFD() has consumed it:

jobject fdObj = (*env)->GetObjectArrayElement(env, fdsObj, i);
if(fdObj) {
    int fd = _getFD(env, fdObj);
    (*env)->DeleteLocalRef(env, fdObj);

    pfd->fd = fd;
    pfd->events = opToEvent(buf[i]);
} else {
    pfd->fd = 0;
    pfd->events = 0;
}

It would also be reasonable to handle a pending exception from GetObjectArrayElement() before continuing the loop.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions