Skip to content

Crash: null IControlInteractivity dereferenced in TermControl::_PointerMovedHandler (AV read @ 0x0) #20477

Description

@iABangTony

Windows Terminal version

1.24.11911.0

Windows build number

10.0.26200.8893

Other Software

Nothing relevant — this is not an interaction bug with other software. Included for completeness:

  • Host: LG Gram 17Z90S-H, Intel Core Ultra 7 155H, Intel Arc iGPU (driver 31.0.101.5382)
  • Windows 11 Pro 25H2 (10.0.26200.8893)
  • Default profile is PowerShell 7 (Windows.Terminal.PowershellCore); WSL Fedora 42 also in use

I specifically verified that no third-party code was loaded into the crashed process. The minidump's module list has 131 entries; the only non-Microsoft modules are the Intel graphics UMD (igd10iumd64.dll, igc64.dll, igdgmm64.dll) and icu.dll. AppInit_DLLs is empty. There is no keyboard-hook / security-agent / injector involved.

Non-default settings, in case any of them matter: backgroundImage: desktopWallpaper + backgroundImageOpacity: 0.2/0.15, FiraCode Nerd Font Mono, experimental.detectURLs: false. Notably experimental.repositionCursorWithMouse is NOT set, so it is at its default of false — mentioning this up front because #19667/#20433 were attributed to that feature and this crash happens without it.

Steps to reproduce

I don't have a deterministic repro, so I'm filing a symbolized crash analysis instead. Two occurrences with matching root cause, both with dumps in hand.

What I can say about the conditions:

  1. Normal interactive use with the mouse over a terminal pane.
  2. The crash lands in the PointerMoved (mouse-move) routed-event path, so the mouse is moving over the control at the moment it dies.
  3. It is a race against control/pane teardown — _interactivity has already been released while a XAML pointer event is still in flight. I could not force the timing by hand.
  4. Frequency: 13 crashes on this machine between 2025-12-29 and 2026-07-28 (table in Actual Behavior). Terminal hosts every window/tab in one process, so each crash takes down all windows at once.

I have minidumps for both occurrences and can capture a TTD trace as well. The dumps contain environment blocks and terminal memory, so I'd rather not attach them to a public issue — happy to send them privately by email, or to file a Feedback Hub report so you can pull them off the backend. Just say which you'd prefer.

Expected Behavior

TermControl::_PointerMovedHandler should tolerate _interactivity being empty — either null-check before calling into it, or detach the PointerMoved handler before the ControlInteractivity object is released, so an in-flight XAML pointer event cannot reach a torn-down control.

Either way, moving the mouse should never be able to terminate the process.

Actual Behavior

TermControl::_PointerMovedHandler invokes _interactivity.PointerMoved(...) while _interactivity is null. The C++/WinRT consume_* stub reads the vtable pointer from address 0 and the process dies instantly.

Analyzed with cdb against the public Microsoft symbol server.

Exception record

ExceptionAddress: 00007ffd79bc031c
  (Microsoft_Terminal_Control!winrt::impl::consume_Microsoft_Terminal_Control_IControlInteractivity
     <winrt::Microsoft::Terminal::Control::IControlInteractivity>::PointerMoved+0x54)
   ExceptionCode: c0000005 (Access violation)
NumberParameters: 2
   Parameter[0]: 0000000000000000        <- read
   Parameter[1]: 0000000000000000        <- address
Attempt to read from address 0000000000000000

AV.Dereference: NullPtr
AV.Type:        Read

FAILURE_BUCKET_ID: INVALID_POINTER_READ_c0000005_Microsoft.Terminal.Control.dll!
  winrt::impl::consume_Microsoft_Terminal_Control_IControlInteractivity_
  winrt::Microsoft::Terminal::Control::IControlInteractivity_::PointerMoved

A second WER report for the same PID follows two seconds later with c000041d (FATAL_USER_CALLBACK_EXCEPTION) at the identical offset — the same AV escaping the KiUserCallbackDispatcher window-proc callback.

