[libxml2] Fix a few problems with setEntityLoader



commit a9016c492788eb4792c42b52df0c72b46136787d
Author: Alexey Neyman <stilor att net>
Date:   Mon Feb 25 16:07:09 2013 +0800

    Fix a few problems with setEntityLoader
    
    1. Setting entity loader does not increment the refcount on the Python object
    passed in. This works only if the object is not deleted. For example, the
    following code results in segmentation fault in Python interpreter when
    attempting to process any document:
    
    [[[
    def register_entity_loader():
        def entity_loader(URL, ID, ctxt):
            ...
        libxml2.setEntityLoader(entity_loader
    
    register_entity_loader()
    ]]]
    
    2. setEntityLoader() does not verify if the passed object is callable. If it
    is not, current implementation attempts to call it anyway and failing that,
    silently moves on to default entity loader. Attached patch makes
    setEntityLoader raise ValueError exception if non-callable object is
    passed.
    
    3. In debug mode, pythonExternalEntityLoader() outputs the result object to
    stderr, while the messages before and after the object (description + newline)
    go to stdout. Attached patch makes them all go to stdout.

 python/libxml.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
---
diff --git a/python/libxml.c b/python/libxml.c
index 9c013a6..8c66fed 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -665,7 +665,7 @@ pythonExternalEntityLoader(const char *URL, const char *ID,
        Py_XDECREF(ctxtobj);
 #ifdef DEBUG_LOADER
        printf("pythonExternalEntityLoader: result ");
-       PyObject_Print(ret, stderr, 0);
+       PyObject_Print(ret, stdout, 0);
        printf("\n");
 #endif
 
@@ -711,13 +711,20 @@ libxml_xmlSetEntityLoader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
                &loader))
        return(NULL);
 
+    if (!PyCallable_Check(loader)) {
+       PyErr_SetString(PyExc_ValueError, "entity loader is not callable");
+       return(NULL);
+    }
+
 #ifdef DEBUG_LOADER
     printf("libxml_xmlSetEntityLoader\n");
 #endif
     if (defaultExternalEntityLoader == NULL) 
        defaultExternalEntityLoader = xmlGetExternalEntityLoader();
 
+    Py_XDECREF(pythonExternalEntityLoaderObjext);
     pythonExternalEntityLoaderObjext = loader;
+    Py_XINCREF(pythonExternalEntityLoaderObjext);
     xmlSetExternalEntityLoader(pythonExternalEntityLoader);
 
     py_retval = PyInt_FromLong(0);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]