conhost.exe heap corruption in COOKED_READ_DATA::_handlePostCharInputLoop #13284

Closed
opened 2026-01-31 03:38:43 +00:00 by claunia · 17 comments
Owner

Originally created by @emmett-b on GitHub (Apr 2, 2021).

Originally assigned to: @zadjii-msft on GitHub.

Windows Terminal version (or Windows build number)

Windows Terminal 1.6.10571.0
OS Build 21343.10000

Other Software

My awful cmd wrapper (attempt at a terminal emulator) written in a weekend 3 years ago. A pyramid of hacks that seems to fuzz the new conhost enough to make it crash. Wasn't crashing before, apparently until I upgraded to Windows 10 insider dev channel.

Steps to reproduce

Not clear yet but my cmd wrapper has multiple threads calling into ReadConsoleOutput, GetConsoleScreenBufferInfo, WriteConsoleInput many times. Looks like it's triggered by successive calls to GetConsoleScreenBufferInfo and then WriteConsoleInput.

Expected Behavior

no crash

Actual Behavior

Heap corruption. Attaching a debugger showed that it was crashing during a call to free which ended up in ntdll!RtlpHeapFindListLookupEntry. I then enabled app verifier for conshost.exe and then it crashed in memcpy called by COOKED_READ_DATA::_handlePostCharInputLoop. So this likely where the heap corruption happens.

Originally created by @emmett-b on GitHub (Apr 2, 2021). Originally assigned to: @zadjii-msft on GitHub. ### Windows Terminal version (or Windows build number) Windows Terminal 1.6.10571.0 OS Build 21343.10000 ### Other Software My awful cmd wrapper (attempt at a terminal emulator) written in a weekend 3 years ago. A pyramid of hacks that seems to fuzz the new conhost enough to make it crash. Wasn't crashing before, apparently until I upgraded to Windows 10 insider dev channel. ### Steps to reproduce Not clear yet but my cmd wrapper has multiple threads calling into ReadConsoleOutput, GetConsoleScreenBufferInfo, WriteConsoleInput many times. Looks like it's triggered by successive calls to GetConsoleScreenBufferInfo and then WriteConsoleInput. ### Expected Behavior no crash ### Actual Behavior Heap corruption. Attaching a debugger showed that it was crashing during a call to free which ended up in ntdll!RtlpHeapFindListLookupEntry. I then enabled app verifier for conshost.exe and then it crashed in memcpy called by COOKED_READ_DATA::_handlePostCharInputLoop. So this likely where the heap corruption happens.
Author
Owner

@emmett-b commented on GitHub (Apr 2, 2021):

I can provide minidumps with heap memory.
Here's the call stack using app verifier:
image
Exception thrown at 0x00007FFA7C66E35B (ucrtbase.dll) in conhost.exe: 0xC0000005: Access violation writing location 0x0000023781939290.

@emmett-b commented on GitHub (Apr 2, 2021): I can provide minidumps with heap memory. Here's the call stack using app verifier: ![image](https://user-images.githubusercontent.com/28929018/113393444-fafa0980-9396-11eb-9f06-10418dd55624.png) Exception thrown at 0x00007FFA7C66E35B (ucrtbase.dll) in conhost.exe: 0xC0000005: Access violation writing location 0x0000023781939290.
Author
Owner

@emmett-b commented on GitHub (Apr 2, 2021):

image

