]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- For multi Python module setups, clean previously parsed module
authorGeorge Thessalonikefs <yorgos@nlnetlabs.nl>
Mon, 16 Oct 2023 14:03:11 +0000 (16:03 +0200)
committerGeorge Thessalonikefs <yorgos@nlnetlabs.nl>
Mon, 16 Oct 2023 14:03:11 +0000 (16:03 +0200)
  functions in __main__'s dictionary, if any, so that only current
  module functions are registered.

doc/Changelog
pythonmod/pythonmod.c

index 195e3b17033e3b165f4cd28f5c37803e3148ad1f..ff12a6b462c8e4e5df8cae93d8309470c8f932d1 100644 (file)
@@ -5,6 +5,9 @@
        - Expose the configured listening and outgoing interfaces, if any, as
          a list of strings in the Python 'config_file' class instead of the
          current Swig object proxy; fixes #79.
+       - For multi Python module setups, clean previously parsed module
+         functions in __main__'s dictionary, if any, so that only current
+         module functions are registered.
 
 13 October 2023: George
        - Better fix for infinite loop when reading multiple lines of input on
index e655066cb21fac44d99a73d5a1d73d752467a595..c6294a1d50c9b443446eea08edbb7eab2cd142cf 100644 (file)
@@ -112,6 +112,34 @@ struct pythonmod_qstate {
        PyObject* data;
 };
 
+/* The dict from __main__ could have remnants from a previous script
+ * invocation, in a multi python module setup. Usually this is fine since newer
+ * scripts will update their values. The obvious erroneous case is when mixing
+ * python scripts that make use of both 'init' and 'init_standard'. This
+ * results in 'init_standard' to persist on following scripts that don't use it
+ * (thus not replacing it). This is also problematic in case where a script
+ * does not define a required function but a previously loaded script did. The
+ * current solution is to make sure to clean offensive remnants that influence
+ * further parsing of the individual scripts.
+ */
+static void
+clean_python_function_objects(PyObject* dict) {
+       const char* function_names[] = {
+               "init",
+               "init_standard",
+               "deinit",
+               "operate",
+               "inform_super"
+       };
+       size_t i;
+
+       for(i=0; i<sizeof(function_names)/sizeof(function_names[0]); i++) {
+               if(PyDict_GetItemString(dict, function_names[i]) != NULL) {
+                       PyDict_DelItemString(dict, function_names[i]);
+               }
+       }
+};
+
 /* Generated */
 #ifndef S_SPLINT_S
 #include "pythonmod/interface.h"
@@ -418,6 +446,8 @@ int pythonmod_init(struct module_env* env, int id)
    Py_XINCREF(pe->module);
    pe->dict = PyModule_GetDict(pe->module);
    Py_XINCREF(pe->dict);
+   clean_python_function_objects(pe->dict);
+
    pe->data = PyDict_New();
    /* add the script filename to the global "mod_env" for trivial access */
    fname = PyString_FromString(pe->fname);