Skip to content

Bug: JNI Connection.execute crashes the JVM on non-Value parameters #751

Description

@alvorithm

Filed against the bindings repo, where the code lives: LadybugDB/ladybug-java#11. Cross-posting here for visibility, since tools/java_api ships with this repo.

Ladybug version

com.ladybugdb:lbug 0.19.0 (Maven Central). JNI source is tools/java_api @ a0e7728, the tip of ladybug-java main and the commit this repo pins at both v0.18.1 and v0.19.0.

What operating system are you using?

Debian 13, Linux x86-64, OpenJDK 25.0.3.

What happened?

Passing a parameter that is not a com.ladybugdb.Value to Connection.execute kills the JVM with SIGSEGV in lbug_value_clone, with no exception and no stack unwinding. bindJavaParamsToPreparedStatement hands each map value straight to getValue (src/jni/lbug_java.cpp:516), which reinterpret_casts a field that only exists on Value (src/jni/lbug_java.cpp:381), with no IsInstanceOf check.

Connection.execute is declared Map<String, Value>, so this is only reachable through erasure: a raw or unchecked Map, reflection, or a JVM language that does not enforce Java generics (my case: Clojure). Expected: an IllegalArgumentException, or conversion of boxed values through the ladder Java_com_ladybugdb_Native_lbugValueCreateValue already implements. Fix options and suggested tests are in LadybugDB/ladybug-java#11.

Are there known steps to reproduce?

Map<String, Object> raw = new HashMap<>();
raw.put("p_id", UUID.fromString("11111111-1111-1111-1111-111111111111"));
raw.put("p_name", "hello");

@SuppressWarnings("unchecked")
Map<String, Value> params = (Map<String, Value>) (Map<?, ?>) raw;

try (PreparedStatement ps = conn.prepare("MATCH (n:T {id: $p_id}) SET n.name = $p_name;")) {
    conn.execute(ps, params);   // process dies here
}
#  SIGSEGV (0xb) at pc=0x00007fc0f4ba89b3
# C  [liblbug_java_native....so+0x29a9b3]  lbug_value_clone+0x23
siginfo: si_signo: 11 (SIGSEGV), si_code: 128 (SI_KERNEL), si_addr: 0x0000000000000000

A single unwrapped entry suffices: one bare String parameter crashes identically. Map.of("p_id", new Value(uuid)) works.

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