We run coverity static analysis as part of our downstream infrastructure for various packages. It found some issues with lxml, more specifically:
10. lxml-6. 0.2/src/ lxml/etree. c:70181: 5: alloc_fn: Storage is returned from allocation function "xmlStrdup".
11. lxml-6. 0.2/src/ lxml/etree. c:70181: 5: var_assign: Assigning: "_pyx_v_c_value" = storage returned from "xmlStrdup((xmlChar const *)PyBytes_ AS_STRING( (PyObject *)_pyx_v_value))".
16. lxml-6. 0.2/src/ lxml/etree. c:70325: 3: leaked_storage: Variable "__pyx_v_c_value" going out of scope leaks the storage it points to.
70323| _Pyx_XDECREF( _pyx_v_ value);
70324| __Pyx_RefNannyF inishContext( );
70325|-> return __pyx_r;
70326| }
70327|
9. lxml-6. 0.2/src/ lxml/etree. c:70610: 5: alloc_fn: Storage is returned from allocation function "xmlStrdup".
10. lxml-6. 0.2/src/ lxml/etree. c:70610: 5: var_assign: Assigning: "_pyx_v_c_value" = storage returned from "xmlStrdup((xmlChar const *)PyBytes_ AS_STRING( (PyObject *)_pyx_v_bvalue))".
15. lxml-6. 0.2/src/ lxml/etree. c:70753: 3: leaked_storage: Variable "__pyx_v_c_value" going out of scope leaks the storage it points to.
70751| _Pyx_XDECREF( _pyx_v_ bvalue) ;
70752| __Pyx_RefNannyF inishContext( );
70753|-> return __pyx_r;
70754| }
70755|
It looks like for these values is something happens like e.g. a KeyboardInterrupt, PyErr_Occurred() will detect it and jump to the error handler, which only frees Python objects, not c_value, hence the leak.
I'm attaching a patch, but my knowledge of the codebase is very limited, and therefore, it should be carefully reviewed. I can prepare a PR if you want, but I wasn't sure about the patch quality and accuracy.