Call stack

Microsoft_Terminal_Control!...consume_..IControlInteractivity::PointerMoved+0x54   <-- AV, read @ 0x0
Microsoft_Terminal_Control!...implementation::TermControl::_PointerMovedHandler+0x255
Microsoft_Terminal_Control!...TermControlT<TermControl>::Connect::__l22::<lambda_21>::operator()+0x23  (inlined)
Microsoft_Terminal_Control!winrt::impl::delegate<Windows::UI::Xaml::Input::PointerEventHandler,...>::Invoke+0x41
Windows_UI_Xaml!CEventManager::RaiseRoutedEvent+0x258
Windows_UI_Xaml!ContentRootInput::PointerInputProcessor::ProcessPointerInput+0x1101
Windows_UI_Xaml!CInputServices::ProcessInput+0x96
Windows_UI_Xaml!CCoreServices::ProcessInput+0x27                          (inlined)
Windows_UI_Xaml!CXcpBrowserHost::HandleInputMessage+0x145
Windows_UI_Xaml!CJupiterControl::HandlePointerMessage+0xc1                (inlined)
Windows_UI_Xaml!CJupiterWindow::OnIslandPointerMessage+0x1aa
Windows_UI_Xaml!CXamlIslandRoot::InjectPointerMessage+0x4c                (inlined)
Windows_UI_Xaml!CXamlIslandRoot::OnIslandPointerMoved+0x4c                (inlined)
InputHost!PointerInputObserverWinRT::OnWindowMessage_Callback+0x12f
InputHost!SystemIslandInputSiteWinRT::OnWindowMessage_Callback+0x2ed
InputHost!WindowsMessageDeliveryAdapter::ProcessWindowMessage_NoLock_Callback+0x37c
user32!UserCallWinProcCheckWow+0x356
user32!DispatchMessageWorker+0x1dd
WindowsTerminal!<message loop>
WindowsTerminal!wWinMain+0x1e2

Faulting module file version: Microsoft.Terminal.Control.dll 1.24.2607.10001, offset 0x10031c.

A second occurrence — same class, different call site

2026-06-30, Terminal 1.24.11321.0 (TerminalApp.dll 1.24.2605.12001):

ExceptionAddress: TerminalApp!winrt::impl::consume_TerminalApp_IPaneContent
                    <winrt::TerminalApp::IPaneContent>::MinimumSize+0x2e
   ExceptionCode: c0000005   Attempt to read from address 0000000000000000

FAILURE_BUCKET_ID: INVALID_POINTER_READ_c0000005_TerminalApp.dll!
  winrt::impl::consume_TerminalApp_IPaneContent_winrt::TerminalApp::IPaneContent_::MinimumSize

Same shape: a projected WinRT interface is empty when a method is called on it — here a layout query against a pane whose content was already released. Also followed by a c000041d report at the identical offset.

Crash history on this machine

13 incidents since 2025-12-29, all in the XAML/UI layer, across four Terminal versions:

Date Terminal (file ver) Faulting module Exception Offset
2026-07-28 1.24.2607.10001 Microsoft.Terminal.Control.dll c0000005 → c000041d 0x10031c
2026-06-30 1.24.2605.12001 TerminalApp.dll c0000005 → c000041d 0xa96e
2026-05-14 1.24.2604.2001 Windows.UI.Xaml.dll c0000005 0x3d96c
2026-05-13 1.24.2604.2001 Windows.UI.Xaml.dll c0000005 0x3d96c
2026-04-09 1.23.2601.21001 Windows.UI.Xaml.dll c0000005 0x9b970
2026-03-10 (×6) 1.23.2601.21001 Windows.UI.Xaml.dll c0000005 0x1874a0 / 0x1874a6
2026-01-27 1.23.2512.16003 Windows.UI.Xaml.dll c000027b 0x8fadf3
2026-01-26 1.23.2512.16003 Windows.UI.Xaml.dll c000027b 0x8fadf3
2026-01-19 1.23.2512.16003 TerminalApp.dll c0000005 → c000041d 0x1698a7
2026-01-15 1.23.2512.16003 TerminalApp.dll c0000005 → c000041d 0x1698a7
2026-01-13 1.23.2512.16003 Windows.UI.Xaml.dll c000027b 0x8fadf3
2026-01-09 / 01-08 / 01-07 1.23.2512.16003 Windows.UI.Xaml.dll c000027b 0x8fadf3
2025-12-29 1.23.2512.16003 Windows.UI.Xaml.dll c000027b 0x8fadf3

