Repository navigation
fix(runtime): Buffer.from() handles inline SSO short strings (#1767) - #1773
Merged
Merged
Conversation
`js_buffer_from_value` only recognized heap strings via the STRING_TAG-only `is_string()` predicate. Strings of length 0..=5 are stored inline in the NaN-box payload under SHORT_STRING_TAG (0x7FF9, the Small String Optimization), which `is_string()` rejects. Such a value fell through to the pointer-extraction path, where its inline bytes (e.g. the ASCII of a 5-char `apiKey` like "mango") were masked to 48 bits and dereferenced as an `ArrayHeader*` — SIGSEGV. This surfaced as a crash in `js_buffer_from_value` during `@perryts/mysql`'s prepared-statement param encoder (`Buffer.from(v, 'utf8')`) on the first parameterized query, once the #1663 microtask fix let execution reach it. Add an SSO branch that decodes the inline bytes and routes them through a shared `buffer_from_str_bytes` helper (extracted from `js_buffer_from_string`) so the heap and inline paths honor identical hex/base64/latin1/utf8 encoding semantics. Add runtime regression tests covering empty/1..=5-byte SSO values under utf8 and hex.
Closed
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1767 — SIGSEGV in
js_buffer_from_valuereached from@perryts/mysql'sexecutePreparedNowon the first parameterized query.Root cause
Perry's Small String Optimization stores strings of length 0..=5 inline in the NaN-box payload under
SHORT_STRING_TAG(0x7FF9) instead of a heapStringHeader.js_buffer_from_valuegated the string path onis_string(), which is STRING_TAG-only (0x7FFF) and returnsfalsefor inline SSO values. So a short-string argument fell through to the pointer-extraction path (bits >> 48 >= 0x7FF8matches0x7FF9), where its inline bytes were masked to 48 bits and dereferenced as anArrayHeader*.The fault address from the repro was
0x056f676e616d— literally the bytesm a n g oplus the SSO length byte0x05, i.e. the 5-charapiKey"mango" interpreted as a pointer.This is a regression: before SSO, "mango" was a heap
StringHeaderandBuffer.fromhandled it. It became reachable in@perryts/mysql's prepared-statement param encoder (Buffer.from(v, 'utf8')) once the #1663 microtask fix let execution get that far.Fix
js_buffer_from_stringinto a sharedbuffer_from_str_bytes(bytes, encoding)helper.is_short_string()branch tojs_buffer_from_valuethat decodes the inline bytes viashort_string_to_bufand routes them through that helper, so heap and inline strings share identical hex/base64/latin1/utf8 semantics.Testing
buffer_from_value_decodes_sso_short_string_{utf8,hex}) covering empty + 1..=5-byte SSO values.buffer::test module green (15 tests);cargo fmt --all -- --checkclean.repro4.tsagainst@perryts/mysql@0.1.4+ a local MySQL. Before the fix it SIGSEGVs on the first POST (backtrace matches the issue exactly); after the fix it survives repeated sequential POSTs, inserts rows, and the 401 / non-SSO-key paths still work — verified with both default (auto-optimize) and--no-auto-optimizebuilds.