0

私のコードは、自分のコンピューターと他のテスト VM では正常に動作しますが、顧客のコンピューターでは動作が未定義です。_tmain の MessageBox で [OK] を押した後、コンパイルされた exe が CPU を 100% 使用し、爆発することがあります。

#include <windows.h>
#include <tchar.h>
#include <strsafe.h>

DWORD GetVS(TCHAR **sGetVS)
{
    DWORD dwSize = 1024;    
    *sGetVS = (TCHAR *) calloc(dwSize,sizeof(TCHAR));

    // Buffer for the environment variable value.
    TCHAR *sBuffEnv = (TCHAR *) calloc(4096+1,sizeof(TCHAR));   
    DWORD dwRet = GetEnvironmentVariable(L"VS90COMNTOOLS", sBuffEnv, 4096);
    if (dwRet)
    {
        StringCchCopy(*sGetVS,_tcslen(sBuffEnv)+1,sBuffEnv);
        MessageBox(0,sBuffEnv,*sGetVS,0);
        _tcslwr_s(*sGetVS,_tcslen(*sGetVS)+1);  // +1 is required for the null char
    }
    free(sBuffEnv);sBuffEnv=NULL;
    return 1;
}

int _tmain(int argc, _TCHAR* argv[])
{
    TCHAR *sTemp = NULL;
    GetVS(&sTemp);
    MessageBox(0,sTemp,L"",0);
    free(sTemp);
    return 0;
}

free最後を削除しようとしましたが、 sTemp=NULL;afterfreeを追加しましたが、同じ問題が発生しています。

ありがとう!

4

1 に答える 1

1

私が見た2つの問題は、どちらもの可能な値の長さを扱っています"VS90COMNTOOLS"

最初GetEnvironmentVariableは正しく使用されていません。渡されたバッファが環境変数値を保持するのに十分な大きさでない場合、の戻り値はGetEnvironmentVariable、ヌルターミネータを含む値を保持するために必要な文字数です。バッファーが十分に大きくないために関数が失敗した場合、コードが想定しているように、戻り値はゼロではありません。戻り値が0(失敗の場合、たとえば見つからない)であるかどうか、または渡されたバッファーのサイズよりも大きい(小さすぎる)かどうかを確認する必要があります。

次に、バッファに4097文字が割り当てられる場所dwSizeに1024文字を割り当てるために使用されます。返される値が1024文字を超える場合、実行時に割り当てられたバッファがオーバーフローし、ヒープが破損してアプリが異常終了します(または任意の数の奇妙なことを実行します)。sGetVSsBuffEnvsBuffEnvsGetVSStringCchCopy

アップデート

環境変数が大きすぎて提供されたバッファーに収まらない場合、からの戻り値GetEnvironmentVariableは、バッファーが変数を保持できるようにするために必要なサイズです。この場合、の内容sBuffEnvは未定義です(変更されない可能性があり、nullターミネータの有無にかかわらず値が切り捨てられる可能性があり、ガベージが含まれる可能性があります...、呼び出し後に何が含まれるかは保証されません)。この場合、を実行するときに不正なデータを使用している可能性がありますStringCchCopy

于 2011-06-02T18:36:17.457 に答える