propget cause heap failure

Answered propget cause heap failure

  • mercredi 7 mars 2012 03:01
     
     

    Hi Guys,

    I was using a COM to provide some date for MFC/Console app. But encounter some propget heap failure.

    Following is the scenario:

    1. Define the propget method

    HRESULT m_ProcessName([out, string, retval] OLECHAR** pVal);

    Body:

    STDMETHODIMP CExProcessInfo::get_m_ProcessName(OLECHAR** pVal)
    {
     // TODO: Add your implementation code here
     if(m_pProcessName == NULL)
      *pVal = (OLECHAR*)::SysAllocString(L"");
     else
      *pVal = (OLECHAR*)::SysAllocString(m_pProcessName);
     return S_OK;
    }

    2. Call the method on client:

      WCHAR* pProcName = new WCHAR[MAX_PATH]; 

      pep[i]->get_m_ProcessName(&pProcName);

    In console application, this call can be executed well and return the right value. But when i call this fucntion in MFC OnInitDialog(), it will fail and prompt a assert.

    When i debug into the code, i've got the following failure info:

    !heap -s -v

    Details:==============================

    Error address: 0041185c
    Heap handle: 003a0000
    Error type heap_failure_invalid_argument (9)
    Stack trace:
                    772cddff: ntdll!RtlFreeHeap+0x00000064
                    75ad6e6a: ole32!CRetailMalloc_Free+0x0000001c
                    75ad6f54: ole32!CoTaskMemFree+0x00000013
                    758e154c: RPCRT4!NdrFreeTypeMemory+0x00000046
                    758d24a9: RPCRT4!NdrPointerFree+0x000000a8
                    7594555e: RPCRT4!NdrpFreeParams+0x00000145
                    75945445: RPCRT4!NdrStubCall2+0x000004e0
                    75bbaec1: ole32!CStdStubBuffer_Invoke+0x0000003c
                    75bbd876: ole32!SyncStubInvoke+0x0000003c
                    75bbddd0: ole32!StubInvoke+0x000000b9
                    75ad8a43: ole32!CCtxComChnl::ContextInvoke+0x000000fa
                    75ad8938: ole32!MTAInvoke+0x0000001a
                    75bba44c: ole32!AppInvoke+0x000000ab
                    75bbdb41: ole32!ComInvokeWithLockAndIPID+0x00000372
                    75bbe1fd: ole32!ComInvoke+0x000000c5
                    75ad9367: ole32!ThreadDispatch+0x00000023
    NtGlobalFlag enables following debugging aids for new heaps:    tail checking
        free checking
        validate parameters
    Index   Address  Name      Debugging options enabled
      1:   003a0000                 tail checking free checking validate parameters
      2:   00010000                 tail checking free checking validate parameters
      3:   00670000                 tail checking free checking validate parameters
      4:   00650000                 tail checking free checking validate parameters
      5:   005f0000                 tail checking free checking validate parameters
      6:   02500000                 tail checking free checking validate parameters
      7:   024d0000                 tail checking free checking validate parameters
      8:   03e30000                 tail checking free checking validate parameters
      9:   03d60000                 tail checking free checking validate parameters
     10:   024f0000                 tail checking free checking validate parameters

    And the !analyze -v ====================================

    FAULTING_IP:
    ntdll!RtlReportCriticalFailure+29
    773137dd cc              int     3

    EXCEPTION_RECORD:  ffffffff -- (.exr 0xffffffffffffffff)
    ExceptionAddress: 773137dd (ntdll!RtlReportCriticalFailure+0x00000029)
       ExceptionCode: 80000003 (Break instruction exception)
      ExceptionFlags: 00000000
    NumberParameters: 3
       Parameter[0]: 00000000
       Parameter[1]: 84d79d48
       Parameter[2]: 056cee5d

    FAULTING_THREAD:  00000be4

    PROCESS_NAME:  TestCOMListView.exe

    ERROR_CODE: (NTSTATUS) 0x80000003 - {EXCEPTION}  Breakpoint  A breakpoint has been reached.

    EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - One or more arguments are invalid

    EXCEPTION_PARAMETER1:  00000000

    EXCEPTION_PARAMETER2:  84d79d48

    EXCEPTION_PARAMETER3:  056cee5d

    MOD_LIST: <ANALYSIS/>

    NTGLOBALFLAG:  70

    APPLICATION_VERIFIER_FLAGS:  0

    LAST_CONTROL_TRANSFER:  from 7731473b to 773137dd

    DEFAULT_BUCKET_ID:  ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument

    PRIMARY_PROBLEM_CLASS:  ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument

    BUGCHECK_STR:  APPLICATION_FAULT_ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument

    STACK_TEXT: 
    056cf128 7731473b c0000374 7732cdd8 056cf16c ntdll!RtlReportCriticalFailure+0x29
    056cf138 7731481b 00000002 723f5340 00000000 ntdll!RtlpReportHeapFailure+0x21
    056cf16c 772cddff 00000009 003a0000 0041185c ntdll!RtlpLogHeapFailure+0xa1
    056cf19c 75ad6e6a 003a0000 00000000 0041185c ntdll!RtlFreeHeap+0x64
    056cf1b0 75ad6f54 75bc66bc 0041185c 056cf1dc ole32!CRetailMalloc_Free+0x1c
    056cf1c0 758e154c 0041185c 758d24d3 637733e8 ole32!CoTaskMemFree+0x13
    056cf1c8 758d24d3 637733e8 637733ec 056cf24c RPCRT4!NdrFreeTypeMemory+0x46
    056cf1dc 758d24a9 0041185c 0041185c 637733ec RPCRT4!NdrPointerFree+0xf3
    056cf1fc 7594555e 0041185c 056cf428 007733e8 RPCRT4!NdrPointerFree+0xa8
    056cf220 75945445 056cf428 00000002 6377318a RPCRT4!NdrpFreeParams+0x145
    056cf234 759453ff e1818bfa 00412560 0040f100 RPCRT4!NdrStubCall2+0x4e0
    056cf630 75bbaec1 00412560 00402fa8 0040f100 RPCRT4!NdrStubCall2+0x415
    056cf678 75bbd876 00412560 0040f100 00402fa8 ole32!CStdStubBuffer_Invoke+0x3c
    056cf6c0 75bbddd0 0040f100 0041325c 00411a48 ole32!SyncStubInvoke+0x3c
    056cf70c 75ad8a43 0040f100 00412160 00412560 ole32!StubInvoke+0xb9
    056cf7e8 75ad8938 00402fa8 00000000 00412560 ole32!CCtxComChnl::ContextInvoke+0xfa
    056cf804 75bba44c 0040f100 00000001 00412560 ole32!MTAInvoke+0x1a
    056cf834 75bbdb41 d0908070 00402fa8 00412560 ole32!AppInvoke+0xab
    056cf914 75bbe1fd 0040f0a8 00403b78 00000000 ole32!ComInvokeWithLockAndIPID+0x372
    056cf93c 75ad9367 0040f0a8 76fdc2b0 0040f258 ole32!ComInvoke+0xc5
    056cf950 75aacd48 0040f0a8 00000000 0040f258 ole32!ThreadDispatch+0x23
    056cf96c 75aad87a 00000000 00000000 056cf988 ole32!CRpcThread::WorkerLoop+0x26
    056cf97c 76fded6c 0040f258 056cf9c8 772b377b ole32!CRpcThreadCache::RpcWorkerThreadEntry+0x16
    056cf988 772b377b 0040f258 723f5be4 00000000 kernel32!BaseThreadInitThunk+0xe
    056cf9c8 772b374e 75aad864 0040f258 00000000 ntdll!__RtlUserThreadStart+0x70
    056cf9e0 00000000 75aad864 0040f258 00000000 ntdll!_RtlUserThreadStart+0x1b


    STACK_COMMAND:  .cxr 00000000 ; kb ; !heap ; dt ntdll!LdrpLastDllInitializer BaseDllName ; dt ntdll!LdrpFailureData ; ~7s ; kb

    FOLLOWUP_IP:
    RPCRT4!NdrFreeTypeMemory+46
    758e154c c3              ret

    SYMBOL_STACK_INDEX:  6

    SYMBOL_NAME:  rpcrt4!NdrFreeTypeMemory+46

    FOLLOWUP_NAME:  MachineOwner

    MODULE_NAME: RPCRT4

    IMAGE_NAME:  RPCRT4.dll

    DEBUG_FLR_IMAGE_TIMESTAMP:  4ce7b9a2

    FAILURE_BUCKET_ID:  ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument_80000003_RPCRT4.dll!NdrFreeTypeMemory

    BUCKET_ID:  APPLICATION_FAULT_ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument_rpcrt4!NdrFreeTypeMemory+46

    WATSON_STAGEONE_URL:  http://watson.microsoft.com/StageOne/TestCOMListView_exe/1_0_0_1/4f56cbbc/ntdll_dll/6_1_7601_17725/4ec49b60/80000003/000c37dd.htm?Retriage=1

    Followup: MachineOwner
    ---------

    Call stack=================================

    0:007> k
    ChildEBP RetAddr 
    056cf128 7731473b ntdll!RtlReportCriticalFailure+0x29
    056cf138 7731481b ntdll!RtlpReportHeapFailure+0x21
    056cf16c 772cddff ntdll!RtlpLogHeapFailure+0xa1
    056cf19c 75ad6e6a ntdll!RtlFreeHeap+0x64
    056cf1b0 75ad6f54 ole32!CRetailMalloc_Free+0x1c
    056cf1c0 758e154c ole32!CoTaskMemFree+0x13
    056cf1c8 758d24d3 RPCRT4!NdrFreeTypeMemory+0x46
    056cf1dc 758d24a9 RPCRT4!NdrPointerFree+0xf3
    056cf1fc 7594555e RPCRT4!NdrPointerFree+0xa8
    056cf220 75945445 RPCRT4!NdrpFreeParams+0x145
    056cf234 759453ff RPCRT4!NdrStubCall2+0x4e0
    056cf630 75bbaec1 RPCRT4!NdrStubCall2+0x415
    056cf678 75bbd876 ole32!CStdStubBuffer_Invoke+0x3c
    056cf6c0 75bbddd0 ole32!SyncStubInvoke+0x3c
    056cf70c 75ad8a43 ole32!StubInvoke+0xb9
    056cf7e8 75ad8938 ole32!CCtxComChnl::ContextInvoke+0xfa
    056cf804 75bba44c ole32!MTAInvoke+0x1a
    056cf834 75bbdb41 ole32!AppInvoke+0xab
    056cf914 75bbe1fd ole32!ComInvokeWithLockAndIPID+0x372
    056cf93c 75ad9367 ole32!ComInvoke+0xc5
    056cf950 75aacd48 ole32!ThreadDispatch+0x23
    056cf96c 75aad87a ole32!CRpcThread::WorkerLoop+0x26
    056cf97c 76fded6c ole32!CRpcThreadCache::RpcWorkerThreadEntry+0x16
    056cf988 772b377b kernel32!BaseThreadInitThunk+0xe
    056cf9c8 772b374e ntdll!__RtlUserThreadStart+0x70
    056cf9e0 00000000 ntdll!_RtlUserThreadStart+0x1b

