diff --git a/src/controllers/plugins/PluginController.cpp b/src/controllers/plugins/PluginController.cpp index a0075d554..f4dacac53 100644 --- a/src/controllers/plugins/PluginController.cpp +++ b/src/controllers/plugins/PluginController.cpp @@ -73,19 +73,52 @@ bool PluginController::tryLoadFromDir(const QDir &pluginDir) this->load(index, pluginDir, PluginMeta(doc.object())); return true; } +void PluginController::openLibrariesFor(lua_State *L, PluginMeta meta) +{ + // copied from linit.c + static const std::array loadedlibs = { + luaL_Reg{LUA_GNAME, luaopen_base}, + luaL_Reg{LUA_LOADLIBNAME, luaopen_package}, + luaL_Reg{LUA_COLIBNAME, luaopen_coroutine}, + luaL_Reg{LUA_TABLIBNAME, luaopen_table}, + luaL_Reg{LUA_IOLIBNAME, luaopen_io}, + luaL_Reg{LUA_OSLIBNAME, luaopen_os}, + luaL_Reg{LUA_STRLIBNAME, luaopen_string}, + luaL_Reg{LUA_MATHLIBNAME, luaopen_math}, + luaL_Reg{LUA_UTF8LIBNAME, luaopen_utf8}, + luaL_Reg{LUA_DBLIBNAME, luaopen_debug}, + luaL_Reg{NULL, NULL}, + }; + + for (const auto ® : loadedlibs) + { + if (meta.libraryPermissions.contains(QString(reg.name))) + { + luaL_requiref(L, reg.name, reg.func, int(true)); + lua_pop(L, 1); + } + } +} void PluginController::load(QFileInfo index, QDir pluginDir, PluginMeta meta) { qCDebug(chatterinoLua) << "Running lua file" << index; lua_State *l = luaL_newstate(); - luaL_openlibs(l); + this->openLibrariesFor(l, meta); this->loadChatterinoLib(l); auto pluginName = pluginDir.dirName(); auto plugin = std::make_unique(pluginName, l, meta, pluginDir); this->plugins_.insert({pluginName, std::move(plugin)}); - luaL_dofile(l, index.absoluteFilePath().toStdString().c_str()); + int err = luaL_dofile(l, index.absoluteFilePath().toStdString().c_str()); + if (err != 0) + { + qCWarning(chatterinoLua) + << "Failed to load" << pluginName << "plugin from" << index << ": " + << lua::humanErrorText(l, err); + return; + } qCInfo(chatterinoLua) << "Loaded" << pluginName << "plugin from" << index; } diff --git a/src/controllers/plugins/PluginController.hpp b/src/controllers/plugins/PluginController.hpp index ec88da923..b672cf9d1 100644 --- a/src/controllers/plugins/PluginController.hpp +++ b/src/controllers/plugins/PluginController.hpp @@ -29,6 +29,8 @@ struct PluginMeta { QString homepage; std::vector tags; + std::set libraryPermissions; + explicit PluginMeta(const QJsonObject &obj) : name(obj.value("name").toString()) , description(obj.value("description").toString()) @@ -37,7 +39,11 @@ struct PluginMeta { { for (const auto &t : obj.value("tags").toArray()) { - tags.push_back(t.toString()); + this->tags.push_back(t.toString()); + } + for (const auto &t : obj.value("library_permissions").toArray()) + { + this->libraryPermissions.insert(t.toString()); } } }; @@ -121,6 +127,9 @@ public: private: void load(QFileInfo index, QDir pluginDir, PluginMeta meta); void loadChatterinoLib(lua_State *l); + + // This function adds lua standard libraries into the state + void openLibrariesFor(lua_State *L, PluginMeta meta); bool tryLoadFromDir(const QDir &pluginDir); std::map> plugins_; }; diff --git a/src/widgets/settingspages/PluginsPage.cpp b/src/widgets/settingspages/PluginsPage.cpp index 5097203c6..00e00a378 100644 --- a/src/widgets/settingspages/PluginsPage.cpp +++ b/src/widgets/settingspages/PluginsPage.cpp @@ -49,6 +49,32 @@ PluginsPage::PluginsPage() pl->addRow("Homepage", homepage); + QString libString; + bool hasDangerous = false; + for (const auto &library : plugin->meta.libraryPermissions) + { + if (!libString.isEmpty()) + { + libString += ", "; + } + if (library == "os" || library == "io") + { + hasDangerous = true; + } + libString += library; + } + if (hasDangerous) + { + libString += "\nDetected potentially dangerous libraries used, be " + "careful with this plugin"; + } + auto *libs = new QLabel(libString); + if (hasDangerous) + { + libs->setStyleSheet("color: red"); + } + pl->addRow("Used libraries", libs); + auto *reload = new QPushButton("Reload"); QObject::connect(reload, &QPushButton::pressed, [name = codename]() { getApp()->plugins->reload(name);