[PATCH] kernel32: return copy of environment blockinGetEnvironmentStringsW

Peter Beutner p.beutner at gmx.net
Thu Apr 5 07:47:45 CDT 2007


Alexandre Julliard schrieb:
> "Dmitry Timoshkov" <dmitry at codeweavers.com> writes:
> 
>> "Peter Beutner" <p.beutner at gmx.net> wrote:
>>> @@ -148,6 +148,10 @@ LPWSTR WINAPI GetEnvironmentStringsW(void)
>>>  */
>>> BOOL WINAPI FreeEnvironmentStringsA( LPSTR ptr )
>>> {
>>> +    /* broken app passes ptr it got from GetEnvironmentStringsW */
>>> +    if(ptr == NtCurrentTeb()->Peb->ProcessParameters->Environment)
>>> +        return TRUE;
>>> +
>>>     return HeapFree( GetProcessHeap(), 0, ptr );
>>> }
>> Personally I think that adding an exception handler or probably just a more
>> strict consistency check inside of RtlFreeHeap should be better.
> 
> An exception handler is probably too slow, but yes RtlFreeHeap should
> have noticed that this block isn't part of the heap. Try something
> like this:
> 
> diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
> index 80ddaf2..61b25db 100644
> --- a/dlls/ntdll/heap.c
> +++ b/dlls/ntdll/heap.c
> @@ -395,7 +395,8 @@ static SUBHEAP *HEAP_FindSubHeap(
>      while (sub)
>      {
>          if (((const char *)ptr >= (const char *)sub) &&
> -            ((const char *)ptr < (const char *)sub + sub->size)) return (SUBHEAP*)sub;
> +            ((const char *)ptr < (const char *)sub + sub->size - sizeof(ARENA_INUSE)))
> +            return (SUBHEAP *)sub;
>          sub = sub->next;
>      }
>      return NULL;
> @@ -783,7 +784,7 @@ static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, SIZE_T size,
>   *
>   * Check that the pointer is inside the range possible for arenas.
>   */
> -static BOOL HEAP_IsValidArenaPtr( const HEAP *heap, const void *ptr )
> +static BOOL HEAP_IsValidArenaPtr( const HEAP *heap, const ARENA_FREE *ptr )
>  {
>      int i;
>      const SUBHEAP *subheap = HEAP_FindSubHeap( heap, ptr );
> @@ -1003,13 +1004,12 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr,   /* [in] ptr to the heap */
>      if (!(flags & HEAP_NO_SERIALIZE))
>          RtlEnterCriticalSection( &heapPtr->critSection );
>  
> -    if (block)
> +    if (block)  /* only check this single memory block */
>      {
> -        /* Only check this single memory block */
> +        const ARENA_INUSE *arena = (const ARENA_INUSE *)block - 1;
>  
> -        if (!(subheap = HEAP_FindSubHeap( heapPtr, block )) ||
> -            ((const char *)block < (char *)subheap + subheap->headerSize
> -                                   + sizeof(ARENA_INUSE)))
> +        if (!(subheap = HEAP_FindSubHeap( heapPtr, arena )) ||
> +            ((const char *)arena < (char *)subheap + subheap->headerSize))
>          {
>              if (quiet == NOISY)
>                  ERR("Heap %p: block %p is not inside heap\n", heapPtr, block );
> @@ -1017,7 +1017,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr,   /* [in] ptr to the heap */
>                  WARN("Heap %p: block %p is not inside heap\n", heapPtr, block );
>              ret = FALSE;
>          } else
> -            ret = HEAP_ValidateInUseArena( subheap, (const ARENA_INUSE *)block - 1, quiet );
> +            ret = HEAP_ValidateInUseArena( subheap, arena, quiet );
>  
>          if (!(flags & HEAP_NO_SERIALIZE))
>              RtlLeaveCriticalSection( &heapPtr->critSection );
> 

Yes that works. It doesn't crash anymore. Thx for looking into this.



More information about the wine-devel mailing list