none
確定前の文字列がある状態でテキストボックスのフォーカス移動でバグ RRS feed

  • 質問


  • 質問掲示板「わんくま同盟」にて論議しましたが、MS-IME か .NET Frameworkの
    バグである可能性が高いとの結論になりましたので、こちらのフォームで
    再問合せいたします。

    表題事象についてバグもしくは仕様となりますでしょうか?


    【発生環境】
    Windows Form アプリケーション
    Windows 10 1809,1903 (32,64bit)
    VB2010(Framework3.5), VB.NET 2015, VB.NET 2017(Framework4.7),VS2019Pro

    【再現方法】
    テキストボックス2つを MS-IME の候補ウインドウの大きさより離して横に配置
    片方に「あいう」と入力しもう一つをマウスクリックすると候補ウインドウが移動
    Enter で確定すると FormClosing / FormClosed ハンドラが呼ばれることなく異常終了。

    【わかっていること】
    終了コードは 0x4000001f STATUS_WX86_BREAKPOINT ということだったのでネイティブコードデバッグを有効化
    0x00200001 で例外がスローされました (Form1.exe 内): 0xC0000005: 場所 0x00200001 の実行中にアクセス違反が発生しました
    0xC0000005 は変化しないけど場所は毎回変わる様子

    ※わんくま同盟 WebSurfer様、774RR様、魔界の仮面弁士様 調査・テストのご協力いただきありがとうございます。


    2019年9月30日 5:12

回答

  • 田中A さま よろしく。

    MS-IME か .NET Frameworkのバグである可能性が高いとの結論、
    であるならば、 ここに書き込むよりも、
    英文にて、 Visual Studio IDE の フィードバック(問題報告) から、
    https://developercommunity.visualstudio.com に問題を挙げる方が確実な気がします。

    • 編集済み ShiroYuki_Mot 2019年9月30日 9:40 VS の文言追加
    • 回答としてマーク 田中A 2019年9月30日 14:42
    2019年9月30日 9:39
  • MSDN フォーラムは基本的にユーザー同士の情報交換フォーラムです。
    そういう意味ではわんくまさんのところと近いです。
    (時々、フォーラムオペレーターが一部だけ、エンジニアと情報のやりとりをしてくれることもありますが、それは保証されていることではないので、例外的な対応になります)

    Developer Community は不具合や要望を報告する場所になります。
    こちらも「サポートサービス」ではないので、「不具合なのか?仕様なのか?」という質問に対して答える場所ではありません。
    フォーラムと違って、エンジニアが調査はしてくれ、何らかの反応はあります。
    ただし、基本的に英語です。

    Microsoft の公式見解が欲しい…といった主旨となると、有償のサポートサービスを使うことになります。
    ただ、プロフェッショナルサポートはあんまり頑張ってくれない事例が増えているそうなので、悩ましいですね…。

    • 回答としてマーク 田中A 2019年10月1日 14:47
    2019年9月30日 21:14
    モデレータ
  • 現状の材料は...

    • Win10 1809,1903 など複数のビルドで再現する
    • 質問者のみでなく、回答側の何人かの環境でも再現するので環境固有ではなさそう(私もさっき試したら起きました)
    • (私が試す限り) ATOK では起きず、MSIME では起きる
    • 呼び出し履歴を見ると msctf.dll の内部処理で関数が何段か呼ばれた後、call esi のところで Access Violation
    • 今のところ、非 .NET アプリで起こせるケースが見つかっていない&(私が試す限り)WPF アプリでは起きない
    • (私が試す限り)RichTextBox でも起きない。
    • (私が試す限り)起きるケースはフォーカス移動でも変換中状態が継続し、起きないケースではフォーカス移動で変換状態が確定している
    • 互換モードを Windows 8 にすると起きない?

    Text Service Framework の層の問題の可能性もあるので、.NET Framework or MSIME と限定できるほどの情報はないですね。
    興味がおありでしたら、わんくまさんのスレッド も含めてご参照ください。

    // 私は自宅でそこまで時間取れない&そこまで関心を払っていないので、追求に時間をかけていませんが…。

    • 回答としてマーク 田中A 2019年10月2日 1:25
    2019年10月1日 22:02
    モデレータ

