I found a few OpenSSL callbacks that create temporary Java arrays and pass them
to Java, but never delete the local references before returning to OpenSSL.
Because these run as callbacks inside native SSL operations, the references stay
alive until the surrounding JNI frame is popped, so repeated callbacks can
accumulate entries in the local-reference table.
File: openssl-dynamic/src/main/c/sslcontext.c
The clearest instance is tcn_get_session_cb:
if ((bArray = (*e)->NewByteArray(e, len)) == NULL) {
return NULL;
}
(*e)->SetByteArrayRegion(e, bArray, 0, len, (jbyte*) session_id);
result = (*e)->CallLongMethod(e, c->ssl_session_cache, c->ssl_session_cache_get_method, P2J(ssl), bArray);
if ((*e)->ExceptionCheck(e)) {
return NULL;
}
if (result == -1) {
return NULL;
}
*copy = 0;
return (SSL_SESSION*) result;
After NewByteArray() succeeds, all three return paths (exception, result == -1,
success) leave bArray undeleted.
cert_requested and certificate_cb have the same pattern: both create types
and issuers via keyTypes() / principalBytes(), pass them into
CallVoidMethod() (or into the CertificateCallbackTask constructor), and never
delete them. certificate_cb even reaches its complete: label and deletes
certificateCallbackTask_class, but not types / issuers.
The same file establishes the cleanup convention elsewhere — e.g. principalBytes
deletes its per-entry bArray inside the loop:
(*e)->SetObjectArrayElement(e, array, i, bArray);
// Delete the local reference as we not know how long the chain is ...
NETTY_JNI_UTIL_DELETE_LOCAL(e, bArray);
which makes the missing deletions in the callbacks above look accidental.
Deleting these local references after the Java call does not invalidate anything
Java keeps, since Java fields and constructor arguments establish their own
managed references.
Suggested fix: delete bArray in tcn_get_session_cb after the session-cache
call, and delete types / issuers on the common exit paths of cert_requested
and certificate_cb, on both successful and exceptional returns:
NETTY_JNI_UTIL_DELETE_LOCAL(e, bArray);
I found a few OpenSSL callbacks that create temporary Java arrays and pass them
to Java, but never delete the local references before returning to OpenSSL.
Because these run as callbacks inside native SSL operations, the references stay
alive until the surrounding JNI frame is popped, so repeated callbacks can
accumulate entries in the local-reference table.
File:
openssl-dynamic/src/main/c/sslcontext.cThe clearest instance is
tcn_get_session_cb:After
NewByteArray()succeeds, all three return paths (exception,result == -1,success) leave
bArrayundeleted.cert_requestedandcertificate_cbhave the same pattern: both createtypesand
issuersviakeyTypes()/principalBytes(), pass them intoCallVoidMethod()(or into theCertificateCallbackTaskconstructor), and neverdelete them.
certificate_cbeven reaches itscomplete:label and deletescertificateCallbackTask_class, but nottypes/issuers.The same file establishes the cleanup convention elsewhere — e.g.
principalBytesdeletes its per-entry
bArrayinside the loop:which makes the missing deletions in the callbacks above look accidental.
Deleting these local references after the Java call does not invalidate anything
Java keeps, since Java fields and constructor arguments establish their own
managed references.
Suggested fix: delete
bArrayintcn_get_session_cbafter the session-cachecall, and delete
types/issuerson the common exit paths ofcert_requestedand
certificate_cb, on both successful and exceptional returns: