crypto.createHash(...).update(<short string>) segfaults in perry_stdlib::crypto::util::bytes_from_ptr when the argument is a short (inline / SSO) string built at runtime.
Repro
import * as crypto from "node:crypto";
const i = 3;
const s = "x" + (i & 7);
console.log(crypto.createHash("sha1").update(s).digest("hex"));
- Node 26.5.1: prints
15da3daa68966ce00bc4d1103f0561573cd36b8a.
- Perry at
7071a126f (Linux x86_64, --release with CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16, PERRY_NO_AUTO_OPTIMIZE=1): SIGSEGV. Also reproduced with a separate main build at b6a85cdad on the same host.
Longer strings (for example "request-path-/api/items/" + n) work. That fits the short-string (SSO) representation reaching a reader that assumes a heap StringHeader.
Stack
#0 perry_stdlib::crypto::util::bytes_from_ptr
#1 perry_stdlib::crypto::x509::decode_hash_update_value
#2 perry_stdlib::crypto::hash_handles::dispatch_hash
#3 js_handle_method_dispatch
#4 perry_runtime::object::native_call_method::handle_methods::dispatch_handle
#5 js_native_call_method
decode_hash_update_value calls bytes_from_ptr(arg_ptr(value)), and arg_ptr only masks the low 48 bits. An SSO string value carries no heap pointer, so bytes_from_ptr reads the masked bits as a StringHeader*. arg_bytes / arg_string use the same pattern, so other crypto arguments are probably affected as well (for example the update encoding argument and createHmac keys).
Possibly the same class as #11430, which is a pg segfault being fixed by reading the SSO bytes directly rather than through a header pointer.
Found while validating #11453. Not fixed there.
crypto.createHash(...).update(<short string>)segfaults inperry_stdlib::crypto::util::bytes_from_ptrwhen the argument is a short (inline / SSO) string built at runtime.Repro
15da3daa68966ce00bc4d1103f0561573cd36b8a.7071a126f(Linux x86_64,--releasewithCARGO_PROFILE_RELEASE_CODEGEN_UNITS=16,PERRY_NO_AUTO_OPTIMIZE=1): SIGSEGV. Also reproduced with a separate main build atb6a85cdadon the same host.Longer strings (for example
"request-path-/api/items/" + n) work. That fits the short-string (SSO) representation reaching a reader that assumes a heapStringHeader.Stack
decode_hash_update_valuecallsbytes_from_ptr(arg_ptr(value)), andarg_ptronly masks the low 48 bits. An SSO string value carries no heap pointer, sobytes_from_ptrreads the masked bits as aStringHeader*.arg_bytes/arg_stringuse the same pattern, so othercryptoarguments are probably affected as well (for example theupdateencoding argument andcreateHmackeys).Possibly the same class as #11430, which is a pg segfault being fixed by reading the SSO bytes directly rather than through a header pointer.
Found while validating #11453. Not fixed there.