Browse Source

http: do not continue after HTTP_Free, fix potential buffer overflow

pull/2/head
mittorn 5 years ago
parent
commit
cb0791c915
  1. 43
      engine/common/net_ws.c

43
engine/common/net_ws.c

@ -1803,7 +1803,7 @@ typedef struct httpfile_s
qboolean process; qboolean process;
// query or response // query or response
char buf[BUFSIZ]; char buf[BUFSIZ+1];
int header_size, query_length, bytes_sent; int header_size, query_length, bytes_sent;
} httpfile_t; } httpfile_t;
@ -1865,7 +1865,7 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
file->socket = -1; file->socket = -1;
Q_snprintf( incname, 256, "%s.incomplete", file->path ); Q_snprintf( incname, 256, "downloaded/%s.incomplete", file->path );
if( error ) if( error )
{ {
// Switch to next fastdl server if present // Switch to next fastdl server if present
@ -1891,7 +1891,7 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
// Success, rename and process file // Success, rename and process file
char name[256]; char name[256];
Q_snprintf( name, 256, "%s", file->path ); Q_snprintf( name, 256, "downloaded/%s", file->path );
FS_Rename( incname, name ); FS_Rename( incname, name );
if( file->process ) if( file->process )
@ -1956,14 +1956,21 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
char *begin = 0; char *begin = 0;
int res; int res;
while( ( res = recv( curfile->socket, buf, BUFSIZ, 0 ) ) > 0) // if we got there, we are receiving data if( curfile->header_size >= BUFSIZ )
{
Con_Reportf( S_ERROR "Header to big\n");
HTTP_FreeFile( curfile, true );
return false;
}
while( ( res = recv( curfile->socket, buf, BUFSIZ - curfile->header_size, 0 ) ) > 0) // if we got there, we are receiving data
{ {
curfile->blocktime = 0; curfile->blocktime = 0;
if( curfile->state < HTTP_RESPONSE_RECEIVED ) // Response still not received if( curfile->state < HTTP_RESPONSE_RECEIVED ) // Response still not received
{ {
buf[res] = 0; // string break to search \r\n\r\n
memcpy( curfile->buf + curfile->header_size, buf, res ); memcpy( curfile->buf + curfile->header_size, buf, res );
curfile->buf[curfile->header_size + res] = 0;
begin = Q_strstr( curfile->buf, "\r\n\r\n" ); begin = Q_strstr( curfile->buf, "\r\n\r\n" );
if( begin ) // Got full header if( begin ) // Got full header
@ -1982,7 +1989,7 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
if( begin ) if( begin )
*begin = 0; *begin = 0;
Con_Printf( S_ERROR "bad response: %s\n", curfile->buf ); Con_Printf( S_ERROR "%s: bad response: %s\n", curfile->path, curfile->buf );
HTTP_FreeFile( curfile, true ); HTTP_FreeFile( curfile, true );
return false; return false;
} }
@ -1999,6 +2006,7 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
Con_Reportf( S_WARN "Server reports wrong file size!\n" ); Con_Reportf( S_WARN "Server reports wrong file size!\n" );
curfile->size = size; curfile->size = size;
curfile->header_size = 0;
} }
if( curfile->size == -1 ) if( curfile->size == -1 )
@ -2032,7 +2040,8 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
curfile->downloaded += ret; curfile->downloaded += ret;
} }
} }
curfile->header_size += res; else
curfile->header_size += res;
} }
else if( res > 0 ) else if( res > 0 )
{ {
@ -2107,14 +2116,14 @@ void HTTP_Run( void )
{ {
Con_Printf( S_ERROR "no servers to download %s!\n", curfile->path ); Con_Printf( S_ERROR "no servers to download %s!\n", curfile->path );
HTTP_FreeFile( curfile, true ); HTTP_FreeFile( curfile, true );
continue; break;
} }
Con_Reportf( "HTTP: Starting download %s from %s\n", curfile->path, curfile->server->host ); Con_Reportf( "HTTP: Starting download %s from %s\n", curfile->path, curfile->server->host );
#ifndef XASH_DEDICATED #ifndef XASH_DEDICATED
UI_ConnectionProgress_Download( curfile->path, curfile->server->host, curfile->server->path, curfile->id, http.fileCount, "(starting)"); UI_ConnectionProgress_Download( curfile->path, curfile->server->host, curfile->server->path, curfile->id, http.fileCount, "(starting)");
#endif // XASH_DEDICATED #endif // XASH_DEDICATED
Q_snprintf( name, sizeof( name ), "%s.incomplete", curfile->path ); Q_snprintf( name, sizeof( name ), "downloaded/%s.incomplete", curfile->path );
curfile->file = FS_Open( name, "wb", true ); curfile->file = FS_Open( name, "wb", true );
@ -2122,7 +2131,7 @@ void HTTP_Run( void )
{ {
Con_Printf( S_ERROR "cannot open %s!\n", name ); Con_Printf( S_ERROR "cannot open %s!\n", name );
HTTP_FreeFile( curfile, true ); HTTP_FreeFile( curfile, true );
continue; break;
} }
curfile->state = HTTP_OPENED; curfile->state = HTTP_OPENED;
@ -2169,7 +2178,7 @@ void HTTP_Run( void )
{ {
Con_Printf( S_ERROR "failed to resolve server address for %s!\n", curfile->server->host ); Con_Printf( S_ERROR "failed to resolve server address for %s!\n", curfile->server->host );
HTTP_FreeFile( curfile, true ); // Cannot connect HTTP_FreeFile( curfile, true ); // Cannot connect
continue; break;
} }
curfile->state = HTTP_NS_RESOLVED; curfile->state = HTTP_NS_RESOLVED;
} }
@ -2186,7 +2195,7 @@ void HTTP_Run( void )
{ {
Con_Printf( S_ERROR "cannot connect to server: %s\n", NET_ErrorString( ) ); Con_Printf( S_ERROR "cannot connect to server: %s\n", NET_ErrorString( ) );
HTTP_FreeFile( curfile, true ); // Cannot connect HTTP_FreeFile( curfile, true ); // Cannot connect
continue; break;
} }
continue; // skip to next file continue; // skip to next file
} }
@ -2256,7 +2265,7 @@ void HTTP_Run( void )
} }
if( !HTTP_ProcessStream( curfile ) ) if( !HTTP_ProcessStream( curfile ) )
continue; break;
if( curfile->size > 0 ) if( curfile->size > 0 )
{ {
@ -2267,9 +2276,9 @@ void HTTP_Run( void )
if( curfile->size > 0 && curfile->downloaded >= curfile->size ) if( curfile->size > 0 && curfile->downloaded >= curfile->size )
{ {
HTTP_FreeFile( curfile, false ); // success HTTP_FreeFile( curfile, false ); // success
continue; break;
} }
else if( WSAGetLastError() != WSAEWOULDBLOCK ) else if( (WSAGetLastError() != WSAEWOULDBLOCK) && (WSAGetLastError() != WSAEINPROGRESS) )
Con_Reportf( "problem downloading %s:\n%s\n", curfile->path, NET_ErrorString() ); Con_Reportf( "problem downloading %s:\n%s\n", curfile->path, NET_ErrorString() );
else else
curfile->blocktime += host.frametime; curfile->blocktime += host.frametime;
@ -2278,7 +2287,7 @@ void HTTP_Run( void )
{ {
Con_Printf( S_ERROR "timeout on receiving data!\n"); Con_Printf( S_ERROR "timeout on receiving data!\n");
HTTP_FreeFile( curfile, true ); HTTP_FreeFile( curfile, true );
continue; break;
} }
} }
@ -2603,5 +2612,5 @@ void HTTP_Shutdown( void )
Mem_Free( tmp ); Mem_Free( tmp );
} }
http.last_server = 0; http.last_server = NULL;
} }

Loading…
Cancel
Save