Toutes les réponses

  • mercredi 7 mars 2012 03:12
     
     

    On 3/6/2012 10:01 PM, Woody Chen wrote:

    STDMETHODIMP CExProcessInfo::get_m_ProcessName(OLECHAR** pVal)
    {
      // TODO: Add your implementation code here
      if(m_pProcessName == NULL)
       *pVal = (OLECHAR*)::SysAllocString(L"");

    OLECHAR* is not supposed to be allocated with SysAllocString (that would be BSTR), but with CoTaskMemAlloc.

    2. Call the method on client:

       WCHAR* pProcName = new WCHAR[MAX_PATH];
       pep[i]->get_m_ProcessName(&pProcName);

    pProcName gets overwritten by the method. You are leaking the block of memory you have (pointlessly) allocated.

    When i debug into the code, i've got the following failure info:

    /Error address: 0041185c/
    /Heap handle: 003a0000/
    /Error type heap_failure_invalid_argument (9)/
    /Stack trace:/
    /                772cddff: ntdll!RtlFreeHeap+0x00000064/
    /                75ad6e6a: ole32!CRetailMalloc_Free+0x0000001c/
    /                75ad6f54: ole32!CoTaskMemFree+0x00000013/

    Note the memory being freed with CoTaskMemFree, not with SysFreeString.


    Igor Tandetnik

  • mercredi 7 mars 2012 03:35
     
     

    On 3/6/2012 10:01 PM, Woody Chen wrote:

    STDMETHODIMP CExProcessInfo::get_m_ProcessName(OLECHAR** pVal)
    {
      // TODO: Add your implementation code here
      if(m_pProcessName == NULL)
       *pVal = (OLECHAR*)::SysAllocString(L"");

    OLECHAR* is not supposed to be allocated with SysAllocString (that would be BSTR), but with CoTaskMemAlloc.

    2. Call the method on client:

       WCHAR* pProcName = new WCHAR[MAX_PATH];
       pep[i]->get_m_ProcessName(&pProcName);

    pProcName gets overwritten by the method. You are leaking the block of memory you have (pointlessly) allocated.

    When i debug into the code, i've got the following failure info:

    /Error address: 0041185c/
    /Heap handle: 003a0000/
    /Error type heap_failure_invalid_argument (9)/
    /Stack trace:/
    /                772cddff: ntdll!RtlFreeHeap+0x00000064/
    /                75ad6e6a: ole32!CRetailMalloc_Free+0x0000001c/
    /                75ad6f54: ole32!CoTaskMemFree+0x00000013/

    Note the memory being freed with CoTaskMemFree, not with SysFreeString.


    Igor Tandetnik


    Thx Igor for the quick response. but why this code works well on console app?

    Another thing is , can this works if i use wmemcpy?(I am trying, but somehow the copy failed due to the length issue). Or what usually people do in case of this kind of OLECHAR copy?

  • mercredi 7 mars 2012 05:58
     
     

    Woody Chen wrote:

    Thx Igor for the quick response. but why this code works well on  console app?

    In one case, the threading model of the component matches that of the  calling thread, so you are making a direct call. The bug in the server  whereby it allocates the memory incorrectly, is masked by a matching bug  in the client whereby it frees the same memory incorrectly (or not at  all).

    In the other case, threading models don't match, so marshalling is  performed. Naturally, the marshalling code in the COM runtime does it by  the book, exposing the server bug.

    Another thing is , can this works if i use wmemcpy?

    wmemcpy from which buffer to which other buffer? wmemcpy doesn't  allocate memory; I don't see how it is relevant to the issue at hand.

    Or what usually people do in case of this kind of OLECHAR copy?

    wmemcpy would work for setting the contents of the memory buffer. But  first, the buffer needs to be allocated correctly.


    Igor Tandetnik

  • jeudi 8 mars 2012 02:23
     
     Traitée

    Woody Chen wrote:

    Thx Igor for the quick response. but why this code works well on  console app?

    In one case, the threading model of the component matches that of the  calling thread, so you are making a direct call. The bug in the server  whereby it allocates the memory incorrectly, is masked by a matching bug  in the client whereby it frees the same memory incorrectly (or not at  all).

    In the other case, threading models don't match, so marshalling is  performed. Naturally, the marshalling code in the COM runtime does it by  the book, exposing the server bug.

    Another thing is , can this works if i use wmemcpy?

    wmemcpy from which buffer to which other buffer? wmemcpy doesn't  allocate memory; I don't see how it is relevant to the issue at hand.

    Or what usually people do in case of this kind of OLECHAR copy?

    wmemcpy would work for setting the contents of the memory buffer. But  first, the buffer needs to be allocated correctly.


    Igor Tandetnik

    i've tried :

    new, CoTaskMemAlloc+wmemcpy, SysAllocString+wmemcpy.....

    still not working...

    ========================================

    Finally, the issue resolve when i change the parameter to BSTR*

    ===>STDMETHODIMP CExProcessInfo::get_m_ProcessName(BSTR* pVal)

    this can resolve that issue, but not sure why???  the method body still

     *pVal = (OLECHAR*)::SysAllocString(m_pProcessName);

    • Modifié Woody Chen jeudi 8 mars 2012 02:46 Update
    • Marqué comme réponse Woody Chen vendredi 9 mars 2012 02:30
    •  
  • jeudi 8 mars 2012 02:35
     
     

    On 3/7/2012 9:23 PM, Woody Chen wrote:

    i've tried :

    new, CoTaskMemAlloc+wmemcpy, SysAllocString+wmemcpy.....

    CoTaskMemAlloc is the right way.

    still not working...

    You are doing something wrong.


    Igor Tandetnik