Skip to content

uuEncoder: fix out-of-bounds write and several decoding bugs - #363

Merged
vincent-richard merged 2 commits into
masterfrom
uuencode-security-and-bug-fixes
Oct 23, 2026
Merged

vincent-richard merged 2 commits into
masterfrom
uuencode-security-and-bug-fixes

Conversation

@vincent-richard

Copy link
Copy Markdown
Member

Memory safety:

  • A 'b' line length which does not introduce a "begin" line made the decoder read 5 bytes while probing for the marker, more than such a line holds. The per-line read count 'inLength - inPos' then underflowed, and the resulting near-SIZE_MAX count drove a write past the decoder's 64-byte stack buffer.

  • A line length larger than 48 made the decoder write out up to 15 bytes of its output buffer which it had not decoded, leaking uninitialized stack memory into the decoded data.

Hardening:

  • inputStreamStringAdapter and seekableInputStreamRegionAdapter now compare the requested count with the number of remaining bytes, instead of testing 'pos + count >= end': the sum may overflow and let a huge count through to the copy.

  • inputStreamStringAdapter no longer copies past the end of its range when it covers only a part of the string.

Decoding:

  • The number of encoded characters on a line was computed as (length * 4) / 3, while the encoder writes 4 characters for each group of 3 bytes, including an incomplete last group. Any line whose length is not a multiple of 3 (usually the last one) was only partly read, and the decoder lost sync with its input.

  • The mode and filename of the "begin" line were both extracted from the start of the line, so the filename included the mode.

  • On a "begin\n" line with no mode nor filename, the following line, which holds data, was taken as the mode and filename.

Fixes #362. Reported by Nguyen Dinh Hai (@Haind03).

Memory safety:

- A 'b' line length which does not introduce a "begin" line made the
  decoder read 5 bytes while probing for the marker, more than such a
  line holds. The per-line read count 'inLength - inPos' then
  underflowed, and the resulting near-SIZE_MAX count drove a write past
  the decoder's 64-byte stack buffer.

- A line length larger than 48 made the decoder write out up to 15
  bytes of its output buffer which it had not decoded, leaking
  uninitialized stack memory into the decoded data.

Hardening:

- inputStreamStringAdapter and seekableInputStreamRegionAdapter now
  compare the requested count with the number of remaining bytes,
  instead of testing 'pos + count >= end': the sum may overflow and let
  a huge count through to the copy.

- inputStreamStringAdapter no longer copies past the end of its range
  when it covers only a part of the string.

Decoding:

- The number of encoded characters on a line was computed as
  (length * 4) / 3, while the encoder writes 4 characters for each group
  of 3 bytes, including an incomplete last group. Any line whose length
  is not a multiple of 3 (usually the last one) was only partly read,
  and the decoder lost sync with its input.

- The mode and filename of the "begin" line were both extracted from
  the start of the line, so the filename included the mode.

- On a "begin\n" line with no mode nor filename, the following line,
  which holds data, was taken as the mode and filename.

Fixes #362. Reported by Nguyen Dinh Hai (@Haind03).
@vincent-richard
vincent-richard merged commit e85925e into master Oct 23, 2026
8 checks passed
@vincent-richard
vincent-richard deleted the uuencode-security-and-bug-fixes branch October 23, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VMime uuencode decoder: an unsigned underflow of the read length drives an out-of-bounds write on the stack while decoding a crafted MIME body

1 participant