Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Windows API の ReadConsoleW の再現テスト

Windows API の ReadConsoleW の再現テスト

Windows API の ReadConsoleW が、1バイト多く書き込む件の再現テストを行います。

<元ネタの情報>
https://stackoverflow.com/questions/11875619/why-is-calling-readconsole-in-a-loop-corrupting-the-stack

<確認環境>
OS : Windows 8.1 (64bit)
開発環境 : MSYS2/MinGW-w64 (64bit) (gcc version 7.1.0 (Rev2, Built by MSYS2 project))

<ソース>
readconsole.c

#include <windows.h>
#include <stdio.h>

#define BUF_NUM 5

int main(void) {
    HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
    wchar_t buf[BUF_NUM];
    DWORD nread;
    int i;

    SetConsoleMode(h, 0);
    printf("sizeof(wchar_t)=%d\n", sizeof(wchar_t));

    for (;;) {
        for (i = 0; i < BUF_NUM; i++) { buf[i] = 0xaaaa; }
        printf("> ");
        ReadConsoleW(h, buf, BUF_NUM, &nread, NULL);
        printf("nread=%d  buf=[", nread);
        for (i = 0; i < BUF_NUM; i++) { printf("0x%04x ", buf[i]); }
        printf("]\n");
        Sleep(3000);
    }

    return 0;
}

<コンパイル>
gcc -g -O2 -o readconsole.exe readconsole.c

<実行>
readconsole.exe を実行する。
1234512345 を素早く入力する。

<結果>

sizeof(wchar_t)=2
> nread=1  buf=[0x0031 0xaaaa 0xaaaa 0xaaaa 0xaaaa ]
> nread=2  buf=[0x0032 0x0033 0xaa34 0xaaaa 0xaaaa ]
> nread=2  buf=[0x0032 0x0033 0xaaaa 0xaaaa 0xaaaa ]
>

nread が 2 なのに 3 要素目の下位バイトにもデータが書き込まれる現象が見られた。
(すなわち、1バイト多く書きこむ現象が見られた)
また、入力の取りこぼしが見られた。
バッファオーバーフロー( buf[BUF_NUM] 以後に書き込むこと)は見られなかった。

<その他>

  • SetConsoleMode(h, 0) をコメントアウトすると、行バッファリングが有効になって、
    問題は見られなくなった。(このときは、Enterキーを押すまでは入力が確定しない)

  • Sleep(3000) をコメントアウトすると、問題は見られなくなった。
    (頻度が減っているだけかもしれない。元ネタの情報でも、
    プログラムの処理速度によって頻度が変わるようなことが書かれている)

  • BUF_NUM を1から5まで変えてみると、
    1バイト多く書き込む現象は どれでも見られた。
    入力の取りこぼしは、BUF_NUM が2以上のときに見られた。
    バッファオーバーフロー( buf[BUF_NUM] 以後に書き込むこと)は見られなかった。

(2017-9-6)(2017-9-11)(2017-9-14)(2017-9-17)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.