From: JINMEI Tatuya Date: Wed, 26 Oct 2011 03:42:46 +0000 (-0700) Subject: [1028] fixed leak in Message.get_section X-Git-Tag: perftcpdns_before_epoll~66^2~1^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6060fcf2a39711ba5d842a311ea03a47054f2ffc;p=thirdparty%2Fkea.git [1028] fixed leak in Message.get_section --- diff --git a/src/lib/dns/python/message_python.cc b/src/lib/dns/python/message_python.cc index 23494019c6..3f89634e46 100644 --- a/src/lib/dns/python/message_python.cc +++ b/src/lib/dns/python/message_python.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,7 @@ using namespace std; using namespace isc::dns; using namespace isc::dns::python; using namespace isc::util; +using namespace isc::util::python; // Import pydoc text #include "message_python_inc.cc" @@ -451,6 +453,21 @@ Message_getQuestion(s_Message* self) { return (NULL); } +class RRsetInserter { +public: + RRsetInserter(PyObject* pylist) : pylist_(pylist) {} + void operator()(ConstRRsetPtr rrset) { + if (PyList_Append(pylist_, + PyObjectContainer(createRRsetObject(*rrset)).get()) + == -1) { + isc_throw(PyCPPWrapperException, "PyList_Append failed, " + "probably due to short memory"); + } + } +private: + PyObject* pylist_; +}; + PyObject* Message_getSection(s_Message* self, PyObject* args) { unsigned int section; @@ -460,46 +477,28 @@ Message_getSection(s_Message* self, PyObject* args) { "no valid type in get_section argument"); return (NULL); } - RRsetIterator rrsi, rrsi_end; + try { - rrsi = self->cppobj->beginSection( - static_cast(section)); - rrsi_end = self->cppobj->endSection( - static_cast(section)); + PyObjectContainer list_container(PyList_New(0)); + const Message::Section msgsection = + static_cast(section); + for_each(self->cppobj->beginSection(msgsection), + self->cppobj->endSection(msgsection), + RRsetInserter(list_container.get())); + return (list_container.release()); } catch (const isc::OutOfRange& ex) { PyErr_SetString(PyExc_OverflowError, ex.what()); - return (NULL); } catch (const InvalidMessageSection& ex) { PyErr_SetString(po_InvalidMessageSection, ex.what()); - return (NULL); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in getting section iterators"); - return (NULL); - } - - PyObject* list = PyList_New(0); - if (list == NULL) { - return (NULL); - } - try { - for (; rrsi != rrsi_end; ++rrsi) { - if (PyList_Append(list, createRRsetObject(**rrsi)) == -1) { - Py_DECREF(list); - return (NULL); - } - } - return (list); } catch (const exception& ex) { const string ex_what = - "Unexpected failure creating Question object: " + + "Unexpected failure in Message.get_section: " + string(ex.what()); PyErr_SetString(po_IscException, ex_what.c_str()); } catch (...) { PyErr_SetString(PyExc_SystemError, - "Unexpected failure creating Question object"); + "Unexpected failure in Message.get_section"); } - Py_DECREF(list); return (NULL); } diff --git a/src/lib/dns/python/tests/message_python_test.py b/src/lib/dns/python/tests/message_python_test.py index 8f2d7323f2..dcc26dc5ed 100644 --- a/src/lib/dns/python/tests/message_python_test.py +++ b/src/lib/dns/python/tests/message_python_test.py @@ -17,6 +17,7 @@ # Tests for the message part of the pydnspp module # +import sys import unittest import os from pydnspp import * @@ -230,6 +231,14 @@ class MessageTest(unittest.TestCase): self.assertTrue(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_ANSWER))) self.assertEqual(2, self.r.get_rr_count(Message.SECTION_ANSWER)) + # We always make a new deep copy in get_section(), so the reference + # count of the returned list and its each item should be 1; otherwise + # they would leak. + self.assertEqual(1, sys.getrefcount(self.r.get_section( + Message.SECTION_ANSWER))) + self.assertEqual(1, sys.getrefcount(self.r.get_section( + Message.SECTION_ANSWER)[0])) + self.assertFalse(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_AUTHORITY))) self.assertEqual(0, self.r.get_rr_count(Message.SECTION_AUTHORITY)) self.r.add_rrset(Message.SECTION_AUTHORITY, self.rrset_a)