js: allow null buffers for bytes inputs
What changed, and why it matters
This commit updates the JavaScript/WebAssembly wrapper for libwally-core so that functions expecting a raw byte input (like a cryptographic key or transaction data) can now accept `null` in addition to a buffer. Previously, passing `null` would likely throw a type error. The change is small and appears intended to support C functions that treat a NULL pointer plus zero length as a valid 'no data' input. There is no direct evidence in the commit that this fixes a security vulnerability, but it could prevent application crashes or incorrect behavior when callers intentionally pass no data.
Treat as a routine API improvement. Review downstream callers to ensure they do not rely on the previous strict rejection of `null` for security-critical parameters, and verify that the underlying C functions safely handle NULL/0-length inputs in all affected call sites. No urgent security patch is indicated by this commit alone.
Security signals we found
API contract relaxation: allows null where previously rejected
Potential reduction in type-error-driven denial of service or unexpected exceptions
No direct memory corruption, overflow, or cryptographic bypass signal in the diff
Change is in JS/WASM glue code, not in C cryptographic implementation
Evidence from the diff
The patch modifies src/wasm_package/src/core.js so that types.IntArray for Uint8Array returns {args: [null, 0]} when the input is null, instead of proceeding to the type check that would throw WallyArrayNumTypeError. It also updates tools/build_wrappers.py to declare the TypeScript type for const unsigned char* parameters as Buffer|Uint8Array|null. This aligns the JS binding with the underlying C API convention where many byte-input arguments can be NULL with length 0. The change is defensive and API-facing rather than a memory-safety fix in the core library.
Changed components
src/wasm_package/src/core.jstools/build_wrappers.pyJavaScript/WebAssembly bindings for libwally-coreInspect captured patch +7 / −2
diff --git a/src/wasm_package/src/core.js b/src/wasm_package/src/core.js
index d1bbed4..c5063e1 100644
--- a/src/wasm_package/src/core.js
+++ b/src/wasm_package/src/core.js
@@ -46,6 +46,11 @@ const _wally_free_string = Module.cwrap('wally_free_string', 'number', ['number'
types.IntArray = (IntArrayType, heap, wrap=x=>x) => ({
wasm_types: ['number', 'number'],
to_wasm: int_arr => {
+ if (int_arr === null && IntArrayType == Uint8Array) {
+ return {
+ args: [null, 0]
+ }
+ }
if (!Array.isArray(int_arr) && !(int_arr instanceof IntArrayType)) {
throw new WallyArrayNumTypeError(int_arr, IntArrayType)
}
@@ -299,4 +304,4 @@ export function wrap(func_name, args_types) {
cleanups.forEach(cleanup_fn => cleanup_fn())
}
}
-}
\ No newline at end of file
+}
diff --git a/tools/build_wrappers.py b/tools/build_wrappers.py
index 3f52d56..359d3dd 100755
--- a/tools/build_wrappers.py
+++ b/tools/build_wrappers.py
@@ -396,7 +396,7 @@ def gen_wasm_package(funcs, all_funcs):
# Input arrays (represented as two arguments - the first identified by this map, followed by a FOO_len argument)
# map of C type -> (JS type, TypeScript argument type)
typemap_arrays = {
- 'const unsigned char*' : ('T.Bytes', 'Buffer|Uint8Array'),
+ 'const unsigned char*' : ('T.Bytes', 'Buffer|Uint8Array|null'),
'const uint32_t*' : ('T.Uint32Array', 'Uint32Array|number[]'),
'const uint64_t*' : ('T.Uint64Array', 'BigUint64Array|Array<bigint>'),
}
Why this scored 28/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.