diff --git a/CHANGELOG.md b/CHANGELOG.md index c51baa045..1c78c33a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ Over here will be noted all the update change logs. +## v1.6.3 - [Release](https://github.com/swiftly-solution/swiftly/releases/tag/v1.6.3) + +### Core + +- Added Crash Prevention for Schema/SDK accessing and for FireEvent. + +![imgalt](https://cdn.skuzzi.ro/dfihge478fg3h478veriufh938wf.png) +![imgalt](https://cdn.skuzzi.ro/vj9834uf09asweifmnjw398fj92hfivsewh98w.png) + +### Crash Reporter + +- Added arguments inside CallStack back. + +### CEntityKeyValues + +- Fixed crashes when map was changing. + ## v1.6.2 - [Release](https://github.com/swiftly-solution/swiftly/releases/tag/v1.6.2) ### Exports @@ -126,4 +143,4 @@ Over here will be noted all the update change logs. - [+] Error Stack Trace -![ImgAlt](https://cdn.skuzzi.ro/zJIsaG8viy2FVsXbtQxmGxCmTJ62iKOD.png) \ No newline at end of file +![ImgAlt](https://cdn.skuzzi.ro/zJIsaG8viy2FVsXbtQxmGxCmTJ62iKOD.png) diff --git a/src/engine/vgui/screentext.cpp b/src/engine/vgui/screentext.cpp index c9ffcc8fa..a221737c6 100644 --- a/src/engine/vgui/screentext.cpp +++ b/src/engine/vgui/screentext.cpp @@ -197,8 +197,8 @@ void ScreenText::SetRenderingTo(CEntityInstance* ent) } void EraseScheduledCEntKeyVals() { - for (auto e : scheduleForDelete) { - delete e; - } + // for (auto e : scheduleForDelete) { + // delete e; + // } scheduleForDelete.clear(); } \ No newline at end of file diff --git a/src/scripting/core.cpp b/src/scripting/core.cpp index 5dbe49cbe..e9cb1612a 100644 --- a/src/scripting/core.cpp +++ b/src/scripting/core.cpp @@ -72,6 +72,11 @@ void SetupScriptingEnvironment(PluginObject plugin, EContext* ctx) ADD_FUNCTION("OnFunctionContextRegister", [](FunctionContext* context) -> void { std::string function_call = replace(context->GetFunctionKey(), " ", "::"); + std::vector arguments; + for (int i = 0; i < context->GetArgumentsCount(); i++) + arguments.push_back(context->GetArgumentAsString(i)); + function_call += "(" + implode(arguments, ", ") + ")"; + context->temporaryData.push_back(g_callStack.RegisterPluginCallstack(FetchPluginName(context->GetPluginContext()), function_call)); g_ResourceMonitor.StartTime("core", replace(context->GetFunctionKey(), " ", "::")); }); diff --git a/src/scripting/engine/events.cpp b/src/scripting/engine/events.cpp index d9dc5124e..fb1e2f00e 100644 --- a/src/scripting/engine/events.cpp +++ b/src/scripting/engine/events.cpp @@ -1,6 +1,8 @@ #include +#include #include #include +#include extern std::map gameEventsRegister; EValue SerializeData(std::any data, EContext* state); @@ -178,7 +180,7 @@ LoadScriptingComponent(events, [](PluginObject plugin, EContext* ctx) -> void { IGameEventListener2* playerListener = g_GameData.FetchSignature("LegacyGameEventListener")(slot); if (!g_gameEventManager->FindListener(playerListener, data->GetData("event_data")->GetName())) { - /* TODO: Crash Reporter - Report crash prevention */ + ReportPreventionIncident("Fire Event", string_format("Tried to fire event '%s' but the client isn't listening to this event.", data->GetData("event_data")->GetName())); return; } playerListener->FireGameEvent(data->GetData("event_data")); diff --git a/src/scripting/sdk/schema.cpp b/src/scripting/sdk/schema.cpp index 23eadfeb1..5577efe0e 100644 --- a/src/scripting/sdk/schema.cpp +++ b/src/scripting/sdk/schema.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -311,7 +312,7 @@ void SchemaCallback(PluginObject plugin, EContext* ctx) { void* instance = data->GetData("class_ptr"); if (!instance) { - /* TODO: Crash Reporter - Report crash prevention */ + ReportPreventionIncident("Schema / SDK", string_format("Tried to get member '%s::%s' but the entity is invalid.", className.c_str(), fieldName.c_str())); return context->StopExecution(); } context->SetReturn(AccessSDK(data->GetData("class_ptr"), className, fieldName, path, context->GetPluginContext())); @@ -320,6 +321,12 @@ void SchemaCallback(PluginObject plugin, EContext* ctx) { std::string className = data->GetData("class_name"); std::string fieldName = explode(context->GetFunctionKey(), " ").back(); + void* instance = data->GetData("class_ptr"); + if (!instance) { + ReportPreventionIncident("Schema / SDK", string_format("Tried to set member '%s::%s' but the entity is invalid.", className.c_str(), fieldName.c_str())); + return context->StopExecution(); + } + UpdateSDK(data->GetData("class_ptr"), className, fieldName, context->GetArgument(0), context->GetPluginContext()); context->StopExecution(); }); @@ -333,7 +340,7 @@ void SchemaCallback(PluginObject plugin, EContext* ctx) { if (classFuncs.find(path) != classFuncs.end()) { void* instance = data->GetData("class_ptr"); if (!instance) { - /* TODO: Crash Reporter - Report crash prevention */ + ReportPreventionIncident("Schema / SDK", string_format("Tried to call function '%s::%s' but the entity is invalid.", className.c_str(), function_name.c_str())); return context->StopExecution(); } return; diff --git a/src/tools/crashreporter/crashreporter.cpp b/src/tools/crashreporter/crashreporter.cpp index ab13c66e4..7debaab93 100644 --- a/src/tools/crashreporter/crashreporter.cpp +++ b/src/tools/crashreporter/crashreporter.cpp @@ -53,6 +53,15 @@ bool BeginCrashListener() { } } + if (!Files::ExistsPath("addons/swiftly/dumps/prevention")) + { + if (!Files::CreateDirectory("addons/swiftly/dumps/prevention")) + { + PLUGIN_PRINTF("Crash Listener", "Couldn't create dumps prevention folder.\n"); + return false; + } + } + startup_cmd = CommandLine()->GetCmdLine(); std::vector exp = explode(startup_cmd, " "); std::vector exp2; @@ -181,6 +190,15 @@ bool BeginCrashListener() { } } + if (!Files::ExistsPath("addons/swiftly/dumps/prevention")) + { + if (!Files::CreateDirectory("addons/swiftly/dumps/prevention")) + { + PLUGIN_PRINTF("Crash Listener", "Couldn't create dumps prevention folder.\n"); + return false; + } + } + startup_cmd = CommandLine()->GetCmdLine(); std::vector exp = explode(startup_cmd, " "); std::vector exp2; @@ -253,4 +271,28 @@ void WriteCrashDump(std::vector functionStack) Files::Append(file_path, string_format("================================\nCommand: %s\nMap: %s\nVersion: %s (%s)\n================================\n\n%s\n\n%s", startup_cmd.c_str(), engine->GetServerGlobals() ? engine->GetServerGlobals()->mapname.ToCStr() : "None", g_Plugin.GetVersion(), GITHUB_SHA, implode(functionStack, "\n").c_str(), WritePluginsCallStack().c_str()), false); PLUGIN_PRINTF("Crash Reporter", "A dump log file has been created at: %s\n", file_path.c_str()); + exit(1); +} + +void ReportPreventionIncident(std::string category, std::string incident_str) +{ + PLUGIN_PRINTF("Crash Prevention", "A crash has been prevented by Swiftly Core and the details will be listed below:\n"); + + TextTable backtraceTable('-', '|', '+'); + + backtraceTable.add(" Category "); + backtraceTable.add(" Message "); + backtraceTable.endOfRow(); + + backtraceTable.add(string_format(" %s ", category.c_str())); + backtraceTable.add(string_format(" %s ", incident_str.c_str())); + backtraceTable.endOfRow(); + + PrintTextTable("Crash Prevention", backtraceTable); + + std::string file_path = string_format("addons/swiftly/dumps/prevention/incident.%s.log", get_uuid().c_str()); + if (Files::ExistsPath(file_path)) Files::Delete(file_path); + + Files::Append(file_path, string_format("================================\nCategory: %s\nDetails: %s\n\n%s", category.c_str(), incident_str.c_str(), WritePluginsCallStack().c_str()), false); + PLUGIN_PRINTF("Crash Prevention", "A log file has been created at: %s\n", file_path.c_str()); } \ No newline at end of file diff --git a/src/tools/crashreporter/crashreporter.h b/src/tools/crashreporter/crashreporter.h index 1089c7b0e..3458c3663 100644 --- a/src/tools/crashreporter/crashreporter.h +++ b/src/tools/crashreporter/crashreporter.h @@ -1,7 +1,11 @@ #ifndef _tools_crashreporter_h #define _tools_crashreporter_h +#include + bool BeginCrashListener(); void EndCrashListener(); +void ReportPreventionIncident(std::string category, std::string incident_str); + #endif \ No newline at end of file