@emmett-b commented on GitHub (Apr 2, 2021): ![image](https://user-images.githubusercontent.com/28929018/113393671-46acb300-9397-11eb-83c0-d5f6e2acbb84.png)
Author
Owner

@emmett-b commented on GitHub (Apr 2, 2021):

Where could I post a minidump of the crash? Here it says "We don't support that file type". The dump is 155MB.

@emmett-b commented on GitHub (Apr 2, 2021): Where could I post a minidump of the crash? Here it says "We don't support that file type". The dump is 155MB.
Author
Owner

@emmett-b commented on GitHub (Apr 2, 2021):

I tried adding locks to serialize my api calls but didn't seem to help.

@emmett-b commented on GitHub (Apr 2, 2021): I tried adding locks to serialize my api calls but didn't seem to help.
Author
Owner

@WSLUser commented on GitHub (Apr 2, 2021):

Your best bet is to do a dump with feedback hub and post the link here. Also try zipping your dump.

@WSLUser commented on GitHub (Apr 2, 2021): Your best bet is to do a dump with feedback hub and post the link here. Also try zipping your dump.
Author
Owner

@zadjii-msft commented on GitHub (Apr 2, 2021):

Your best bet is to do a dump with feedback hub

Meh, the Feedback Hub is garbage. If GitHub doesn't let you upload the .zip, then just email it to the address in my profile 😉 (and @ me here so I know to look for it)

@zadjii-msft commented on GitHub (Apr 2, 2021): > Your best bet is to do a dump with feedback hub Meh, the Feedback Hub is garbage. If GitHub doesn't let you upload the `.zip`, then just email it to the address in my profile 😉 (and @ me here so I know to look for it)
Author
Owner

@emmett-b commented on GitHub (Apr 2, 2021):

@zadjii-msft just send you the zip file

@emmett-b commented on GitHub (Apr 2, 2021): @zadjii-msft just send you the zip file
Author
Owner

@DHowett commented on GitHub (Apr 2, 2021):

That's not good! Thanks!

@DHowett commented on GitHub (Apr 2, 2021): _That's not good!_ Thanks!
Author
Owner

@zadjii-msft commented on GitHub (Apr 2, 2021):

@ future self: I downloaded the zip to my corporate OneDrive. I'll probably take a look when I get around to a full triage pass Tuesday

@zadjii-msft commented on GitHub (Apr 2, 2021): @ future self: I downloaded the zip to my corporate OneDrive. I'll probably take a look when I get around to a full triage pass Tuesday
Author
Owner

@DHowett commented on GitHub (Apr 2, 2021):

_handlePostCharInputLoop is one of the our large, refactoring-resistant functions. It's older than the rest of the code, like WriteCharsLegacy, and critically important that we get right because it underpins the line editing behavior of CMD and everything else that uses cooked input.

It's here, for those interested:

4b7d955012/src/host/readDataCooked.cpp (L1003)

@DHowett commented on GitHub (Apr 2, 2021): `_handlePostCharInputLoop` is one of the our large, refactoring-resistant functions. It's older than the rest of the code, like WriteCharsLegacy, and *critically important* that we get right because it underpins the line editing behavior of CMD and everything else that uses cooked input. It's here, for those interested: https://github.com/microsoft/terminal/blob/4b7d9550129615e14501abddbd92b04b33a4a0fb/src/host/readDataCooked.cpp#L1003
Author
Owner

@emmett-b commented on GitHub (Apr 6, 2021):

I build OpenConsole in debug mode at commit 507a84664e (tag: v1.6.10571.0).
I YOLO'd my system by briefly replacing system32\conhost.exe.
Still using app verifier, crash is happening at readDataCooked.cpp:1158
memmove(_userBuffer, _backupLimit, numBytes);
_userBuffer points to non existent memory. So it seems _handlePostCharInputLoop isn't the culprit, _userBuffer is already wrong when it's called. Looks like a use-after-free.

@emmett-b commented on GitHub (Apr 6, 2021): I build `OpenConsole` in debug mode at commit 507a84664e6d5449bc31746510128d3136ecc719 (tag: v1.6.10571.0). I YOLO'd my system by briefly replacing system32\conhost.exe. Still using app verifier, crash is happening at readDataCooked.cpp:1158 `memmove(_userBuffer, _backupLimit, numBytes);` `_userBuffer` points to non existent memory. So it seems `_handlePostCharInputLoop` isn't the culprit, _userBuffer is already wrong when it's called. Looks like a use-after-free.
Author
Owner

@emmett-b commented on GitHub (Apr 6, 2021):

On the crashing call stack we see that InputBuffer::Write calls WakeUpReadersWaitingForData (which then calls ConsoleWaitQueue::NotifyWaiters)
InputBuffer::WaitQueue contains 1 ConsoleWaitBlock item.
This wait block has _WaitReplyMessage.State.OutputBuffer == _pWaiter->_userBuffer pointing to non existent memory.
This waiting message probably had its output buffer freed somehow.
The waiting block api number is 0x01000005 (API_NUMBER_READCONSOLE).
So it has been inserted by a previous ReadConsoleOutput call.
The buffer must have been allocated in ApiDispatchers::ServerReadConsole, with a call to m->GetAugmentedOutputBuffer.
Not sure who is responsible for freeing this buffer but I guess it's freed prematurely.
I hope this helps.

@emmett-b commented on GitHub (Apr 6, 2021): On the crashing call stack we see that `InputBuffer::Write` calls `WakeUpReadersWaitingForData` (which then calls ` ConsoleWaitQueue::NotifyWaiters`) `InputBuffer::WaitQueue` contains 1 `ConsoleWaitBlock` item. This wait block has `_WaitReplyMessage.State.OutputBuffer` == `_pWaiter->_userBuffer` pointing to non existent memory. This waiting message probably had its output buffer freed somehow. The waiting block api number is 0x01000005 (API_NUMBER_READCONSOLE). So it has been inserted by a previous `ReadConsoleOutput` call. The buffer must have been allocated in `ApiDispatchers::ServerReadConsole`, with a call to `m->GetAugmentedOutputBuffer`. Not sure who is responsible for freeing this buffer but I guess it's freed prematurely. I hope this helps.
Author
Owner

@emmett-b commented on GitHub (Apr 6, 2021):

@zadjii-msft I can send you a debug mode minidump of the crash if you're interested.

@emmett-b commented on GitHub (Apr 6, 2021): @zadjii-msft I can send you a debug mode minidump of the crash if you're interested.
Author
Owner

@DHowett commented on GitHub (Apr 13, 2021):

Triaged into Windows vNext -- I think there are some crash dumps we're getting from this.

@DHowett commented on GitHub (Apr 13, 2021): Triaged into Windows vNext -- I think there are some crash dumps we're getting from this.
Author
Owner
@zadjii-msft commented on GitHub (Apr 16, 2021): based on https://github.com/microsoft/terminal/issues/9828#issuecomment-820850638, /dup https://dev.azure.com/microsoft/OS/_workitems/edit/24113101
Author
Owner

@ghost commented on GitHub (Apr 16, 2021):

Hi! We've identified this issue as a duplicate of one that exists on somebody else's Issue Tracker. Please make sure you subscribe to the referenced external issue for future updates. Thanks for your report!

@ghost commented on GitHub (Apr 16, 2021): Hi! We've identified this issue as a duplicate of one that exists on somebody else's Issue Tracker. Please make sure you subscribe to the referenced external issue for future updates. Thanks for your report!
Author
Owner

@DHowett commented on GitHub (May 11, 2021):

Realized that this was not fixed, and that we now understand the actual root cause 😄

@DHowett commented on GitHub (May 11, 2021): Realized that this _was not_ fixed, and that we now understand the actual root cause :smile:
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#13284