22
33#include <stdbool.h>
44#include <stdint.h>
5+ #include <stdlib.h>
6+ #include <string.h>
57
68#include "uast.h"
79
10+ // Used to store references to the Pyobjects instanced in String() and
11+ // ItemAt() methods. Those can't be DECREF'ed to 0 because libuast uses the
12+ // so we pass ownership to these lists and free them at the end of filter()
13+ static PyObject * stringAllocsList ;
14+ static PyObject * itemAtAllocsList ;
15+
816static PyObject * Attribute (const void * node , const char * prop ) {
917 PyObject * n = (PyObject * )node ;
1018 return PyObject_GetAttrString (n , prop );
@@ -16,20 +24,38 @@ static PyObject *AttributeValue(const void *node, const char *prop) {
1624}
1725
1826static const char * String (const void * node , const char * prop ) {
27+ const char * retval = NULL ;
1928 PyObject * o = Attribute (node , prop );
20- return o ? PyUnicode_AsUTF8 (o ) : NULL ;
29+ if (o != NULL ) {
30+ retval = PyUnicode_AsUTF8 (o );
31+ PyList_Append (stringAllocsList , o );
32+ Py_DECREF (o );
33+ }
34+ return retval ;
2135}
2236
2337static size_t Size (const void * node , const char * prop ) {
38+ size_t retval = 0 ;
2439 PyObject * o = Attribute (node , prop );
25- return o ? PySequence_Size (o ) : 0 ;
40+ if (o != NULL ) {
41+ retval = PySequence_Size (o );
42+ Py_DECREF (o );
43+ }
44+
45+ return retval ;
2646}
2747
2848static PyObject * ItemAt (PyObject * object , int index ) {
49+ PyObject * retval = NULL ;
2950 PyObject * seq = PySequence_Fast (object , "expected a sequence" );
30- return PyList_GET_ITEM (seq , index );
31- }
51+ if (seq != NULL ) {
52+ retval = PyList_GET_ITEM (seq , index );
53+ PyList_Append (itemAtAllocsList , seq );
54+ Py_DECREF (seq );
55+ }
3256
57+ return retval ;
58+ }
3359
3460static const char * InternalType (const void * node ) {
3561 return String (node , "internal_type" );
@@ -68,8 +94,13 @@ static const char *PropertyKeyAt(const void *node, int index) {
6894 return NULL ;
6995 }
7096
97+ const char * retval = NULL ;
7198 PyObject * keys = PyMapping_Keys (properties );
72- return keys ? PyUnicode_AsUTF8 (ItemAt (keys , index )) : NULL ;
99+ if (keys != NULL ) {
100+ retval = PyUnicode_AsUTF8 (ItemAt (keys , index ));
101+ Py_DECREF (keys );
102+ }
103+ return retval ;
73104}
74105
75106static const char * PropertyValueAt (const void * node , int index ) {
@@ -78,8 +109,13 @@ static const char *PropertyValueAt(const void *node, int index) {
78109 return NULL ;
79110 }
80111
112+ const char * retval = NULL ;
81113 PyObject * values = PyMapping_Values (properties );
82- return values ? PyUnicode_AsUTF8 (ItemAt (values , index )) : NULL ;
114+ if (values != NULL ) {
115+ retval = PyUnicode_AsUTF8 (ItemAt (values , index ));
116+ Py_DECREF (values );
117+ }
118+ return retval ;
83119}
84120
85121static uint32_t PositionValue (const void * node , const char * prop , const char * field ) {
@@ -256,14 +292,20 @@ static PyObject *PyFilter(PyObject *self, PyObject *args)
256292 PyObject * obj = NULL ;
257293 const char * query = NULL ;
258294
259- if (!PyArg_ParseTuple (args , "Os" , & obj , & query ))
295+ if (!PyArg_ParseTuple (args , "Os" , & obj , & query )) {
260296 return NULL ;
297+ }
298+
299+ itemAtAllocsList = PyList_New (0 );
300+ stringAllocsList = PyList_New (0 );
261301
262302 Nodes * nodes = UastFilter (ctx , obj , query );
263303 if (!nodes ) {
264304 char * error = LastError ();
265305 PyErr_SetString (PyExc_RuntimeError , error );
266306 free (error );
307+ Py_DECREF (stringAllocsList );
308+ Py_DECREF (itemAtAllocsList );
267309 return NULL ;
268310 }
269311 size_t len = NodesSize (nodes );
@@ -275,7 +317,12 @@ static PyObject *PyFilter(PyObject *self, PyObject *args)
275317 PyList_SET_ITEM (list , i , node );
276318 }
277319 NodesFree (nodes );
278- return PySeqIter_New (list );
320+ PyObject * iter = PySeqIter_New (list );
321+ Py_DECREF (list );
322+
323+ Py_DECREF (itemAtAllocsList );
324+ Py_DECREF (stringAllocsList );
325+ return iter ;
279326}
280327
281328static PyMethodDef extension_methods [] = {
0 commit comments