From 23f4001f36fc7a5ad50ec85eb9c722c8e52e1ac6 Mon Sep 17 00:00:00 2001 From: ccw Date: Sat, 30 Jan 2016 08:21:44 +0000 Subject: [PATCH] Fixed crash when using fileRead with a large count argument --- MTA10/mods/shared_logic/CScriptFile.cpp | 16 +++++++++++++--- MTA10/mods/shared_logic/CScriptFile.h | 2 +- MTA10/mods/shared_logic/luadefs/CLuaFileDefs.cpp | 9 +++------ .../mods/deathmatch/logic/CScriptFile.cpp | 16 +++++++++++++--- MTA10_Server/mods/deathmatch/logic/CScriptFile.h | 2 +- .../deathmatch/logic/luadefs/CLuaFileDefs.cpp | 10 +++------- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/MTA10/mods/shared_logic/CScriptFile.cpp b/MTA10/mods/shared_logic/CScriptFile.cpp index 0ed6934d48..7c40d03205 100644 --- a/MTA10/mods/shared_logic/CScriptFile.cpp +++ b/MTA10/mods/shared_logic/CScriptFile.cpp @@ -162,15 +162,25 @@ void CScriptFile::Flush ( void ) } -long CScriptFile::Read ( unsigned long ulSize, char* pData ) +long CScriptFile::Read ( unsigned long ulSize, CBuffer& outBuffer ) { if ( !m_pFile ) return -1; DoResourceFileCheck(); - // Try to read data into the given block. Return number of bytes we read. - return m_pFile->FRead ( pData, ulSize ); + // If read size is large, limit it to how many bytes can be read (avoid memory problems with over allocation) + if ( ulSize > 10000 ) + { + long lCurrentPos = m_pFile->FTell (); + m_pFile->FSeek ( 0, SEEK_END ); + long lFileSize = m_pFile->FTell (); + m_pFile->FSeek ( lCurrentPos, SEEK_SET ); + ulSize = Min < unsigned long > ( lFileSize - lCurrentPos, ulSize ); + } + + outBuffer.SetSize( ulSize ); + return m_pFile->FRead ( outBuffer.GetData(), ulSize ); } diff --git a/MTA10/mods/shared_logic/CScriptFile.h b/MTA10/mods/shared_logic/CScriptFile.h index 5502c04ebc..ac3e3b251a 100644 --- a/MTA10/mods/shared_logic/CScriptFile.h +++ b/MTA10/mods/shared_logic/CScriptFile.h @@ -59,7 +59,7 @@ class CScriptFile : public CClientEntity long SetPointer ( unsigned long ulPosition ); void Flush ( void ); - long Read ( unsigned long ulSize, char* pData ); + long Read ( unsigned long ulSize, CBuffer& outBuffer ); long Write ( unsigned long ulSize, const char* pData ); private: diff --git a/MTA10/mods/shared_logic/luadefs/CLuaFileDefs.cpp b/MTA10/mods/shared_logic/luadefs/CLuaFileDefs.cpp index 4687bf6949..40b94e4419 100644 --- a/MTA10/mods/shared_logic/luadefs/CLuaFileDefs.cpp +++ b/MTA10/mods/shared_logic/luadefs/CLuaFileDefs.cpp @@ -409,14 +409,14 @@ int CLuaFileDefs::fileRead ( lua_State* luaVM ) if ( ulCount > 0 ) { // Allocate a buffer to read the stuff into and read some shit into it - char* pReadContent = new char [ulCount + 1]; - long lBytesRead = pFile->Read ( ulCount, pReadContent ); + CBuffer buffer; + long lBytesRead = pFile->Read ( ulCount, buffer ); if ( lBytesRead != -1 ) { // Push the string onto the lua stack. Use pushlstring so we are binary // compatible. Normal push string takes zero terminated strings. - lua_pushlstring ( luaVM, pReadContent, lBytesRead ); + lua_pushlstring ( luaVM, buffer.GetData(), lBytesRead ); } else { @@ -424,9 +424,6 @@ int CLuaFileDefs::fileRead ( lua_State* luaVM ) lua_pushnil ( luaVM ); } - // Delete our read content. Lua should've stored it - delete[] pReadContent; - // We're returning the result string return 1; } diff --git a/MTA10_Server/mods/deathmatch/logic/CScriptFile.cpp b/MTA10_Server/mods/deathmatch/logic/CScriptFile.cpp index 268fcd981e..5ab10822f4 100644 --- a/MTA10_Server/mods/deathmatch/logic/CScriptFile.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CScriptFile.cpp @@ -181,13 +181,23 @@ void CScriptFile::Flush ( void ) } -long CScriptFile::Read ( unsigned long ulSize, char* pData ) +long CScriptFile::Read ( unsigned long ulSize, CBuffer& outBuffer ) { if ( !m_pFile ) return -1; - // Try to read data into the given block. Return number of bytes we read. - return fread ( pData, 1, ulSize, m_pFile ); + // If read size is large, limit it to how many bytes can be read (avoid memory problems with over allocation) + if ( ulSize > 10000 ) + { + long lCurrentPos = ftell ( m_pFile ); + fseek ( m_pFile, 0, SEEK_END ); + long lFileSize = ftell ( m_pFile ); + fseek ( m_pFile, lCurrentPos, SEEK_SET ); + ulSize = Min < unsigned long > ( lFileSize - lCurrentPos, ulSize ); + } + + outBuffer.SetSize( ulSize ); + return fread ( outBuffer.GetData(), 1, ulSize, m_pFile ); } diff --git a/MTA10_Server/mods/deathmatch/logic/CScriptFile.h b/MTA10_Server/mods/deathmatch/logic/CScriptFile.h index 86f5df10f1..ce0d2b02a3 100644 --- a/MTA10_Server/mods/deathmatch/logic/CScriptFile.h +++ b/MTA10_Server/mods/deathmatch/logic/CScriptFile.h @@ -53,7 +53,7 @@ class CScriptFile: public CElement void SetSize ( unsigned long ulNewSize ); void Flush ( void ); - long Read ( unsigned long ulSize, char* pData ); + long Read ( unsigned long ulSize, CBuffer& outBuffer ); long Write ( unsigned long ulSize, const char* pData ); private: diff --git a/MTA10_Server/mods/deathmatch/logic/luadefs/CLuaFileDefs.cpp b/MTA10_Server/mods/deathmatch/logic/luadefs/CLuaFileDefs.cpp index 3424958bbe..da35fcd0a9 100644 --- a/MTA10_Server/mods/deathmatch/logic/luadefs/CLuaFileDefs.cpp +++ b/MTA10_Server/mods/deathmatch/logic/luadefs/CLuaFileDefs.cpp @@ -405,15 +405,14 @@ int CLuaFileDefs::fileRead ( lua_State* luaVM ) { if ( ulCount > 0 ) { - // Allocate a buffer to read the stuff into and read some shit into it - char* pReadContent = new char [ulCount + 1]; - long lBytesRead = pFile->Read ( ulCount, pReadContent ); + CBuffer buffer; + long lBytesRead = pFile->Read ( ulCount, buffer ); if ( lBytesRead != -1 ) { // Push the string onto the lua stack. Use pushlstring so we are binary // compatible. Normal push string takes zero terminated strings. - lua_pushlstring ( luaVM, pReadContent, lBytesRead ); + lua_pushlstring ( luaVM, buffer.GetData(), lBytesRead ); } else { @@ -421,9 +420,6 @@ int CLuaFileDefs::fileRead ( lua_State* luaVM ) lua_pushnil ( luaVM ); } - // Delete our read content. Lua should've stored it - delete [] pReadContent; - // We're returning the result string return 1; }