Skip to content

StdOutStream: backport 7-Zip 26.01 terminal escape filter - #260

Open
tonghuaroot wants to merge 1 commit into
p7zip-project:masterfrom
tonghuaroot:fix/stdout-terminal-escape-26.01
Open

tonghuaroot wants to merge 1 commit into
p7zip-project:masterfrom
tonghuaroot:fix/stdout-terminal-escape-26.01

Conversation

@tonghuaroot

Copy link
Copy Markdown

Backports the terminal escape filter expansion landed in upstream 7-Zip 26.01 (released 2026-04-27) to keep parity with mainline on CStdOutStream::Normalize_UString.

What changed upstream

CPP/Common/StdOutStream.cpp in p7zip filters only \a \b \t \v \f \r (c >= 7 && c <= 13) when printing strings sourced from archives (entry names, error / warning messages) to the user's terminal. p7zip's filter is even narrower than 7-Zip 26.00 -- it lacks ESC (0x1b).

7-Zip 26.01 replaces the narrow check with IsDangerousTerminalChar() which also filters:

  • all of the C0 control range 0x00..0x1F, including ESC
  • DEL (0x7F) and the C1 control range 0x80..0x9F, including 0x9B which terminals treat as the 8-bit CSI start-of-escape byte
  • Unicode BiDi override characters 0x202A..0x202E (LRE/RLE/PDF/LRO/RLO) and 0x2066..0x2069 (LRI/RLI/FSI/PDI), the "Trojan Source" family

Impact

Archive entry names are attacker-controlled UTF-16 strings printed verbatim by 7z l and during 7z x. With only c >= 7 && c <= 13 filtered, an archive can:

  1. Embed BiDi override codepoints in an entry name so the displayed listing disagrees with the on-disk write target.
  2. Embed 0x1b (ESC) or 0x9B followed by ANSI sequences to overwrite earlier terminal output.

Patch

The hunk matches the upstream 7-Zip 26.01 source. Normalize_UString_Path reaches the same code path through Normalize_UString, so callers that print paths during list/extract get the fix transparently.

Disclosure

I am not a native English speaker. AI tooling was used to polish the prose in this PR description. The fix itself is a direct backport from upstream 7-Zip 26.01 source; no design choices were made beyond matching upstream verbatim.

Upstream 7-Zip 26.01 (released 2026-04-27) replaced the narrow
"\a \b \t \n \v \f \r" filter in CStdOutStream::Normalize_UString
with a comprehensive IsDangerousTerminalChar() that also covers:

  - all of the C0 controls (0x00..0x1F), including ESC (0x1b)
  - DEL (0x7F) and the C1 controls (0x80..0x9F), including the 0x9B
    8-bit CSI byte that terminals treat as start-of-escape-sequence
  - Unicode BiDi override characters 0x202A..0x202E (LRE/RLE/PDF/LRO/RLO)
    and 0x2066..0x2069 (LRI/RLI/FSI/PDI), the "Trojan Source" family.

p7zip's pre-existing filter was even narrower than upstream 26.00 --
it covered c >= 7 && c <= 13 but lacked ESC (0x1b). With only those
bytes filtered, an attacker who supplies an archive can embed BiDi
override codepoints in an entry name (which the listing path prints
verbatim) so that the displayed name disagrees with the on-disk name --
e.g. a file shown as "safe.txt" but actually written as "exe.tnp".
Similarly the 0x9B CSI byte was not filtered, allowing an archive name
to inject raw ANSI escape sequences into the user's terminal when
running 7z l / 7z x.

Patch matches upstream 7-Zip 26.01 source.

Signed-off-by: tonghuaroot <tonghuaroot@gmail.com>
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.

1 participant