0

アプリケーションは、名前付きパイプのリストをナビゲートし、アプリケーションによって作成された名前付きパイプを探します。

名前付きパイプが存在しない場合は、先に進んで作成します。しかし、最近私たちのクライアントは報告しています

アプリケーションが行でクラッシュします:

fileName = std::wstring(TmpInfo->FileName);

以下に添付されているwindbgクラッシュダンプレポートを確認できます。クラッシュは散発的であり、常に再現できるわけではありません。問題を特定するのを手伝ってもらえますか?への変換TmpInfo->FileNameに問題がありますかwstring。このコンポーネントはActiveXコントロールであることに注意してください。ActiveXが他のアプリケーションをクラッシュさせています。

次のコードは、名前付きパイプの列挙を担当します。

typedef struct {
        ULONG                   NextEntryOffset;
        ULONG                   FileIndex;
        ULONG                   FileNameLength;
        WCHAR                   FileName[1];    
    } FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;


inline void EnumerateRunningPipes(std::vector<std::wstring>& pipeNames, std::wstring stringLookup,      

                                     bool useStringLookup, bool 

truncatePipeDirPrefix)
    {
        LONG ntStatus;   
        IO_STATUS_BLOCK IoStatus;       
        BOOL bReset = TRUE;       
        PFILE_NAMES_INFORMATION fileNameInfo, TmpInfo;              

        fileNameInfo = (PFILE_NAMES_INFORMATION) new BYTE[1024];

        HANDLE hPipe = CreateFile("//./pipe/", 
            GENERIC_READ,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            NULL,
            OPEN_EXISTING,
            0,
            NULL);

        if(hPipe == INVALID_HANDLE_VALUE)
            throw CEnumeratePipeException("Could not get handle to root directory for pipes.",
            CEnumeratePipeException::ErrorType::CREATE_FILE, GetLastError());       

        USES_CONVERSION;

        locale loc;
        mbstate_t state = {0};

        while(true)
        {
            memset(fileNameInfo, 0, 1024);
            ntStatus = NtQueryDirectoryFile( hPipe, NULL, NULL, NULL, &IoStatus, fileNameInfo, 

1024,
                FileNameInformation, FALSE, NULL, bReset );

            if (ntStatus!=NO_ERROR)   
            {   
                if (ntStatus == STATUS_NO_MORE_FILES)                       


                    break;              

                std::stringstream sstream;      
                sstream << "NtQueryDirectoryFile error " << ntStatus;

                logger->writeLog(sstream.str()); 
                throw CEnumeratePipeException(
                    "NtQueryDirectoryFile could not get information about the directory or 

file.", 
                    CEnumeratePipeException::ErrorType::QUERY_DIR, ntStatus);
            }   

            TmpInfo = fileNameInfo;                         

            while(true)   
            {           
                const int endStringAt = TmpInfo->FileNameLength / sizeof(WCHAR);        



                std::wstring fileName;

                try
                {                                       
                    fileName = std::wstring(TmpInfo->FileName);//The access violation 

occurs at this line of code.
                    fileName = fileName.substr(0, endStringAt);
                }
                catch (...)
                {
                    logger->writeLog("Caught unknown exception.");

                    if (TmpInfo->FileName == NULL)
                    {
                        logger->writeLog("TmpInfo->FileName = NULL");           


                    }                   
                }

                if (useStringLookup)
                {               
                    if (fileName.find(stringLookup) != std::wstring::npos)
                    {       
                        if (!truncatePipeDirPrefix)
                            fileName.insert(0, L"\\\\.\\pipe\\");
                        pipeNames.push_back(fileName);  
                    }   
                }
                else
                {
                    pipeNames.push_back(fileName);
                }

                if(TmpInfo->NextEntryOffset==0)
                    break;   

                TmpInfo = (PFILE_NAMES_INFORMATION)((DWORD)TmpInfo+TmpInfo->NextEntryOffset);
            }   

            bReset = FALSE;
        }   

        delete fileNameInfo;
    }

クラッシュダンプレポートの一部は次のとおりです。

FAULTING_IP:
msvcr100!memcpy + 57 [f:\ dd \ vctools \ crt_bld \ SELF_X86 \ crt \ src \ INTEL \ memcpy.asm @ 185]
78aa1ed7 f3a5 rep movs dword ptr es:[edi]、dword ptr [esi]

EXCEPTION_RECORD:ffffffff-(.exr 0xffffffffffffffff)
ExceptionAddress:78aa1ed7(msvcr100!memcpy + 0x00000057)
ExceptionCode:c0000005(アクセス違反)
ExceptionFlags:00000000
NumberParameters:2
パラメータ[0]:00000000
パラメータ[1]:0d6b8000
アドレス0d6b8000からの読み取りを試みます

SYMBOL_STACK_INDEX:0

SYMBOL_NAME:msvcr100!memcpy + 57

FOLLOWUP_NAME:MachineOwner

MODULE_NAME:msvcr100

IMAGE_NAME:msvcr100.dll

DEBUG_FLR_IMAGE_TIMESTAMP:4ba1dbbe

FAILURE_BUCKET_ID:STRING_DEREFERENCE_c0000005_msvcr100.dll!memcpy

BUCKET_ID:

APPLICATION_FAULT_STRING_DEREFERENCE_CODE_ADDRESS_MISMATCH_INVALID_POINTER_READ_WRONG_SYMBOLS_msvcr100!memcpy

+57

4

2 に答える 2

2

FILE_NAMES_INFORMATIONドキュメントには、FileNameメンバーが null で終了しているという記述はありません。また、メンバーの存在は、FileNameLengthそれが null で終了していないことを示唆しています。

だからその可能性が高いと思われる

fileName = std::wstring(TmpInfo->FileName);

TmpInfo2 つの連続したヌル バイトが検出されるまで、バッファの末尾から読み取っています。読み取り不能な仮想メモリ領域に到達する前に null バイトが検出されない場合は、アクセス違反が発生します。

次の 2 行のコードを置き換えることをお勧めします。

fileName = std::wstring(TmpInfo->FileName);
fileName = fileName.substr(0, endStringAt);

これとともに:

fileName = std::wstring(TmpInfo->FileName, TmpInfo->FileNameLength);

そのコンストラクターはバッファーから文字のみを読み取るFileNameLengthため、クラッシュすることはありません。そして、それはより効率的です!

于 2012-05-14T14:22:14.000 に答える
1

TmpInfo と TmpInfo->FileName はどのように定義されていますか? クラッシュ時の TmpInfo->FileName の値の例はありますか?

私の推測では、場合によっては null で終了していないため、std::wstringのコンストラクターがそれに属さないメモリに読み込まれる可能性があります。

于 2012-05-14T14:20:37.770 に答える