java: allow non-const maps to be passed as null
What changed, and why it matters
This is a small Java language-binding change that lets callers pass Java null for one specific type of object (a non-const wally_map) instead of requiring a real object. It is used to skip an internal caching map when computing a Bitcoin/Elements transaction signature hash. The change is a convenience/API improvement, not a fix for a memory corruption or cryptographic bug.
No security action required. Treat as a normal API/usability improvement. If auditing, confirm the underlying C function tx_get_input_signature_hash safely handles a NULL cache argument, which the new test implies it does.
Security signals we found
API behavior change: null now accepted for a previously required non-const map argument
No bounds-check, memory allocation, or cryptographic algorithm changes
Test-only addition confirms functional equivalence of cached vs null-cache paths
No mention of vulnerability, CVE, security bug, or researcher attribution in commit
Evidence from the diff
The SWIG Java typemap for non-const struct pointers was changed so that when the type is wally_map, it calls get_obj() instead of get_obj_or_throw(). get_obj() presumably returns NULL for a null Java reference, whereas get_obj_or_throw() would throw an exception. This allows Java code to pass null for the cache parameter of tx_get_input_signature_hash, disabling the cache. The test file was updated to exercise both cached and null-cache paths and verify the same signature hash is produced.
Changed components
src/swig_java/swig.isrc/swig_java/src/com/blockstream/test/test_elements_tx.javaJava SWIG bindings for wally_mapInspect captured patch +20 / −4
diff --git a/src/swig_java/src/com/blockstream/test/test_elements_tx.java b/src/swig_java/src/com/blockstream/test/test_elements_tx.java
index ad5b694..6f43c2f 100644
--- a/src/swig_java/src/com/blockstream/test/test_elements_tx.java
+++ b/src/swig_java/src/com/blockstream/test/test_elements_tx.java
@@ -47,11 +47,23 @@ public class test_elements_tx {
final String expected = "2c478ce6d5637e0ea8be37a53090e0955b6c501773fccf6738520cfcc5442150";
+ // Compute the signature hash
Wally.tx_get_input_signature_hash(tx, input_idx, scripts, assets, values,
tapleaf_script, key_version, codesep_pos, annex, genesis, sighash, sighash_type,
cache, bytes_out
);
-
+ assert_eq(expected, h(bytes_out), "different sighash");
+ // Compute again to ensure the cache works as expected
+ Wally.tx_get_input_signature_hash(tx, input_idx, scripts, assets, values,
+ tapleaf_script, key_version, codesep_pos, annex, genesis, sighash, sighash_type,
+ cache, bytes_out
+ );
+ assert_eq(expected, h(bytes_out), "different sighash");
+ // Compute with the cache disabled (passed as null)
+ Wally.tx_get_input_signature_hash(tx, input_idx, scripts, assets, values,
+ tapleaf_script, key_version, codesep_pos, annex, genesis, sighash, sighash_type,
+ null, bytes_out
+ );
assert_eq(expected, h(bytes_out), "different sighash");
Wally.map_free(cache);
diff --git a/src/swig_java/swig.i b/src/swig_java/swig.i
index 14d7f9f..5ce5d2a 100644
--- a/src/swig_java/swig.i
+++ b/src/swig_java/swig.i
@@ -393,9 +393,13 @@ static jobjectArray create_jstringArray(JNIEnv *jenv, char **p, size_t len) {
%typemap(jtype) const struct NAME * "Object"
%typemap(jni) const struct NAME * "jobject"
%typemap (in) struct NAME * {
- $1 = (struct NAME *)get_obj_or_throw(jenv, $input, ID, "NAME");
- if (!$1)
- return $null;
+ if (strcmp("NAME", "wally_map") == 0)
+ $1 = (struct NAME *)get_obj(jenv, $input, ID);
+ else {
+ $1 = (struct NAME *)get_obj_or_throw(jenv, $input, ID, "NAME");
+ if (!$1)
+ return $null;
+ }
}
%typemap(jtype) struct NAME * "Object"
%typemap(jni) struct NAME * "jobject"
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.