3030#include < luabind/class_info.hpp>
3131
3232#include < stdarg.h>
33+ #include < limits>
3334
3435Flags32 g_LuaDebug;
3536int g_LuaDumpDepth = 0 ;
@@ -140,8 +141,11 @@ void CScriptEngine::reinit()
140141 file_header = file_header_new;
141142 else
142143 file_header = file_header_old;
143- scriptBufferSize = 1024 * 1024 ;
144+ constexpr size_t kInitialScriptBufferSize = 1024 * 1024 + 1 ;
145+ scriptBufferSize = kInitialScriptBufferSize ;
144146 scriptBuffer = xr_alloc<char >(scriptBufferSize);
147+ if (scriptBuffer)
148+ scriptBuffer[0 ] = ' \0 ' ;
145149
146150 if (m_profiler)
147151 m_profiler->OnReinit (m_virtual_machine);
@@ -313,6 +317,9 @@ bool CScriptEngine::parse_namespace(pcstr caNamespaceName, pstr b, size_t b_size
313317bool CScriptEngine::load_buffer (
314318lua_State* L, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, LPCSTR caNameSpaceName)
315319{
320+ m_lastLoadedChunk = caScriptName ? caScriptName : " <unnamed chunk>" ;
321+ m_lastLoadedNamespace = caNameSpaceName ? caNameSpaceName : GlobalNamespace;
322+
316323 int l_iErrorCode;
317324 if (caNameSpaceName && xr_strcmp (GlobalNamespace, caNameSpaceName))
318325 {
@@ -323,14 +330,35 @@ lua_State* L, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, LPCSTR caNameS
323330 xr_sprintf (insert, header, caNameSpaceName, a, b);
324331 const size_t str_len = xr_strlen (insert);
325332 const size_t total_size = str_len + tSize;
326- if (total_size >= scriptBufferSize)
333+ if (total_size < str_len)
334+ {
335+ script_log (LuaMessageType::Error, " script namespace header overflow for %s" , caScriptName);
336+ on_error (L);
337+ return false ;
338+ }
339+ if (total_size > std::numeric_limits<size_t >::max () - 1 )
340+ {
341+ script_log (LuaMessageType::Error, " script buffer size overflow for %s" , caScriptName);
342+ on_error (L);
343+ return false ;
344+ }
345+ const size_t required_size = total_size + 1 ; // extra byte for sentinel '\0'
346+ if (required_size > scriptBufferSize)
327347 {
328- scriptBufferSize = total_size;
329- scriptBuffer = (char *)xr_realloc (scriptBuffer, scriptBufferSize);
348+ scriptBufferSize = required_size;
349+ scriptBuffer = static_cast <char *>(xr_realloc (scriptBuffer, scriptBufferSize));
350+ if (!scriptBuffer)
351+ {
352+ script_log (LuaMessageType::Error, " out of memory while resizing script buffer for %s" , caScriptName);
353+ on_error (L);
354+ return false ;
355+ }
330356 }
331- xr_strcpy (scriptBuffer, total_size, insert);
332- CopyMemory (scriptBuffer + str_len, caBuffer, tSize);
333- l_iErrorCode = luaL_loadbuffer (L, scriptBuffer, tSize + str_len, caScriptName);
357+ xr_strcpy (scriptBuffer, scriptBufferSize, insert);
358+ if (tSize > 0 )
359+ CopyMemory (scriptBuffer + str_len, caBuffer, tSize);
360+ scriptBuffer[total_size] = ' \0 ' ;
361+ l_iErrorCode = luaL_loadbuffer (L, scriptBuffer, total_size, caScriptName);
334362 }
335363 else
336364 l_iErrorCode = luaL_loadbuffer (L, caBuffer, tSize, caScriptName);
@@ -370,6 +398,7 @@ bool CScriptEngine::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName)
370398 if (debugger ())
371399 errFuncId = debugger ()->PrepareLua (lua ());
372400#endif
401+ m_lastExecutingChunk = caScriptName ? caScriptName : " <unnamed chunk>" ;
373402 if (0 ) // .
374403 {
375404 for (int i = 0 ; lua_type (lua (), -i - 1 ); i++)
@@ -639,6 +668,9 @@ CScriptEngine::CScriptEngine(bool is_editor, bool is_with_profiler)
639668 m_reload_modules = false ;
640669 m_last_no_file_length = 0 ;
641670 *m_last_no_file = 0 ;
671+ m_lastLoadedChunk.clear ();
672+ m_lastLoadedNamespace = GlobalNamespace;
673+ m_lastExecutingChunk.clear ();
642674#ifdef USE_DEBUGGER
643675#ifndef USE_LUA_STUDIO
644676 static_assert (false , " Do not define USE_LUA_STUDIO macro without USE_DEBUGGER macro" );
@@ -1174,3 +1206,37 @@ bool CScriptEngine::is_editor()
11741206{
11751207 return m_is_editor;
11761208}
1209+
1210+ void CScriptEngine::OnLuaAssertion (lua_State* state, pcstr file, int line, pcstr func, pcstr message)
1211+ {
1212+ const pcstr loadedChunk = m_lastLoadedChunk.empty () ? " <none>" : m_lastLoadedChunk.c_str ();
1213+ const pcstr namespaceName = m_lastLoadedNamespace.empty () ? GlobalNamespace : m_lastLoadedNamespace.c_str ();
1214+ const pcstr executingChunk = m_lastExecutingChunk.empty () ? loadedChunk : m_lastExecutingChunk.c_str ();
1215+
1216+ Msg (" ! [LuaJIT] ASSERT %s:%d (%s): %s" , file ? file : " <unknown>" , line,
1217+ func ? func : " <unknown>" , (message && message[0 ]) ? message : " <no message>" );
1218+ Msg (" ! [LuaJIT] last loaded chunk: %s (namespace: %s)" , loadedChunk, namespaceName);
1219+ Msg (" ! [LuaJIT] last executing chunk: %s" , executingChunk);
1220+
1221+ #ifdef DEBUG
1222+ const bool reenter = logReenterability;
1223+ logReenterability = true ;
1224+ if (state)
1225+ print_stack (state);
1226+ logReenterability = reenter;
1227+ #else
1228+ (void )state;
1229+ #endif
1230+ }
1231+
1232+ extern " C" XRSCRIPTENGINE_API void xr_LuaAssertionHandler (lua_State* state, const char * file, int line, const char * func, const char * message)
1233+ {
1234+ if (!state)
1235+ return ;
1236+
1237+ CScriptEngine* engine = CScriptEngine::GetInstance (state);
1238+ if (!engine)
1239+ return ;
1240+
1241+ engine->OnLuaAssertion (state, file, line, func, message);
1242+ }
0 commit comments