From 6d5d6aed2e38e1abc625f29c0b3e97fc8c60ae3b Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Wed, 28 Aug 2024 11:16:55 +0200 Subject: [PATCH] Avoid custom "tp_new()" call and add a safe-guard that element lookups actually return a type. --- src/lxml/etree.pyx | 12 +++++------- src/lxml/includes/etree_defs.h | 8 ++------ src/lxml/python.pxd | 1 - 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/lxml/etree.pyx b/src/lxml/etree.pyx index c21d1343..90579af9 100644 --- a/src/lxml/etree.pyx +++ b/src/lxml/etree.pyx @@ -1636,11 +1636,6 @@ cdef public class _Element [ type LxmlElementType, object LxmlElement ]: return CSSSelector(expr, translator=translator)(self) -cdef extern from "includes/etree_defs.h": - # macro call to 't->tp_new()' for fast instantiation - cdef object NEW_ELEMENT "PY_NEW" (object t) - - @cython.linetrace(False) cdef _Element _elementFactory(_Document doc, xmlNode* c_node): cdef _Element result @@ -1650,12 +1645,15 @@ cdef _Element _elementFactory(_Document doc, xmlNode* c_node): if c_node is NULL: return None - element_class = LOOKUP_ELEMENT_CLASS( + element_class = LOOKUP_ELEMENT_CLASS( ELEMENT_CLASS_LOOKUP_STATE, doc, c_node) + if type(element_class) is not type: + if not isinstance(element_class, type): + raise TypeError(f"Element class is not a type, got {type(element_class)}") if hasProxy(c_node): # prevent re-entry race condition - we just called into Python return getProxy(c_node) - result = NEW_ELEMENT(element_class) + result = element_class.__new__(element_class) if hasProxy(c_node): # prevent re-entry race condition - we just called into Python result._c_node = NULL diff --git a/src/lxml/includes/etree_defs.h b/src/lxml/includes/etree_defs.h index 17d470d0..8645869f 100644 --- a/src/lxml/includes/etree_defs.h +++ b/src/lxml/includes/etree_defs.h @@ -177,7 +177,7 @@ long _ftol2( double dblSource ) { return _ftol( dblSource ); } #ifdef __GNUC__ /* Test for GCC > 2.95 */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) +#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) #define unlikely_condition(x) __builtin_expect((x), 0) #else /* __GNUC__ > 2 ... */ #define unlikely_condition(x) (x) @@ -190,10 +190,6 @@ long _ftol2( double dblSource ) { return _ftol( dblSource ); } #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #endif -#define PY_NEW(T) \ - (((PyTypeObject*)(T))->tp_new( \ - (PyTypeObject*)(T), __pyx_empty_tuple, NULL)) - #define _fqtypename(o) ((Py_TYPE(o))->tp_name) #define lxml_malloc(count, item_size) \ @@ -268,7 +264,7 @@ static void* lxml_unpack_xmldoc_capsule(PyObject* capsule, int* is_owned) { * 'inclusive' is 1). The _ELEMENT_ variants will only stop on nodes * that match _isElement(), the normal variant will stop on every node * except text nodes. - * + * * To traverse the node and all of its children and siblings in Pyrex, call * cdef xmlNode* some_node * BEGIN_FOR_EACH_ELEMENT_FROM(some_node.parent, some_node, 1) diff --git a/src/lxml/python.pxd b/src/lxml/python.pxd index d0877355..e0ec762e 100644 --- a/src/lxml/python.pxd +++ b/src/lxml/python.pxd @@ -131,7 +131,6 @@ cdef extern from "includes/etree_defs.h": # redefines some functions as macros cdef void* lxml_unpack_xmldoc_capsule(object capsule, bint* is_owned) except? NULL cdef bint _isString(object obj) cdef const_char* _fqtypename(object t) - cdef object PY_NEW(object t) cdef bint IS_PYPY cdef object PyOS_FSPath(object obj)