[PATCH] winhttp: Process end of read data before sending callback in read_data().

Hans Leidekker hans at codeweavers.com
Fri Oct 15 05:04:18 CDT 2021


On Thu, 2021-10-14 at 18:17 +0300, Paul Gofman wrote:
> Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
> ---
>     The read completion callback may call WineHttpReadData(). Which may either run
>     synchronously (if the data is available and recursion depth limit is not reached)
>     or queued to thread pool. Fallout76 always proceeds with last WinHttpReadData of
>     size 0 with recursion limit reached, and finished_reading() is racing between the
>     (synchronous) call which has read the last portion of data and the queued
>     WinHttpReadData called with zero size sometimes causing a crash in cache_connection
>     which may be called with NULL connection in this case.
> 
>  dlls/winhttp/request.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
> index 2c064bb767b..a9c65d15fa8 100644
> --- a/dlls/winhttp/request.c
> +++ b/dlls/winhttp/request.c
> @@ -1850,6 +1850,7 @@ static DWORD read_data( struct request *request, void *buffer, DWORD size, DWORD
>  
> 
>  done:
>      TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, request->content_read, request->content_length );
> +    if (end_of_read_data( request )) finished_reading( request );
>      if (async)
>      {
>          if (!ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read );
> @@ -1863,7 +1864,6 @@ done:
>      }
>  
> 
>      if (!ret && read) *read = bytes_read;
> -    if (end_of_read_data( request )) finished_reading( request );
>      return ret;
>  }

This could use a test because it changes the order of notifications.
When finished_reading() closes the connection
WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION will now be sent before
WINHTTP_CALLBACK_STATUS_READ_COMPLETE.





More information about the wine-devel mailing list