Diagnostic identifiers (in lieu of a Feedback Hub link)

To be precise about what exists on your side: WER reported the bucket signatures only. All four reports came back with Cab ID: 0 / Cab Guid: 0 and this machine is on Basic (AllowTelemetry=1) diagnostic data, so no cab was ever collected — there is no dump on the backend to pull. The bucket records should still let you see how many other users are landing in the same bucket, which is why I'm including them:

Date Exception Report ID Bucket ID
2026-07-28 c0000005 f8ebcb9e-3354-404a-84c8-8a5b08767f1b 2057686308220423815
2026-07-28 c000041d 82735d47-fe5f-4b5b-9c9f-f863c0267a7e 1790230109502622945
2026-06-30 c0000005 972a8989-2f41-439e-995c-a9be66e623d5
2026-06-30 c000041d 482c68fb-d8be-41ba-8c1b-7e9e50a334d3

Still reachable in main (checked 2026-07-28)

The call site has no guard for an empty _interactivity:

  • src/cascadia/TerminalControl/TermControl.h:252 — the member is declared with null as its default:
    Control::ControlInteractivity _interactivity{ nullptr };
    So "empty" is a representable state of this member, not an impossible one.
  • src/cascadia/TerminalControl/TermControl.cpp:272-273 — the converting constructor stores whatever it is handed, with no validation:
    TermControl::TermControl(Control::ControlInteractivity content) :
        _interactivity{ content },
  • src/cascadia/TerminalControl/TermControl.cpp:2017-2042_PointerMovedHandler guards only on _IsClosing(), then calls straight through:
    if (_IsClosing()) { return; }
    ...
    auto suppressFurtherHandling = _interactivity.PointerMoved(...);   // line 2038, unguarded
  • src/cascadia/TerminalControl/TermControl.h:331-340_IsClosing() returns _closing and nothing else, so it cannot stand in for an emptiness check on _interactivity.
  • TermControl::Close() calls _interactivity.Close() (TermControl.cpp:2673) but does not clear the member, so the null observed in the dump is not coming from that path — it is a TermControl whose _interactivity was already empty.

I have not been able to prove which path leaves it empty (detach/reattach and content-process attach are my suspicions), but the dump proves it happens, and the call site is unguarded regardless of how it got there.

Why I don't think this duplicates #19667 / #20433

Adjacent area, but a different failure mode, and the fix that closed them does not touch this path:

I also could not find an existing issue for this signature — searches for _PointerMovedHandler, for a PointerMoved crash, and for INVALID_POINTER_READ + Microsoft.Terminal.Control all came back empty, and none of the currently open PRs that touch TermControl.cpp modify this handler.

Also ruled out

  • GPU / display driver — not a single graphics frame on the faulting stack; it is user32InputHost → XAML input dispatch end to end.
  • OS-level fault — no Kernel-Power 41 / 6008; the machine had 12 days of uptime spanning the crash. Only the Terminal process died.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-TerminalControlIssues pertaining to the terminal control (input, selection, keybindings, mouse interaction, etc.)Issue-BugIt either shouldn't be doing this or needs an investigation.Priority-3A description (P3)Product-TerminalThe new Windows Terminal.Severity-CrashCrashes are real bad news.

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions