Skip to content

test: add unit tests for SettingsSerializer readStream() input valida…

8501425
Select commit
Loading
Failed to load commit list.
Open

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

test: add unit tests for SettingsSerializer readStream() input valida…
8501425
Select commit
Loading
Failed to load commit list.
Mergeable / Mergeable succeeded May 19, 2026 in 2s

3 checks passed!

Status: PASS

Details

✔️ Validator: TITLE

  • ✔️ All the requisite validations passed for 'or' option
    Input : fix: Fix OOM crash in SettingsSerializer readStream() VInt decoder.
    Settings : {"or":[{"must_include":{"regex":"^(feat|docs|chore|cleanup|fix|refactor|test|style|perf)(\\([^) ]+\\))?:\\ .+$","message":"Semantic release conventions must be followed."}},{"must_include":{"regex":"^Bump [^ ]* from [^ ]* to [^ ]*$","message":"Dependabot PRs are exempt from semantic release conventions."}}]}

✔️ Validator: COMMIT

  • ✔️ Your commit messages met the specified criteria
    Input : fix: Fix OOM crash in SettingsSerializer readStream() VInt decoder.

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.,test: add unit tests for SettingsSerializer readStream() input validation

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
    Settings : {"do":"commit","message":{"regex":"^((feat|docs|chore|cleanup|fix|refactor|test|style|perf)(\\([^) ]+\\))?:\\ .+|Bump [^ ]* from [^ ]* to [^ ]*)","message":"Semantic release conventions must be followed."}}

✔️ Validator: DESCRIPTION

  • ✔️ description must exclude '\[ \]'
    Input : 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

Settings : {"must_exclude":{"regex":"\\\\[ \\\\]","message":"There are incomplete TODO task(s) unchecked."}}