Home
|
FAQ
|
Feedback
|
Licence
|
Updates
|
Mirrors
|
Keys
|
Links
|
Team
Download:
Stable
ยท
Snapshot
|
Docs
|
Privacy
|
Changes
|
Wishlist
When the PuTTY terminal code wants to make a change to the terminal window properties, the change is not made immediately, but queued until the next window redraw. This policy was introduced as a means of limiting the rate at which a server could cause PuTTY to perform GUI activity, preventing at least one server-triggerable DoS attack.
One of the window-property changes included in this policy is its
size. When the server sends any of the escape sequences that triggers
a terminal resize (including both the DECCOLM ESC[?3h
/
ESC[?3l
sequences for 80/132 column switch, and the xterm
general resize sequence
ESC[8;
H;
Wt
), the
actual resize may not happen until up to 20ms later.
But it's not unreasonable for the server to send a control sequence to resize the terminal, and then immediately follow that up with a stream of terminal output that draws a full screen of text in the expectation that it's drawing on the new window size. So if PuTTY has not yet enacted the size change, then that redraw can go wrong, e.g. with lines of text intended for the new terminal width wrapping at the shorter old width. (Or being truncated, depending on other terminal settings, but neither of those was what you actually wanted.)
It's not clear what the best fix for this might be. I can think of several plausible options:
Revert the rate-limiting for resizes, and put things back to the way they used to work, so that window resizes are enacted synchronously. That might be OK: we don't know for sure that a significant server-triggered DoS is available relating to resizes in particular. But it might reintroduce a vulnerability, so I'd rather not do it that way.
Pause processing of terminal output until a resize
completes. The physical window resize would still happen at
the same time as it currently does, but until it was finished,
terminal output would remain in terminal.c
's incoming
buffer, waiting for the terminal to be the right size to accept it.
This would introduce up to 20ms of delay in terminal output processing
whenever a resize took place.
Decouple logical and physical terminal resizes.
Perhaps the most conceptually clean solution, but also the trickiest
to implement: respond to a terminal resize request by immediately
changing the logical size of the terminal screen in the
terminal.c
data structures, so that further terminal data
can be immediately processed and will find terminal features like line
wrapping behaving as expected. But the physical resize of the
window, in the GUI, would still wait until the next redraw timer, and
at that point, the window would become the new size and have the new
contents drawn on it.
The biggest problem with this last option is: what happens if the
GUI doesn't give us the window size we asked for? If you try to resize
a window larger than the screen on some GUI platforms (including
Windows), you get a size that will fit in place of the size you
requested. And you don't find this out until you actually attempt the
physical resize in the GUI, and get sent a WM_SIZE
telling you what size you actually got. So in the decoupled
approach, you'd end up already having drawn a load of output to the
terminal data structures in the expectation of getting one size, and
by the time you find you got a different size instead, it's a bit late
to figure out what the screen should have ended up looking
like.
But perhaps that doesn't matter too much, and we should just regard that later change of mind on the GUI's part as equivalent to a user action resizing the terminal window. It's not clear.
2021-12-29: should be fixed by 420fe75552afa9490c7ca2ff08e92ec96933cfe1, using the middle option of the three listed above: we pause output processing while waiting for the window system to respond to our resize and tell us what size we ended up with. This does cause a bit of delay, because we still enact the window resize on a timer, so you can start with up to 20ms of delay while waiting for that timer to fire, and then it might take time to get a response back from the window system (e.g. if it's X11 and everything is asynchronous).
A danger on X11 in particular is that if the window manager is in a confused state, it might never get round to responding to the resize request, even to send a notification that it refused. There's a fallback 5-second timeout for that situation, to avoid terminal output processing being 'paused' forever.