すべての返信

  • わんくま掲示板とマルチポストになってしまっています。わんくまの方はともかく、このフォーラムではマルチポストは遠慮いただくようにと管理者の方から案内が出ています。マルチポストにならないような対応をお願いします。
    2019年9月30日 8:38
  • 田中A さま よろしく。

    MS-IME か .NET Frameworkのバグである可能性が高いとの結論、
    であるならば、 ここに書き込むよりも、
    英文にて、 Visual Studio IDE の フィードバック(問題報告) から、
    https://developercommunity.visualstudio.com に問題を挙げる方が確実な気がします。

    • 編集済み ShiroYuki_Mot 2019年9月30日 9:40 VS の文言追加
    • 回答としてマーク 田中A 2019年9月30日 14:42
    2019年9月30日 9:39

  • ShiroYuki_Mot 様

    ありがとうございます。
    いただいたアドレスのほうで試してみます。

    初めての質問で不慣れなため
    お手数おかけいたして
    すいません。
    2019年9月30日 14:45
  • MSDN フォーラムは基本的にユーザー同士の情報交換フォーラムです。
    そういう意味ではわんくまさんのところと近いです。
    (時々、フォーラムオペレーターが一部だけ、エンジニアと情報のやりとりをしてくれることもありますが、それは保証されていることではないので、例外的な対応になります)

    Developer Community は不具合や要望を報告する場所になります。
    こちらも「サポートサービス」ではないので、「不具合なのか?仕様なのか?」という質問に対して答える場所ではありません。
    フォーラムと違って、エンジニアが調査はしてくれ、何らかの反応はあります。
    ただし、基本的に英語です。

    Microsoft の公式見解が欲しい…といった主旨となると、有償のサポートサービスを使うことになります。
    ただ、プロフェッショナルサポートはあんまり頑張ってくれない事例が増えているそうなので、悩ましいですね…。

    • 回答としてマーク 田中A 2019年10月1日 14:47
    2019年9月30日 21:14
    モデレータ
  • 質問を質問で返すようで、また怒られそうですが。。。

    私だけが理解できていないようなので、どなたか教えていただきたいのですが、「MS-IME か .NET Frameworkのバグである可能性が高いとの結論」に至る理由は何でしょうか?
    私には、【わかっていること】と結論が結びつかない。。。。

    2019年10月1日 0:29
  • Azulean様

    MSDNのフォーラムを誤解しておりました。
    基本の部分から教えていただきありがとうございます。

    基本的な動作部分で発生するため、バグであればMSさんが
    何かしらの形で対応してくれることが良いと考えていましたが
    悩ましいところです。

    根本的な解決策は難しいと考えていますが、回避策はについては、
    わんくま同盟様の掲示板で検討したいと思います。

    まことに勝手ながらこのフォーラムはクローズさせていただきたいと思います。
    MSDNフォーラムの意味を理解しておらずお騒がせいたしました。

    2019年10月1日 14:55
  • 現状の材料は...

    • Win10 1809,1903 など複数のビルドで再現する
    • 質問者のみでなく、回答側の何人かの環境でも再現するので環境固有ではなさそう(私もさっき試したら起きました)
    • (私が試す限り) ATOK では起きず、MSIME では起きる
    • 呼び出し履歴を見ると msctf.dll の内部処理で関数が何段か呼ばれた後、call esi のところで Access Violation
    • 今のところ、非 .NET アプリで起こせるケースが見つかっていない&(私が試す限り)WPF アプリでは起きない
    • (私が試す限り)RichTextBox でも起きない。
    • (私が試す限り)起きるケースはフォーカス移動でも変換中状態が継続し、起きないケースではフォーカス移動で変換状態が確定している
    • 互換モードを Windows 8 にすると起きない?

    Text Service Framework の層の問題の可能性もあるので、.NET Framework or MSIME と限定できるほどの情報はないですね。
    興味がおありでしたら、わんくまさんのスレッド も含めてご参照ください。

    // 私は自宅でそこまで時間取れない&そこまで関心を払っていないので、追求に時間をかけていませんが…。

    • 回答としてマーク 田中A 2019年10月2日 1:25
    2019年10月1日 22:02
    モデレータ
  • Azulean さん

    説明ありがとうございました。
    私は .NET アプリ開発の開発はおろか、開発環境すらインストールしていませんが、面白そうなので時間ができたら勉強がてらでデバッグしてみようと思ってます。
    (もっとも Windows Form App の作成方法から勉強しないといけませんが w)

    > 呼び出し履歴を見ると msctf.dll の内部処理で関数が何段か呼ばれた後、call esi のところで Access Violation

    とりあえずわんくまのスレッドを覗いてみましたが、Azulean さんの環境で再現した状態が、魔界の仮面弁士さんが提示したコールスタックと似たような状況なら、下記箇所からデバッグ トレースしていけば原因箇所を特定できるのでは。。。と思ってます。
    0x00200001
    msctf!CInputContext::_DoEditSession+42531
    msctf!CInputContext::_EditSessionQiCallback+4f

    試しに手元の環境で msctf!CInputContext::_EditSessionQiCallback+4f を確認したら、ntdll!LdrpValidateUserCallTarget へのコールとなっていまいた。

    MSCTF!CInputContext::_EditSessionQiCallback+0x43:
    00007ff9`abd96fa3 488b01          mov     rax,qword ptr [rcx]
    00007ff9`abd96fa6 488b4008        mov     rax,qword ptr [rax+8]
    00007ff9`abd96faa ff1578b70b00    call    qword ptr [MSCTF!_guard_dispatch_icall_fptr (00007ff9`abe52728)]
    00007ff9`abd96fb0 eb00            jmp     MSCTF!CInputContext::_EditSessionQiCallback+0x52 (00007ff9`abd96fb2)  Branch
    
    0:000> dqs 00007ff9`abe52728 l1
    00007ff9`abe52720  00007ff9`ac00fb70 ntdll!LdrpValidateUserCallTarget

    LdrpValidateUserCallTarget は CFG (Control Flow Guard) 処理で利用される API らしいので、もしかしたら CFG でのチェックに引っかかってエラーになったのかも。。。。と推測しています。

    Visual C++ コンパイラには下記 CFG 関連のオプション スイッチがあるので、.NET コンパイラ (?) にも同様の CFG 関連オプションがあるなら、それを変更することで改善できるかも。
    ------------------------------------------
    /guard (Enable Control Flow Guard)
    https://docs.microsoft.com/ja-jp/cpp/build/reference/guard-enable-control-flow-guard?view=vs-2019
    ------------------------------------------

    • 編集済み お馬鹿 2019年10月2日 2:34
    2019年10月2日 2:33
  • CInputContext::_DoEditSession 自体はフォーカス遷移やらキー入力やらでやたら来る場所なのでリモートデバッグで少し見ましたが、普通に NULL 参照の雰囲気はありますね。
    正常時(フォーカス遷移させずに候補確定)は、call esi から CInputContext::RequestEditSession() に飛びますし、esi 取り出すときの eax のメモリの内容は関数のアドレスのようなので、vtable と見て良さそう。

    75A3A642  mov         esi,dword ptr [eax+0Ch]
    ; EAX = 0910D7F0 ESI = 00000000 
    75A3A645  lea         eax,[ebp-1Ch]  
    75A3A648  push        eax  
    75A3A649  push        ebx  
    75A3A64A  lea         eax,[ebp-2Ch]  
    75A3A64D  push        eax  
    75A3A64E  push        edx  
    75A3A64F  push        ecx  
    75A3A650  mov         ecx,esi  
    75A3A652  call        dword ptr [___guard_check_icall_fptr (75AC07CCh)]  
    75A3A658  call        esi  ; Access Violation
    正常時
    75A3A640  mov         eax,dword ptr [ecx]  
    75A3A642  mov         esi,dword ptr [eax+0Ch]  
    ; EAX = 759D2204 ESI = 759F8470
    
    メモリ 0x759D2204
    60 0c a0 75 60 a1 a0 75 20 ab a0 75 70 84 9f 75
    
    0x75a00c60 CInputContext::QueryInterface
    0x75a0a160 CInputContext::AddRef
    0x75a0ab20 CInputContext::Release
    0x759f8470 CInputContext::RequestEditSession

    ※起きるのは x86 プロセスの場合だけらしいので、32bit レジスタの表現になっています。
    ※ダンプ解析ではなく、Visual Studio のネイティブデバッグ&リモートデバッグ。

    2019年10月2日 13:12
    モデレータ
  • 75A3A652  call        dword ptr [___guard_check_icall_fptr (75AC07CCh)]  

    上記の場合の 0x75AC07CC は、どこを指してました?

    たぶん ntdll!LdrpValidateUserCallTarget を指してると思うのですが。

    2019年10月2日 14:04
  • 該当の call を step in したときに飛んでいる先で表示された名前は以下ですね。

    wistd::__function::__func<<lambda_4b29d149b8821cfbae4eba16ce6a2849>,bool __stdcall(void *,unsigned int,void *,unsigned int,unsigned int)>::destroy(void)

    ※セッション立て直したので、具体的なアドレスは変わっているので、シンボルのみ記載。
    ※ step in 先は ret 0 だけですぐに戻りました。

    2019年10月2日 14:58
    モデレータ
  • うーーん。。。Visual Studio でのデバッグはほとんどしないので、なんか期待した情報と違う。。。。
    もし可能でしたら WinDbg Preview をインストールして、下記確認をしてもらえると嬉しいです。
    (WinDbg Preview は Time Travel Debugging ができるのでとっても便利だと思うのですが、あんまり普及していないみたいですね。)

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    <確認してほしいこと>

    1. WinDbg Preview をインストールし起動させたら、問題の発生する該当プロセスにアタッチさせる。
    (WinDbg Preview から直接起動してもいいけど。)

    2. 下記コマンドで、msctf!CInputContext::_EditSessionQiCallback ルーチン内の該当箇所を確認する。
    0:008> uf msctf!CInputContext::_EditSessionQiCallback
    ...
    MSCTF!CInputContext::_EditSessionQiCallback+0x59:
    7683b4d9 8bce            mov     ecx,esi
    7683b4db ff15c8978e76    call    dword ptr [MSCTF!__guard_check_icall_fptr (768e97c8)]
    7683b4e1 ffd6            call    esi
    ...

    3. 下記コマンドで、"MSCTF!__guard_check_icall_fptr" にセットされている実際のコール先を確認する。
    0:008> dds MSCTF!__guard_check_icall_fptr l1
    768e97c8  7684f020 MSCTF!CTipProxy::CEditSession::AddRefServer
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    上記の場合、MSCTF!__guard_check_icall_fptr (0x768e97c8) に登録されているコール先は "MSCTF!CTipProxy::CEditSession::AddRefServer" なので、CFG は無効状態となっていると考えられます。
    問題のケースでは、恐らく MSCTF!__guard_check_icall_fptr には NULL がセットされているのでは。。。。と思い、それを確認してほしかったわけです。
    NULL がセットされていた場合、MSCTF!__guard_check_icall_fptr へのポインタが壊れたか、本当に NULL がセットされていたのかのケースが考えられると思いますが、前者の場合、その前後を確認することで、おおよその判断はできます。

    ---------------------------------------------------------
    0:009> dds MSCTF!__guard_check_icall_fptr l1
    768e97c8  7684f020 MSCTF!CTipProxy::CEditSession::AddRefServer

    0:009> dds MSCTF!__guard_check_icall_fptr l-4
    768e97b8  77580610 ntdll!NtQueryInformationProcess
    768e97bc  77580570 ntdll!NtClose
    768e97c0  775801c0 ntdll!RtlPublishWnfStateData
    768e97c4  00000000

    0:009> dds MSCTF!__guard_check_icall_fptr l4
    768e97c8  7684f020 MSCTF!CTipProxy::CEditSession::AddRefServer
    768e97cc  000ea238
    768e97d0  00000000
    768e97d4  00000000
    ---------------------------------------------------------

    釈迦に説法だとは思いますが。。。。
    比較対象として x64 環境での msctf!CInputContext::_EditSessionQiCallback ルーチンを確認すると、以下のように CFG が機能していることが確認できます。
    -----------------------------------------------------
    0:005> uf msctf!CInputContext::_EditSessionQiCallback
    ...
    MSCTF!CInputContext::_EditSessionQiCallback+0x43:
    00007ff9`abd96fa3 488b01          mov     rax,qword ptr [rcx]
    00007ff9`abd96fa6 488b4008        mov     rax,qword ptr [rax+8]
    00007ff9`abd96faa ff1578b70b00    call    qword ptr [MSCTF!_guard_dispatch_icall_fptr (00007ff9`abe52728)]
    00007ff9`abd96fb0 eb00            jmp     MSCTF!CInputContext::_EditSessionQiCallback+0x52 (00007ff9`abd96fb2)  Branch
    ...
    0:005> dqs MSCTF!_guard_dispatch_icall_fptr l1
    00007ff9`abe52728  00007ff9`ac00fc10 ntdll!LdrpDispatchUserCallTarget
    -----------------------------------------------------
    つまり何が言いたいかというと、今回の問題は msctf モジュール内の CFG チェック対象のルーチン コールで発生しているように見えるので、まずはそれを切り分けた方が良いのでは。。。。ということです。
    もし CFG 処理で発生しているんであれば、コンパイラかリンカの CFG オプションで回避できるのでは。。。というのが私の妄想です。


    • 編集済み お馬鹿 2019年10月3日 3:21
    2019年10月3日 3:18
  • 出先なので一言だけ。C# コンパイラには Control flow guard を制御するオプションはないので、その回避策はなさそうです。
    2019年10月3日 3:32
    モデレータ
  • こんな感じですね。
    正常時・異常時ともに以下の出力ですので、MSCTF!__guard_check_icall_fptr が壊れているという可能性は低いと思っています。
    この call 前後でも esi はおかしいので、普通に開放済みの COM オブジェクトの呼び出しのように思えます。

    0:000> dds MSCTF!__guard_check_icall_fptr l1
    772307cc  7718e560 MSCTF!wistd::__function::__func<<lambda_4b29d149b8821cfbae4eba16ce6a2849>,bool __stdcall(void *,unsigned int,void *,unsigned int,unsigned int)>::destroy

    2019年10月3日 14:58
    モデレータ
  • 一日一往復だともやっとすると思いますので、私が試しているシンプルな .NET WinForms アプリをソースコード込みで置いておきます。
    単にテキストボックス 2 つと説明用ラベルを貼っただけですが、Release ビルドした exe も含めています。
    (ブラウザーによっては警告されてしまいますが…)

    https://azulean.me/crashsample/ ※真ん中にハイパーリンクで zip にリンク。
    https://azulean.me/crashsample_anime/ ※再現手順。右側をクリックした後は Enter 押下


    2019年10月3日 15:08
    モデレータ
  • 私の投稿が AccessViolation を引き起こす call 直前の画像だったので、今回はお馬鹿さんが言われている msctf!CInputContext::_EditSessionQiCallback での +0x59 付近(こちらはバージョンが微妙に違うっぽくずれているので近似箇所)で止めた際の画像も貼り付けておきます。

    ※朝は時間が取れなかったので、観察はしてみたものの、Access Violation を起こす直前の状態確認はできていません。

    0:000> dds MSCTF!__guard_check_icall_fptr l1
    762407cc  7619e560 MSCTF!wistd::__function::__func<<lambda_4b29d149b8821cfbae4eba16ce6a2849>,bool __stdcall(void *,unsigned int,void *,unsigned int,unsigned int)>::destroy

    2019年10月3日 21:55
    モデレータ
  • サンプルの提供ありがとうございます。
    おかげ様で現象を確認することができました。
    (C# は素人以下なので、大変助かりました。)

    今下記☆の2か所に Breakpoint をセットしデバッグ トレースしてみましたが、私が指摘していた CFG は関係なさそうですね。
    適当なことを書いて混乱させてしまい、大変申し訳ありませんでした。
    で。。。
    OK ケースの場合、MSCTF!CInputContext::_DoEditSession+0x425a9 (call dword ptr [MSCTF!__guard_check_icall_fptr]) の処理が実行される以前に esi レジスタには MSCTF!CInputContext::RequestEditSession ルーチンへのアドレスがセットされていましたが、NG ケースの場合はおかしな値がセットされていました。
    以前に Azulean さんが指摘されていたように、esi レジスタにセットする値は MSCTF!CEditSession::`vftable' から引っ張ってきているように見えるので、vftable 関連に問題が潜んでいるようです。
    (ただ NG ケースの場合でも、[ebp-2Ch] 自体は vftable へのアドレスを指しているし、vftable 内のアドレス データも壊れているようには見えないので、オフセット算出時。。。。ということなのかも。)

    -----------------------------------------------------
    MSCTF!CInputContext::_DoEditSession+0x4257e:
    7793a6f7 c745d4503e8d77  mov     dword ptr [ebp-2Ch],offset MSCTF!CEditSession::`vftable'+0x18 (778d3e50)
    7793a6fe 8d477c          lea     eax,[edi+7Ch]
    7793a701 8945d8          mov     dword ptr [ebp-28h],eax
    7793a704 8b450c          mov     eax,dword ptr [ebp+0Ch]
    7793a707 8945dc          mov     dword ptr [ebp-24h],eax
    7793a70a 83e3f7          and     ebx,0FFFFFFF7h
    7793a70d 83cb01          or      ebx,1
    7793a710 8b01            mov     eax,dword ptr [ecx]
    7793a712 8b700c          mov     esi,dword ptr [eax+0Ch]
    7793a715 8d45e4          lea     eax,[ebp-1Ch]
    7793a718 50              push    eax
    7793a719 53              push    ebx
    7793a71a 8d45d4          lea     eax,[ebp-2Ch]
    7793a71d 50              push    eax
    7793a71e 52              push    edx
    7793a71f 51              push    ecx
    7793a720 8bce            mov     ecx,esi
    7793a722 ff15d8079c77    call    dword ptr [MSCTF!__guard_check_icall_fptr (779c07d8)]  ;; ☆
    7793a728 ffd6            call    esi ;; ☆
    7793a72a 85c0            test    eax,eax
    7793a72c 0f89acdafbff    jns     MSCTF!CInputContext::_DoEditSession+0x65 (778f81de)  Branch
    -----------------------------------------------------
    <OK>
    0:000:x86> dds @ebp-2c l1
    004feac0  778d3e50 MSCTF!CEditSession::`vftable'+0x18
    
    0:000:x86> r
    eax=004feac0 ebx=00000003 ecx=778f84c0 edx=00000004 esi=778f84c0 edi=0074f1c8
    eip=7793a728 esp=004fea9c ebp=004feaec iopl=0         nv up ei pl nz na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200206
    MSCTF!CInputContext::_DoEditSession+0x425af:
    7793a728 ffd6            call    esi {MSCTF!CInputContext::RequestEditSession (778f84c0)}
    
    0:000:x86> u 778f84c0 l1
    MSCTF!CInputContext::RequestEditSession:
    778f84c0 8bff            mov     edi,edi
    -----------------------------------------------------
    <NG>
    0:000:x86> dds @ebp-2c l1
    004feac0  778d3e50 MSCTF!CEditSession::`vftable'+0x18
    
    0:000:x86> r
    eax=004feac0 ebx=00000003 ecx=feeefeee edx=00000004 esi=feeefeee edi=09d55ab8
    eip=7793a728 esp=004fea9c ebp=004feaec iopl=0         nv up ei pl nz na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200206
    MSCTF!CInputContext::_DoEditSession+0x425af:
    7793a728 ffd6            call    esi {feeefeee}
    -----------------------------------------------------

    これはなかなか奥が深そう。。。

    追記
    よく見たら、ecx レジスタの値もおかしい。。。
    もしかして、this ポインタを壊している?

    追記するのをすっかり忘れていましたが。。。。
    本件 Microsoft の Bug だそうです。
    ---------------------------------------------
    Windows 10 バージョン 1809 以降の環境において、Microsoft IME による日本語入力中にアプリケーションエラーが発生する
    https://social.msdn.microsoft.com/Forums/ja-JP/1d77d1ed-8995-4bc3-805a-c29276b29108/windows-10-1249612540124721251912531-1809?forum=windowssdksupportteamja
    ---------------------------------------------

    • 編集済み お馬鹿 2020年3月18日 1:02
    2019年10月4日 3:58