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

This commit is contained in:
mittorn 2019-09-29 01:41:41 +07:00
parent 03c73f56d2
commit cb0791c915
1 changed files with 26 additions and 17 deletions

View File

@ -1803,7 +1803,7 @@ typedef struct httpfile_s
qboolean process;
// query or response
char buf[BUFSIZ];
char buf[BUFSIZ+1];
int header_size, query_length, bytes_sent;
} httpfile_t;
@ -1865,7 +1865,7 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
file->socket = -1;
Q_snprintf( incname, 256, "%s.incomplete", file->path );
Q_snprintf( incname, 256, "downloaded/%s.incomplete", file->path );
if( error )
{
// 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
char name[256];
Q_snprintf( name, 256, "%s", file->path );
Q_snprintf( name, 256, "downloaded/%s", file->path );
FS_Rename( incname, name );
if( file->process )
@ -1956,14 +1956,21 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
char *begin = 0;
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;
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 );
curfile->buf[curfile->header_size + res] = 0;
begin = Q_strstr( curfile->buf, "\r\n\r\n" );
if( begin ) // Got full header
@ -1982,7 +1989,7 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
if( begin )
*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 );
return false;
}
@ -1999,6 +2006,7 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
Con_Reportf( S_WARN "Server reports wrong file size!\n" );
curfile->size = size;
curfile->header_size = 0;
}
if( curfile->size == -1 )
@ -2032,7 +2040,8 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
curfile->downloaded += ret;
}
}
curfile->header_size += res;
else
curfile->header_size += res;
}
else if( res > 0 )
{
@ -2107,14 +2116,14 @@ void HTTP_Run( void )
{
Con_Printf( S_ERROR "no servers to download %s!\n", curfile->path );
HTTP_FreeFile( curfile, true );
continue;
break;
}
Con_Reportf( "HTTP: Starting download %s from %s\n", curfile->path, curfile->server->host );
#ifndef XASH_DEDICATED
UI_ConnectionProgress_Download( curfile->path, curfile->server->host, curfile->server->path, curfile->id, http.fileCount, "(starting)");
#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 );
@ -2122,7 +2131,7 @@ void HTTP_Run( void )
{
Con_Printf( S_ERROR "cannot open %s!\n", name );
HTTP_FreeFile( curfile, true );
continue;
break;
}
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 );
HTTP_FreeFile( curfile, true ); // Cannot connect
continue;
break;
}
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( ) );
HTTP_FreeFile( curfile, true ); // Cannot connect
continue;
break;
}
continue; // skip to next file
}
@ -2256,7 +2265,7 @@ void HTTP_Run( void )
}
if( !HTTP_ProcessStream( curfile ) )
continue;
break;
if( curfile->size > 0 )
{
@ -2267,9 +2276,9 @@ void HTTP_Run( void )
if( curfile->size > 0 && curfile->downloaded >= curfile->size )
{
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() );
else
curfile->blocktime += host.frametime;
@ -2278,7 +2287,7 @@ void HTTP_Run( void )
{
Con_Printf( S_ERROR "timeout on receiving data!\n");
HTTP_FreeFile( curfile, true );
continue;
break;
}
}
@ -2603,5 +2612,5 @@ void HTTP_Shutdown( void )
Mem_Free( tmp );
}
http.last_server = 0;
http.last_server = NULL;
}