From e206c242c6b7011f424e0da975d7aeb2d0b450d5 Mon Sep 17 00:00:00 2001 From: lethosor Date: Tue, 2 Dec 2014 21:29:13 -0500 Subject: [PATCH] Add a plugin_globals vector to aid in safety checks for plugins that require globals This allows "using df::global::foo" to be replaced by "REQUIRE_GLOBAL(foo)", and DFHack will refuse to load the plugin if df::global::foo is NULL --- library/PluginManager.cpp | 25 +++++++++++++++++++++++-- library/include/PluginManager.h | 10 +++++++++- plugins/3dveins.cpp | 7 +++---- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp index ad390d507..713c442c3 100644 --- a/library/PluginManager.cpp +++ b/library/PluginManager.cpp @@ -30,6 +30,7 @@ distribution. #include "RemoteServer.h" #include "Console.h" #include "Types.h" +#include "VersionInfo.h" #include "DataDefs.h" #include "MiscUtils.h" @@ -167,6 +168,7 @@ Plugin::Plugin(Core * core, const std::string & filepath, const std::string & _f } plugin_lib = 0; plugin_init = 0; + plugin_globals = 0; plugin_shutdown = 0; plugin_status = 0; plugin_onupdate = 0; @@ -235,13 +237,32 @@ bool Plugin::load(color_ostream &con) *plug_self = this; RefAutolock lock(access); plugin_init = (command_result (*)(color_ostream &, std::vector &)) LookupPlugin(plug, "plugin_init"); - if(!plugin_init) + std::vector** plugin_globals_ptr = (std::vector**) LookupPlugin(plug, "plugin_globals"); + if(!plugin_init || !plugin_globals_ptr) { - con.printerr("Plugin %s has no init function.\n", filename.c_str()); + con.printerr("Plugin %s has no init function or globals vector.\n", filename.c_str()); ClosePlugin(plug); state = PS_BROKEN; return false; } + plugin_globals = *plugin_globals_ptr; + if (plugin_globals->size()) + { + std::vector missing_globals; + for (auto it = plugin_globals->begin(); it != plugin_globals->end(); ++it) + { + if (!Core::getInstance().vinfo->getAddress(it->c_str())) + missing_globals.push_back(*it); + } + if (missing_globals.size()) + { + con.printerr("Plugin %s is missing required globals: %s\n", + filename.c_str(), join_strings(", ", missing_globals).c_str()); + ClosePlugin(plug); + state = PS_BROKEN; + return false; + } + } plugin_status = (command_result (*)(color_ostream &, std::string &)) LookupPlugin(plug, "plugin_status"); plugin_onupdate = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_onupdate"); plugin_shutdown = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_shutdown"); diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h index b47863d48..ba5b76b62 100644 --- a/library/include/PluginManager.h +++ b/library/include/PluginManager.h @@ -205,6 +205,7 @@ namespace DFHack void reset_lua(); bool *plugin_is_enabled; + std::vector* plugin_globals; command_result (*plugin_init)(color_ostream &, std::vector &); command_result (*plugin_status)(color_ostream &, std::string &); command_result (*plugin_shutdown)(color_ostream &); @@ -264,7 +265,9 @@ namespace DFHack #define DFHACK_PLUGIN(plugin_name) \ DFhackDataExport const char * version = DFHACK_VERSION;\ DFhackDataExport const char * name = plugin_name;\ - DFhackDataExport Plugin *plugin_self = NULL; + DFhackDataExport Plugin *plugin_self = NULL;\ + std::vector _plugin_globals;\ + DFhackDataExport std::vector* plugin_globals = &_plugin_globals; #define DFHACK_PLUGIN_IS_ENABLED(varname) \ DFhackDataExport bool plugin_is_enabled = false; \ @@ -281,3 +284,8 @@ namespace DFHack #define DFHACK_LUA_FUNCTION(name) { #name, df::wrap_function(name,true) } #define DFHACK_LUA_EVENT(name) { #name, &name##_event } #define DFHACK_LUA_END { NULL, NULL } + +#define REQUIRE_GLOBAL(global_name) \ + using df::global::global_name; \ + static int VARIABLE_IS_NOT_USED CONCAT_TOKENS(required_globals_, __LINE__) = \ + (plugin_globals->push_back(#global_name), 0); diff --git a/plugins/3dveins.cpp b/plugins/3dveins.cpp index 9802ff5eb..d57a80662 100644 --- a/plugins/3dveins.cpp +++ b/plugins/3dveins.cpp @@ -41,13 +41,12 @@ using namespace DFHack; using namespace MapExtras; using namespace DFHack::Random; -using df::global::world; -using df::global::gametype; +DFHACK_PLUGIN("3dveins"); +REQUIRE_GLOBAL(world); +REQUIRE_GLOBAL(gametype); command_result cmd_3dveins(color_ostream &out, std::vector & parameters); -DFHACK_PLUGIN("3dveins"); - DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand(