-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pasting specific texts into vim (WSL) breaks some keys #16655
Comments
I have a little more information now. It looks like the bracketed paste sequences are getting corrupted somehow. The paste starts with the opening sequence ( As a result, vim thinks you're still pasting content, so it won't process any command keys unless you manually terminate the paste. Ctrl+C is one way of doing that, but you could also enter the closing bracket sequence manually: Esc [ 2 0 1 ~. The length of the paste seems to be a factor in the bug, because for every additional character I add to the pasted content, one more character is included in the closing bracket sequence, until it's sending the full sequence. At that point, additional content doesn't seem make any difference. |
I think I know why it's failing now. There's assumedly a 4096 byte buffer somewhere, and the pasted content along with the bracketed paste sequences adds up to just over 4096 bytes. As a result, the closing bracket sequence is cut off, and what we end up receiving in the initial packet is something like this:
When the parser gets to that last escape, we have a heuristic that looks for a single escape, or a two byte Alt+key sequence, but this fits neither of those patterns, so it seems we just drop those characters! Then when the next packet arrives, we get the remaining characters for the closing bracket ( The more I think about, the more convinced I am that what we're doing here is completely wrong, but I don't know what the correct solution would be. |
terminal/src/terminal/parser/stateMachine.cpp Lines 2152 to 2155 in ef96e22
I wonder if it's sufficient to always switch into a normal VT state machine mode once we've encountered a Win32 Input Mode sequence, e.g.:
|
Could we just amend the heuristic to also account for bracketed paste mode? Like, if we've started a bracketed paste, don't ever flush the state machine at the end of a write? Not sure how bad that would be. |
Sorry, I think I've been misleading everyone. I've just been looking at this again, and I now realise that my initial understanding was wrong. When the first packet ends with half an escape sequence (the It gets to a point where it decides it should flush the content to the input queue. However, the only thing it can flush is what it has in the current buffer, which is the second half of the sequence. So I think that's how the first half ends up being dropped, and vim sees the second half of the sequence as additional pasted text. I think it's best I leave this to someone else to figure out, because I seem to be out of my depth here. |
Any update on this? |
I've just had this issue come up again in a different context (a VT query response that exceeded 4K), and I think I have a better understanding of what's going wrong now. As I mentioned above:
But the state machine already has a process for dealing with this. If you exit the state machine and you're not in the ground state, it can save the current run in the The problem is that this process is only applied to the output state machine. See here: terminal/src/terminal/parser/stateMachine.cpp Lines 2073 to 2084 in 0199ca3
So I think all we need to do is copy that chunk of code up a couple of lines into the I've done a basic test with this patch, and it seems to fix my problem as well as the vim pasting bug described in this issue. I don't know if there are any edge cases I'm missing though. |
## Summary of the Pull Request When conhost receives input from a conpty connection, and that input arrives in a block larger than our 4K buffer, we can end up with a VT sequence that's split at the buffer boundary. Previously that could result in the start of the sequence being dropped, and the remaining characters being interpreted as individual key presses. This PR attempts to fix the issue by caching the unprocessed characters from the start of the sequence, and then combining them with the second half of the sequence when it's later received. ## Validation Steps Performed I've confirmed that pasting into vim now works correctly with the sample data from issue #16655. I've also tested with a `DECCTR` report larger than 4K which would previously have been corrupted, and which now works as expected. ## PR Checklist - [x] Closes #16655 (cherry picked from commit 131728b) Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSCpCk Service-Version: 1.21
Windows Terminal version
1.20.10303.0 and 1.19.10302.0
Windows build number
10.0.22621.0
Other Software
vim 9.1.31 in WSL
nvim v0.9.5 in WSL
Steps to reproduce
This input is a base64 encoded chunk of Lorem Ipsum.
The issue only happens with specific inputs. I encountered it first when pasting another base64 encoded text, but that had sensitive data in it.
Then I played around with
dd if=lorem.txt bs=1 count=... | base64 -w 180
until I found a configuration that also triggered the issue.Expected Behavior
Escape, backspace and Function keys works properly after the paste.
Only the pasted text appears in the editor.
Actual Behavior
You are now stuck in editing mode. Esc, backspace and other keys are now sending weird escape sequences.
After the last character a
1~
appears. Pressing esc inserts^[
, pressing backspace inserts^?
.The text was updated successfully, but these errors were encountered: