Skip to content

fix: Fix OOM crash in SettingsSerializer readStream() VInt decoder.#707

Open
lggcs wants to merge 2 commits into
TokTok:masterfrom
lggcs:master
Open

fix: Fix OOM crash in SettingsSerializer readStream() VInt decoder.#707
lggcs wants to merge 2 commits into
TokTok:masterfrom
lggcs:master

Conversation

@lggcs

@lggcs lggcs commented Apr 15, 2026

Copy link
Copy Markdown

readStream() had no bounds check on the VInt shift count or the accumulated size value before calling QByteArray::resize(), allowing a crafted settings file to trigger an unbounded allocation (up to 2GB) and immediate OOM crash. The signed left-shift also produced undefined behavior when the shift exceeded 28 bits. Add the same overflow guard used by dataToVInt() (num2 > sizeof(int) * CHAR_BIT), stream error status checks, and a post-loop validity check on the decoded size before allocation.

Resolves #706


This change is Reviewable

readStream() had no bounds check on the VInt shift count or the accumulated size value before calling QByteArray::resize(), allowing a crafted settings file to trigger an unbounded allocation (up to 2GB) and immediate OOM crash. The signed left-shift also produced undefined behavior when the shift exceeded 28 bits. Add the same overflow guard used by dataToVInt() (num2 > sizeof(int) * CHAR_BIT), stream error status checks, and a post-loop validity check on the decoded size before allocation.
@github-actions

github-actions Bot commented Apr 15, 2026

Copy link
Copy Markdown

Tip

Preview URL:

@github-actions github-actions Bot added the bug Bug fix for the user, not a fix to a build script label Apr 15, 2026

@iphydf iphydf left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's an easy way to unit test this, please add a test. If not, file an issue and I'll follow up.

…tion

Covers the three guards added to readStream():

- OOM payload: VInt encoding 0x7FFFFFFF triggers the shift-count guard
  (num2 > sizeof(int)*CHAR_BIT), preventing QByteArray::resize(INT_MAX)
- Shift overflow: 5 continuation bytes push shifts past 32 bits,
  exercising the same guard for the UB case
- Truncated stream: premature EOF is caught by the QDataStream status
  check before each readRawData
- Zero-size VInt: the post-loop num <= 0 guard rejects empty values
- Valid settings: round-trips a key/value pair through the serializer
- isSerializedFormat: verifies QTOX magic detection
@lggcs

lggcs commented May 19, 2026

Copy link
Copy Markdown
Author

If there's an easy way to unit test this, please add a test. If not, file an issue and I'll follow up.

@iphydf comprehensive test case was committed.

@Green-Sky

Green-Sky commented May 30, 2026

Copy link
Copy Markdown
Member

@lggcs we require signed commit, to denote authorship and origin.

Other than that, it looks good now (:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug fix for the user, not a fix to a build script

Development

Successfully merging this pull request may close these issues.

[Bug]: SettingsSerializer readStream() Unbounded Allocation and Integer Overflow

3 participants