fix(NODE-7611): bounds check findNull scan in on-demand parser - #924
Open
AbinMadathil-Celigo wants to merge 3 commits into
Open
fix(NODE-7611): bounds check findNull scan in on-demand parser#924AbinMadathil-Celigo wants to merge 3 commits into
AbinMadathil-Celigo wants to merge 3 commits into
Conversation
A malformed document with a string element declaring a zero length passes the size/terminator guards and advances the cursor to the declared document end. The next loop iteration then called findNull from past the end of the buffer: out-of-range Uint8Array reads return undefined (never 0x00), so the scan never terminated — a synchronous CPU hang on caller-controlled bytes. findNull now stops at the end of the input and throws BSONOffsetError instead of scanning out of range forever. The standard deserializer path (BSON.deserialize) is unaffected; it already rejects stringSize <= 0.
tadjik1
reviewed
Aug 27, 2026
tadjik1
requested changes
Aug 27, 2026
tadjik1
left a comment
Member
There was a problem hiding this comment.
hi @AbinMadathil-Celigo , thanks for your work! Please check one comment in the code, I believe there is another case we want to make sure works as expected.
…'s end The length guard only compared the element's length against the whole document size, so an element near the end of a (sub)document could declare a value that extends past the document's null terminator and be silently accepted — e.g. an embedded document whose int32 element's value bytes actually belong to the outer document's next element. The value must now fit within the current document: it may extend at most up to the document's null terminator byte. This also catches the zero-length string repro earlier with a more descriptive error; the findNull bounds check remains as a safety net for name and regex scans. Also fixes a wire-inaccurate binary fixture in the parser tests that declared 5 data bytes but provided 1 (asserted length is unchanged).
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.
Description
Summary of Changes
A malformed document with a string element declaring a zero length passes the on-demand parser's size/terminator guards and advances the cursor to the declared document end. The next loop iteration then calls
findNullfrom past the end of the buffer: out-of-rangeUint8Arrayreads returnundefined(which is never0x00), so the scan never terminates — a synchronous CPU hang on caller-controlled bytes.findNullnow stops at the end of the input and throws aBSONOffsetError('Null terminator not found')instead of scanning out of range forever. The existing "reached the document terminator" throw is preserved by folding both conditions intonullTerminatorOffset >= bytes.length - 1.Repro (hangs before this change, throws after):
Notes for Reviewers
BSON.onDemand.parseToElementspath is affected; the standardBSON.deserializepath already rejectsstringSize <= 0.stringSize <= 0check is not mirrored on the on-demand path. I kept this PR focused on the non-termination bug; mirroring that check would need per-type care (e.g. a zero length is valid forbinData) and could be a follow-up.What is the motivation for this change?
Fixes NODE-7611 (part of NODE-7598).
Release Highlight
BSON.onDemand.parseToElementsno longer hangs on malformed inputA malformed document containing a string element with a declared length of zero previously caused a non-terminating scan (synchronous CPU hang). The experimental on-demand parser now throws a
BSONOffsetErrorinstead.Double check the following
npm run check:lint)type(NODE-xxxx)[!]: description