Skip to content

JniCallback checks the input object instead of the NewGlobalRef result #14974

Description

@K-ANOY

File: java/rocksjni/jnicallback.cc

Function: JniCallback::JniCallback

The base callback wrapper creates a global reference for the Java callback object, but the null check tests the input local reference instead of the NewGlobalRef result:

assert(jcallback_obj != nullptr);
m_jcallback_obj = env->NewGlobalRef(jcallback_obj);
if (jcallback_obj == nullptr) {
  // exception thrown: OutOfMemoryError
  return;
}

NewGlobalRef can return null, typically with an OutOfMemoryError pending.
In normal calls jcallback_obj is non-null, so this guard never catches a
failed global-reference allocation. The object is left with
m_jcallback_obj == nullptr while derived callback constructors continue to run
and native factory functions can still return a native handle.

This base class is shared by multiple RocksJava callback bridges, including
comparators, loggers, event listeners, table filters, WAL filters, trace
writers, transaction notifiers, and write-batch handlers.

Suggested fix

At minimum, check the returned global reference:

 assert(jcallback_obj != nullptr);
 m_jcallback_obj = env->NewGlobalRef(jcallback_obj);
-if (jcallback_obj == nullptr) {
+if (m_jcallback_obj == nullptr) {
   // exception thrown: OutOfMemoryError
   return;
 }

Because a C++ base constructor cannot stop the derived constructor body from
running, the callback constructors or factory functions should also propagate
construction failure before using or returning the callback object.

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