Mercurial > hg > vampy
changeset 92:a6718f9fe942
If a module appears to redefine one of our own types, refuse to load it. Also clear out the class dict for all refused modules now, so that we don't get stale names on the next scan due to not having cleared the module on unload
author | Chris Cannam |
---|---|
date | Mon, 14 Jan 2019 16:19:44 +0000 |
parents | c4510e5f7a17 |
children | 161ed1fb016b |
files | PyExtensionManager.h PyPlugScanner.cpp |
diffstat | 2 files changed, 88 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/PyExtensionManager.h Mon Jan 14 16:16:43 2019 +0000 +++ b/PyExtensionManager.h Mon Jan 14 16:19:44 2019 +0000 @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 8 indent-tabs-mode: t -*- */ /* * Vampy : This plugin is a wrapper around the Vamp plugin API. @@ -64,9 +65,9 @@ void setPlugModuleNames(vector<string> pyPlugs); void deleteModuleName(string plugKey); + static const char* m_exposedNames[]; + private: - static const char* m_exposedNames[]; - vector<string> m_plugModuleNames; PyObject* m_pyGlobalNamespace; PyObject* m_pyVampyNamespace;
--- a/PyPlugScanner.cpp Mon Jan 14 16:16:43 2019 +0000 +++ b/PyPlugScanner.cpp Mon Jan 14 16:19:44 2019 +0000 @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 8 indent-tabs-mode: t -*- */ /* * Vampy : This plugin is a wrapper around the Vamp plugin API. @@ -11,6 +12,8 @@ #include "PyPlugScanner.h" +#include "PyExtensionManager.h" +#include "Debug.h" #include <algorithm> #include <cstdlib> //#include "vamp-hostsdk/PluginHostAdapter.h" @@ -95,13 +98,12 @@ pluginKey=joinPath(m_path[i],script)+":"+classname; pyClass = getScriptClass(m_path[i],classname); if (pyClass == NULL) - cerr << "Warning: Syntax error in VamPy plugin: " + cerr << "Warning: Syntax error or other problem in scanning VamPy plugin: " << classname << ". Avoiding plugin." << endl; else { pyPlugs.push_back(pluginKey); m_pyClasses.push_back(pyClass); - } - //pyPlugs.push_back(pluginKey); + } } } } @@ -142,7 +144,6 @@ PyObject* PyPlugScanner::getScriptClass(string path, string classname) { - //Add plugin path to active Python Path string pyCmd = "import sys\nsys.path.append('" + path + "')\n"; PyRun_SimpleString(pyCmd.c_str()); @@ -169,17 +170,91 @@ //Get the PluginClass from the module (borrowed reference) PyObject *pyClass = PyDict_GetItemString(pyDict, classname.c_str()); - //Check if class is present and a callable method is implemented - if (pyClass && PyCallable_Check(pyClass)) { - - return pyClass; - } - else { + if (pyClass == Py_None) { + DSTREAM << "Vampy: class name " << classname + << " is None in module; assuming it was scrubbed " + << "following an earlier load failure" << endl; + return NULL; + } + + // Check if class is present and a callable method is implemented + if (!pyClass || !PyCallable_Check(pyClass)) { cerr << "ERROR: callable plugin class could not be found in source: " << classname << endl << "Hint: plugin source filename and plugin class name must be the same." << endl; PyErr_Print(); return NULL; } + + bool acceptable = true; + + // Check that the module doesn't have any name collisions with + // our own symbols + + int i = 0; + while (PyExtensionManager::m_exposedNames[i]) { + + const char* name = PyExtensionManager::m_exposedNames[i]; + i++; + + PyObject *item = PyDict_GetItemString(pyDict, name); + if (!item) continue; + + if (item == Py_None) { + DSTREAM << "Vampy: name " << name << " is None " + << "in module " << classname + << "; assuming it was cleared on unload" + << endl; + continue; + } + + PyTypeObject *metatype = Py_TYPE(item); + + if (!strcmp(name, "frame2RealTime")) { + if (metatype != &PyCFunction_Type) { + cerr << "ERROR: plugin " << classname + << " redefines Vampy function name \"" + << name << "\" (metatype is \"" + << metatype->tp_name << "\")" << endl; + acceptable = false; + break; + } else { + continue; + } + } + + if (metatype != &PyType_Type) { + cerr << "ERROR: plugin " << classname + << " uses Vampy reserved type name \"" << name + << "\" for non-type (metatype is \"" + << metatype->tp_name << "\")" << endl; + acceptable = false; + break; + } + + PyTypeObject *type = (PyTypeObject *)item; + if (type->tp_name == std::string("vampy.") + name) { + DSTREAM << "Vampy: acceptable Vampy type name " + << type->tp_name << " found in module" << endl; + } else { + cerr << "ERROR: plugin " << classname + << " redefines Vampy type \"" << name << "\""; + if (strcmp(type->tp_name, name)) { + cerr << " (as \"" << type->tp_name << "\")"; + } + cerr << endl; + acceptable = false; + break; + } + } + + if (acceptable) { + return pyClass; + } else { + PyObject *key = PyString_FromString(classname.c_str()); + PyDict_SetItem(pyDict, key, Py_None); + Py_DECREF(key); + return NULL; + } }