diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 6cf4a83ce..a69fc1fae 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -142,28 +142,33 @@ void Cbuf_AddFilteredText( const char *text ) Cbuf_InsertText Adds command text immediately after the current command -Adds a \n to the text ============ */ -static void Cbuf_InsertTextToBuffer( cmdbuf_t *buf, const char *text ) +static void Cbuf_InsertTextToBuffer( cmdbuf_t *buf, const char *text, size_t len, size_t requested_len ) { - int l = Q_strlen( text ); - - if(( buf->cursize + l ) >= buf->maxsize ) + if(( buf->cursize + requested_len ) >= buf->maxsize ) { Con_Reportf( S_WARN "%s: overflow\n", __func__ ); } else { - memmove( buf->data + l, buf->data, buf->cursize ); - memcpy( buf->data, text, l ); - buf->cursize += l; + memmove( buf->data + len, buf->data, buf->cursize ); + memcpy( buf->data, text, len ); + buf->cursize += len; } } +void Cbuf_InsertTextLen( const char *text, size_t len, size_t requested_len ) +{ + // sometimes we need to insert more data than we have + // but also prevent overflow + Cbuf_InsertTextToBuffer( &cmd_text, text, len, requested_len ); +} + void Cbuf_InsertText( const char *text ) { - Cbuf_InsertTextToBuffer( &cmd_text, text ); + size_t l = Q_strlen( text ); + Cbuf_InsertTextToBuffer( &cmd_text, text, l, l ); } /* @@ -1010,9 +1015,10 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr if( a ) { + size_t len = Q_strlen( a->value ); Cbuf_InsertTextToBuffer( isPrivileged ? &cmd_text : &filteredcmd_text, - a->value ); + a->value, len, len ); return; } } diff --git a/engine/common/common.h b/engine/common/common.h index 6b08e02c8..db6961597 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -425,6 +425,7 @@ void Cbuf_AddText( const char *text ); void Cbuf_AddTextf( const char *text, ... ) FORMAT_CHECK( 1 ); void Cbuf_AddFilteredText( const char *text ); void Cbuf_InsertText( const char *text ); +void Cbuf_InsertTextLen( const char *text, size_t len, size_t requested_len ); void Cbuf_ExecStuffCmds( void ); void Cbuf_Execute (void); qboolean Cmd_CurrentCommandIsPrivileged( void ); diff --git a/engine/common/host.c b/engine/common/host.c index 9ed0be05c..0fd3ccdac 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -418,8 +418,7 @@ static void Host_Exec_f( void ) { string cfgpath; byte *f; - char *txt; - fs_offset_t len; + fs_offset_t len; if( Cmd_Argc() != 2 ) { @@ -474,20 +473,29 @@ static void Host_Exec_f( void ) return; } + // len is fs_offset_t, which can be larger than size_t + if( len >= SIZE_MAX ) + { + Con_Reportf( "%s: %s is too long\n", __func__, Cmd_Argv( 1 )); + return; + } + if( !Q_stricmp( "config.cfg", cfgpath )) host.config_executed = true; - // adds \n\0 at end of the file - txt = Z_Calloc( len + 2 ); - memcpy( txt, f, len ); - txt[len] = '\n'; - txt[len + 1] = '\0'; - Mem_Free( f ); - if( !host.apply_game_config ) Con_Printf( "execing %s\n", Cmd_Argv( 1 )); - Cbuf_InsertText( txt ); - Mem_Free( txt ); + + // adds \n at end of the file + // FS_LoadFile always null terminates + if( f[len - 1] != '\n' ) + { + Cbuf_InsertTextLen( f, len, len + 1 ); + Cbuf_InsertTextLen( "\n", 1, 1 ); + } + else Cbuf_InsertTextLen( f, len, len ); + + Mem_Free( f ); } /*