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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions