BIND 10 master, updated. e665914a467810569a22e093a56ff5c711179143 Changelog for #1407

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Nov 29 08:29:43 UTC 2011


The branch, master has been updated
       via  e665914a467810569a22e093a56ff5c711179143 (commit)
       via  5b64e839be2906b8950f5b1e42a3fadd72fca033 (commit)
       via  4dc636c8d46d857f617bfef2ae9444dce438cff4 (commit)
       via  de9532ce586ac69ff58dad2096f23db0cb062639 (commit)
       via  a81436b0c8f9c3974ec3373f586c45e2cf03cb64 (commit)
       via  207038a3ff7503cd2b2ab44238c71da55912bb4a (commit)
       via  5dc772648fb9779359b4d409086d55745afccad9 (commit)
      from  eb06cb8dfea727c5d9366583581ca674d23c4c2e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit e665914a467810569a22e093a56ff5c711179143
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Tue Nov 29 09:27:54 2011 +0100

    Changelog for #1407

commit 5b64e839be2906b8950f5b1e42a3fadd72fca033
Merge: eb06cb8dfea727c5d9366583581ca674d23c4c2e 4dc636c8d46d857f617bfef2ae9444dce438cff4
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Tue Nov 29 09:17:34 2011 +0100

    Merge #1407

commit 4dc636c8d46d857f617bfef2ae9444dce438cff4
Author: JINMEI Tatuya <jinmei at isc.org>
Date:   Mon Nov 28 19:40:04 2011 -0800

    [1407] a minor style cleanup: adding braces for if-else

commit de9532ce586ac69ff58dad2096f23db0cb062639
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Sat Nov 26 13:14:51 2011 +0100

    [1407] Little bit more exception handling

commit a81436b0c8f9c3974ec3373f586c45e2cf03cb64
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Sat Nov 26 12:43:57 2011 +0100

    [1407] Remove reinterpret_casts

commit 207038a3ff7503cd2b2ab44238c71da55912bb4a
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Fri Nov 25 09:35:58 2011 +0100

    [1407] Cleanups

commit 5dc772648fb9779359b4d409086d55745afccad9
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Nov 23 14:09:18 2011 +0100

    [1407] Catch in Rdata_init

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                     |    5 +
 src/lib/dns/python/rdata_python.cc            |  210 +++++++++++++++++--------
 src/lib/dns/python/rrset_python.cc            |   97 ++++++------
 src/lib/dns/python/tests/rdata_python_test.py |    8 +
 4 files changed, 209 insertions(+), 111 deletions(-)

-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index eaec9e9..7644588 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+332.    [bug]		vorner
+	C++ exceptions in the isc.dns.Rdata wrapper are now converted
+	to python ones instead of just aborting the interpretter.
+	(Trac #1407, git 5b64e839be2906b8950f5b1e42a3fadd72fca033)
+
 bind10-devel-20111128 released on November 28, 2011
 
 331.	[bug]		shane
diff --git a/src/lib/dns/python/rdata_python.cc b/src/lib/dns/python/rdata_python.cc
index 06c0263..e4ff890 100644
--- a/src/lib/dns/python/rdata_python.cc
+++ b/src/lib/dns/python/rdata_python.cc
@@ -16,6 +16,7 @@
 #include <Python.h>
 #include <dns/rdata.h>
 #include <dns/messagerenderer.h>
+#include <dns/exceptions.h>
 #include <util/buffer.h>
 #include <util/python/pycppwrapper_util.h>
 
@@ -23,6 +24,7 @@
 #include "rrtype_python.h"
 #include "rrclass_python.h"
 #include "messagerenderer_python.h"
+#include "name_python.h"
 
 using namespace isc::dns;
 using namespace isc::dns::python;
@@ -31,6 +33,27 @@ using namespace isc::util::python;
 using namespace isc::dns::rdata;
 
 namespace {
+
+typedef PyObject* method(PyObject* self, PyObject* args);
+
+// Wrap a method into an exception handling, converting C++ exceptions
+// to python ones. The params and return value is just passed through.
+PyObject*
+exception_wrap(method* method, PyObject* self, PyObject* args) {
+    try {
+        return (method(self, args));
+    } catch (const std::exception& ex) {
+        // FIXME: These exceptions are not tested, I don't know how or if
+        // at all they can be triggered. But they are caught just in the case.
+        PyErr_SetString(PyExc_Exception, (std::string("Unknown exception: ") +
+                        ex.what()).c_str());
+        return (NULL);
+    } catch (...) {
+        PyErr_SetString(PyExc_Exception, "Unknown exception");
+        return (NULL);
+    }
+}
+
 class s_Rdata : public PyObject {
 public:
     isc::dns::rdata::ConstRdataPtr cppobj;
@@ -44,16 +67,16 @@ typedef CPPPyObjectContainer<s_Rdata, Rdata> RdataContainer;
 //
 
 // General creation and destruction
-int Rdata_init(s_Rdata* self, PyObject* args);
-void Rdata_destroy(s_Rdata* self);
+int Rdata_init(PyObject* self, PyObject* args, PyObject*);
+void Rdata_destroy(PyObject* self);
 
 // These are the functions we export
-PyObject* Rdata_toText(s_Rdata* self);
+PyObject* Rdata_toText(PyObject* self, PyObject*);
 // This is a second version of toText, we need one where the argument
 // is a PyObject*, for the str() function in python.
 PyObject* Rdata_str(PyObject* self);
-PyObject* Rdata_toWire(s_Rdata* self, PyObject* args);
-PyObject* RData_richcmp(s_Rdata* self, s_Rdata* other, int op);
+PyObject* Rdata_toWire(PyObject* self, PyObject* args);
+PyObject* RData_richcmp(PyObject* self, PyObject* other, int op);
 
 // This list contains the actual set of functions we have in
 // python. Each entry has
@@ -62,9 +85,9 @@ PyObject* RData_richcmp(s_Rdata* self, s_Rdata* other, int op);
 // 3. Argument type
 // 4. Documentation
 PyMethodDef Rdata_methods[] = {
-    { "to_text", reinterpret_cast<PyCFunction>(Rdata_toText), METH_NOARGS,
+    { "to_text", Rdata_toText, METH_NOARGS,
       "Returns the string representation" },
-    { "to_wire", reinterpret_cast<PyCFunction>(Rdata_toWire), METH_VARARGS,
+    { "to_wire", Rdata_toWire, METH_VARARGS,
       "Converts the Rdata object to wire format.\n"
       "The argument can be either a MessageRenderer or an object that "
       "implements the sequence interface. If the object is mutable "
@@ -75,58 +98,89 @@ PyMethodDef Rdata_methods[] = {
 };
 
 int
-Rdata_init(s_Rdata* self, PyObject* args) {
+Rdata_init(PyObject* self_p, PyObject* args, PyObject*) {
     PyObject* rrtype;
     PyObject* rrclass;
     const char* s;
     const char* data;
     Py_ssize_t len;
+    s_Rdata* self(static_cast<s_Rdata*>(self_p));
 
-    // Create from string
-    if (PyArg_ParseTuple(args, "O!O!s", &rrtype_type, &rrtype,
-                                        &rrclass_type, &rrclass,
-                                        &s)) {
-        self->cppobj = createRdata(PyRRType_ToRRType(rrtype),
-                                   PyRRClass_ToRRClass(rrclass), s);
-        return (0);
-    } else if (PyArg_ParseTuple(args, "O!O!y#", &rrtype_type, &rrtype,
-                                &rrclass_type, &rrclass, &data, &len)) {
-        InputBuffer input_buffer(data, len);
-        self->cppobj = createRdata(PyRRType_ToRRType(rrtype),
-                                   PyRRClass_ToRRClass(rrclass),
-                                   input_buffer, len);
-        return (0);
+    try {
+        // Create from string
+        if (PyArg_ParseTuple(args, "O!O!s", &rrtype_type, &rrtype,
+                             &rrclass_type, &rrclass,
+                             &s)) {
+            self->cppobj = createRdata(PyRRType_ToRRType(rrtype),
+                                       PyRRClass_ToRRClass(rrclass), s);
+            return (0);
+        } else if (PyArg_ParseTuple(args, "O!O!y#", &rrtype_type, &rrtype,
+                                    &rrclass_type, &rrclass, &data, &len)) {
+            InputBuffer input_buffer(data, len);
+            self->cppobj = createRdata(PyRRType_ToRRType(rrtype),
+                                       PyRRClass_ToRRClass(rrclass),
+                                       input_buffer, len);
+            return (0);
+        }
+    } catch (const isc::dns::rdata::InvalidRdataText& irdt) {
+        PyErr_SetString(po_InvalidRdataText, irdt.what());
+        return (-1);
+    } catch (const isc::dns::rdata::InvalidRdataLength& irdl) {
+        PyErr_SetString(po_InvalidRdataLength, irdl.what());
+        return (-1);
+    } catch (const isc::dns::rdata::CharStringTooLong& cstl) {
+        PyErr_SetString(po_CharStringTooLong, cstl.what());
+        return (-1);
+    } catch (const isc::dns::DNSMessageFORMERR& dmfe) {
+        PyErr_SetString(po_DNSMessageFORMERR, dmfe.what());
+        return (-1);
+    } catch (const std::exception& ex) {
+        // FIXME: These exceptions are not tested, I don't know how or if
+        // at all they can be triggered. But they are caught just in the case.
+        PyErr_SetString(PyExc_Exception, (std::string("Unknown exception: ") +
+                        ex.what()).c_str());
+        return (-1);
+    } catch (...) {
+        PyErr_SetString(PyExc_Exception, "Unknown exception");
+        return (-1);
     }
 
     return (-1);
 }
 
 void
-Rdata_destroy(s_Rdata* self) {
+Rdata_destroy(PyObject* self) {
     // Clear the shared_ptr so that its reference count is zero
     // before we call tp_free() (there is no direct release())
-    self->cppobj.reset();
+    static_cast<s_Rdata*>(self)->cppobj.reset();
     Py_TYPE(self)->tp_free(self);
 }
 
 PyObject*
-Rdata_toText(s_Rdata* self) {
+Rdata_toText_internal(PyObject* self, PyObject*) {
     // Py_BuildValue makes python objects from native data
-    return (Py_BuildValue("s", self->cppobj->toText().c_str()));
+    return (Py_BuildValue("s", static_cast<const s_Rdata*>(self)->cppobj->
+                          toText().c_str()));
+}
+
+PyObject*
+Rdata_toText(PyObject* self, PyObject* args) {
+    return (exception_wrap(&Rdata_toText_internal, self, args));
 }
 
 PyObject*
 Rdata_str(PyObject* self) {
     // Simply call the to_text method we already defined
     return (PyObject_CallMethod(self,
-                               const_cast<char*>("to_text"),
+                                const_cast<char*>("to_text"),
                                 const_cast<char*>("")));
 }
 
 PyObject*
-Rdata_toWire(s_Rdata* self, PyObject* args) {
+Rdata_toWire_internal(PyObject* self_p, PyObject* args) {
     PyObject* bytes;
     PyObject* mr;
+    const s_Rdata* self(static_cast<const s_Rdata*>(self_p));
 
     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
@@ -134,6 +188,11 @@ Rdata_toWire(s_Rdata* self, PyObject* args) {
         OutputBuffer buffer(4);
         self->cppobj->toWire(buffer);
         PyObject* rd_bytes = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
+        // Make sure exceptions from here are propagated.
+        // The exception is already set, so we just return NULL
+        if (rd_bytes == NULL) {
+            return (NULL);
+        }
         PyObject* result = PySequence_InPlaceConcat(bytes_o, rd_bytes);
         // We need to release the object we temporarily created here
         // to prevent memory leak
@@ -152,45 +211,64 @@ Rdata_toWire(s_Rdata* self, PyObject* args) {
 }
 
 PyObject*
-RData_richcmp(s_Rdata* self, s_Rdata* other, int op) {
-    bool c;
+Rdata_toWire(PyObject* self, PyObject* args) {
+    return (exception_wrap(&Rdata_toWire_internal, self, args));
+}
+
+PyObject*
+RData_richcmp(PyObject* self_p, PyObject* other_p, int op) {
+    try {
+        bool c;
+        const s_Rdata* self(static_cast<const s_Rdata*>(self_p)),
+              * other(static_cast<const s_Rdata*>(other_p));
 
-    // Check for null and if the types match. If different type,
-    // simply return False
-    if (!other || (self->ob_type != other->ob_type)) {
-        Py_RETURN_FALSE;
-    }
+        // Check for null and if the types match. If different type,
+        // simply return False
+        if (!other || (self->ob_type != other->ob_type)) {
+            Py_RETURN_FALSE;
+        }
 
-    switch (op) {
-    case Py_LT:
-        c = self->cppobj->compare(*other->cppobj) < 0;
-        break;
-    case Py_LE:
-        c = self->cppobj->compare(*other->cppobj) < 0 ||
-            self->cppobj->compare(*other->cppobj) == 0;
-        break;
-    case Py_EQ:
-        c = self->cppobj->compare(*other->cppobj) == 0;
-        break;
-    case Py_NE:
-        c = self->cppobj->compare(*other->cppobj) != 0;
-        break;
-    case Py_GT:
-        c = self->cppobj->compare(*other->cppobj) > 0;
-        break;
-    case Py_GE:
-        c = self->cppobj->compare(*other->cppobj) > 0 ||
-            self->cppobj->compare(*other->cppobj) == 0;
-        break;
-    default:
-        PyErr_SetString(PyExc_IndexError,
-                        "Unhandled rich comparison operator");
+        switch (op) {
+            case Py_LT:
+                c = self->cppobj->compare(*other->cppobj) < 0;
+                break;
+            case Py_LE:
+                c = self->cppobj->compare(*other->cppobj) < 0 ||
+                    self->cppobj->compare(*other->cppobj) == 0;
+                break;
+            case Py_EQ:
+                c = self->cppobj->compare(*other->cppobj) == 0;
+                break;
+            case Py_NE:
+                c = self->cppobj->compare(*other->cppobj) != 0;
+                break;
+            case Py_GT:
+                c = self->cppobj->compare(*other->cppobj) > 0;
+                break;
+            case Py_GE:
+                c = self->cppobj->compare(*other->cppobj) > 0 ||
+                    self->cppobj->compare(*other->cppobj) == 0;
+                break;
+            default:
+                PyErr_SetString(PyExc_IndexError,
+                                "Unhandled rich comparison operator");
+                return (NULL);
+        }
+        if (c) {
+            Py_RETURN_TRUE;
+        } else {
+            Py_RETURN_FALSE;
+        }
+    } catch (const std::exception& ex) {
+        // FIXME: These exceptions are not tested, I don't know how or if
+        // at all they can be triggered. But they are caught just in the case.
+        PyErr_SetString(PyExc_Exception, (std::string("Unknown exception: ") +
+                        ex.what()).c_str());
+        return (NULL);
+    } catch (...) {
+        PyErr_SetString(PyExc_Exception, "Unknown exception");
         return (NULL);
     }
-    if (c)
-        Py_RETURN_TRUE;
-    else
-        Py_RETURN_FALSE;
 }
 
 } // end of unnamed namespace
@@ -217,7 +295,7 @@ PyTypeObject rdata_type = {
     "pydnspp.Rdata",
     sizeof(s_Rdata),                    // tp_basicsize
     0,                                  // tp_itemsize
-    (destructor)Rdata_destroy,          // tp_dealloc
+    Rdata_destroy,                      // tp_dealloc
     NULL,                               // tp_print
     NULL,                               // tp_getattr
     NULL,                               // tp_setattr
@@ -237,7 +315,7 @@ PyTypeObject rdata_type = {
     "a set of common interfaces to manipulate concrete RDATA objects.",
     NULL,                               // tp_traverse
     NULL,                               // tp_clear
-    (richcmpfunc)RData_richcmp,         // tp_richcompare
+    RData_richcmp,                      // tp_richcompare
     0,                                  // tp_weaklistoffset
     NULL,                               // tp_iter
     NULL,                               // tp_iternext
@@ -249,7 +327,7 @@ PyTypeObject rdata_type = {
     NULL,                               // tp_descr_get
     NULL,                               // tp_descr_set
     0,                                  // tp_dictoffset
-    (initproc)Rdata_init,               // tp_init
+    Rdata_init,                         // tp_init
     NULL,                               // tp_alloc
     PyType_GenericNew,                  // tp_new
     NULL,                               // tp_free
diff --git a/src/lib/dns/python/rrset_python.cc b/src/lib/dns/python/rrset_python.cc
index 73a19e7..77d520b 100644
--- a/src/lib/dns/python/rrset_python.cc
+++ b/src/lib/dns/python/rrset_python.cc
@@ -52,51 +52,51 @@ public:
 int RRset_init(s_RRset* self, PyObject* args);
 void RRset_destroy(s_RRset* self);
 
-PyObject* RRset_getRdataCount(s_RRset* self);
-PyObject* RRset_getName(s_RRset* self);
-PyObject* RRset_getClass(s_RRset* self);
-PyObject* RRset_getType(s_RRset* self);
-PyObject* RRset_getTTL(s_RRset* self);
-PyObject* RRset_setName(s_RRset* self, PyObject* args);
-PyObject* RRset_setTTL(s_RRset* self, PyObject* args);
-PyObject* RRset_toText(s_RRset* self);
+PyObject* RRset_getRdataCount(PyObject* self, PyObject* args);
+PyObject* RRset_getName(PyObject* self, PyObject* args);
+PyObject* RRset_getClass(PyObject* self, PyObject* args);
+PyObject* RRset_getType(PyObject* self, PyObject* args);
+PyObject* RRset_getTTL(PyObject* self, PyObject* args);
+PyObject* RRset_setName(PyObject* self, PyObject* args);
+PyObject* RRset_setTTL(PyObject* self, PyObject* args);
+PyObject* RRset_toText(PyObject* self, PyObject* args);
 PyObject* RRset_str(PyObject* self);
-PyObject* RRset_toWire(s_RRset* self, PyObject* args);
-PyObject* RRset_addRdata(s_RRset* self, PyObject* args);
-PyObject* RRset_getRdata(PyObject* po_self, PyObject*);
-PyObject* RRset_removeRRsig(s_RRset* self);
+PyObject* RRset_toWire(PyObject* self, PyObject* args);
+PyObject* RRset_addRdata(PyObject* self, PyObject* args);
+PyObject* RRset_getRdata(PyObject* po_self, PyObject* args);
+PyObject* RRset_removeRRsig(PyObject* self, PyObject* args);
 
 // TODO: iterator?
 
 PyMethodDef RRset_methods[] = {
-    { "get_rdata_count", reinterpret_cast<PyCFunction>(RRset_getRdataCount), METH_NOARGS,
+    { "get_rdata_count", RRset_getRdataCount, METH_NOARGS,
       "Returns the number of rdata fields." },
-    { "get_name", reinterpret_cast<PyCFunction>(RRset_getName), METH_NOARGS,
+    { "get_name", RRset_getName, METH_NOARGS,
       "Returns the name of the RRset, as a Name object." },
-    { "get_class", reinterpret_cast<PyCFunction>(RRset_getClass), METH_NOARGS,
+    { "get_class", RRset_getClass, METH_NOARGS,
       "Returns the class of the RRset as an RRClass object." },
-    { "get_type", reinterpret_cast<PyCFunction>(RRset_getType), METH_NOARGS,
+    { "get_type", RRset_getType, METH_NOARGS,
       "Returns the type of the RRset as an RRType object." },
-    { "get_ttl", reinterpret_cast<PyCFunction>(RRset_getTTL), METH_NOARGS,
+    { "get_ttl", RRset_getTTL, METH_NOARGS,
       "Returns the TTL of the RRset as an RRTTL object." },
-    { "set_name", reinterpret_cast<PyCFunction>(RRset_setName), METH_VARARGS,
+    { "set_name", RRset_setName, METH_VARARGS,
       "Sets the name of the RRset.\nTakes a Name object as an argument." },
-    { "set_ttl", reinterpret_cast<PyCFunction>(RRset_setTTL), METH_VARARGS,
+    { "set_ttl", RRset_setTTL, METH_VARARGS,
       "Sets the TTL of the RRset.\nTakes an RRTTL object as an argument." },
-    { "to_text", reinterpret_cast<PyCFunction>(RRset_toText), METH_NOARGS,
+    { "to_text", RRset_toText, METH_NOARGS,
       "Returns the text representation of the RRset as a string" },
-    { "to_wire", reinterpret_cast<PyCFunction>(RRset_toWire), METH_VARARGS,
+    { "to_wire", RRset_toWire, METH_VARARGS,
       "Converts the RRset object to wire format.\n"
       "The argument can be either a MessageRenderer or an object that "
       "implements the sequence interface. If the object is mutable "
       "(for instance a bytearray()), the wire data is added in-place.\n"
       "If it is not (for instance a bytes() object), a new object is "
       "returned" },
-    { "add_rdata", reinterpret_cast<PyCFunction>(RRset_addRdata), METH_VARARGS,
+    { "add_rdata", RRset_addRdata, METH_VARARGS,
       "Adds the rdata for one RR to the RRset.\nTakes an Rdata object as an argument" },
     { "get_rdata", RRset_getRdata, METH_NOARGS,
       "Returns a List containing all Rdata elements" },
-    { "remove_rrsig", reinterpret_cast<PyCFunction>(RRset_removeRRsig), METH_NOARGS,
+    { "remove_rrsig", RRset_removeRRsig, METH_NOARGS,
       "Clears the list of RRsigs for this RRset" },
     { NULL, NULL, 0, NULL }
 };
@@ -133,14 +133,16 @@ RRset_destroy(s_RRset* self) {
 }
 
 PyObject*
-RRset_getRdataCount(s_RRset* self) {
-    return (Py_BuildValue("I", self->cppobj->getRdataCount()));
+RRset_getRdataCount(PyObject* self, PyObject*) {
+    return (Py_BuildValue("I", static_cast<const s_RRset*>(self)->cppobj->
+                          getRdataCount()));
 }
 
 PyObject*
-RRset_getName(s_RRset* self) {
+RRset_getName(PyObject* self, PyObject*) {
     try {
-        return (createNameObject(self->cppobj->getName()));
+        return (createNameObject(static_cast<const s_RRset*>(self)->cppobj->
+                                 getName()));
     } catch (const exception& ex) {
         const string ex_what =
             "Unexpected failure getting rrset Name: " +
@@ -154,9 +156,10 @@ RRset_getName(s_RRset* self) {
 }
 
 PyObject*
-RRset_getClass(s_RRset* self) {
+RRset_getClass(PyObject* self, PyObject*) {
     try {
-        return (createRRClassObject(self->cppobj->getClass()));
+        return (createRRClassObject(static_cast<const s_RRset*>(self)->cppobj->
+                                    getClass()));
     } catch (const exception& ex) {
         const string ex_what =
             "Unexpected failure getting question RRClass: " +
@@ -170,9 +173,10 @@ RRset_getClass(s_RRset* self) {
 }
 
 PyObject*
-RRset_getType(s_RRset* self) {
+RRset_getType(PyObject* self, PyObject*) {
     try {
-        return (createRRTypeObject(self->cppobj->getType()));
+        return (createRRTypeObject(static_cast<const s_RRset*>(self)->cppobj->
+                                   getType()));
     } catch (const exception& ex) {
         const string ex_what =
             "Unexpected failure getting question RRType: " +
@@ -186,9 +190,10 @@ RRset_getType(s_RRset* self) {
 }
 
 PyObject*
-RRset_getTTL(s_RRset* self) {
+RRset_getTTL(PyObject* self, PyObject*) {
     try {
-        return (createRRTTLObject(self->cppobj->getTTL()));
+        return (createRRTTLObject(static_cast<const s_RRset*>(self)->cppobj->
+                                  getTTL()));
     } catch (const exception& ex) {
         const string ex_what =
             "Unexpected failure getting question TTL: " +
@@ -202,29 +207,30 @@ RRset_getTTL(s_RRset* self) {
 }
 
 PyObject*
-RRset_setName(s_RRset* self, PyObject* args) {
+RRset_setName(PyObject* self, PyObject* args) {
     PyObject* name;
     if (!PyArg_ParseTuple(args, "O!", &name_type, &name)) {
         return (NULL);
     }
-    self->cppobj->setName(PyName_ToName(name));
+    static_cast<s_RRset*>(self)->cppobj->setName(PyName_ToName(name));
     Py_RETURN_NONE;
 }
 
 PyObject*
-RRset_setTTL(s_RRset* self, PyObject* args) {
+RRset_setTTL(PyObject* self, PyObject* args) {
     PyObject* rrttl;
     if (!PyArg_ParseTuple(args, "O!", &rrttl_type, &rrttl)) {
         return (NULL);
     }
-    self->cppobj->setTTL(PyRRTTL_ToRRTTL(rrttl));
+    static_cast<s_RRset*>(self)->cppobj->setTTL(PyRRTTL_ToRRTTL(rrttl));
     Py_RETURN_NONE;
 }
 
 PyObject*
-RRset_toText(s_RRset* self) {
+RRset_toText(PyObject* self, PyObject*) {
     try {
-        return (Py_BuildValue("s", self->cppobj->toText().c_str()));
+        return (Py_BuildValue("s", static_cast<const s_RRset*>(self)->cppobj->
+                              toText().c_str()));
     } catch (const EmptyRRset& ers) {
         PyErr_SetString(po_EmptyRRset, ers.what());
         return (NULL);
@@ -235,14 +241,15 @@ PyObject*
 RRset_str(PyObject* self) {
     // Simply call the to_text method we already defined
     return (PyObject_CallMethod(self,
-                               const_cast<char*>("to_text"),
+                                const_cast<char*>("to_text"),
                                 const_cast<char*>("")));
 }
 
 PyObject*
-RRset_toWire(s_RRset* self, PyObject* args) {
+RRset_toWire(PyObject* self_p, PyObject* args) {
     PyObject* bytes;
     PyObject* mr;
+    const s_RRset* self(static_cast<const s_RRset*>(self_p));
 
     try {
         if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
@@ -274,13 +281,13 @@ RRset_toWire(s_RRset* self, PyObject* args) {
 }
 
 PyObject*
-RRset_addRdata(s_RRset* self, PyObject* args) {
+RRset_addRdata(PyObject* self, PyObject* args) {
     PyObject* rdata;
     if (!PyArg_ParseTuple(args, "O!", &rdata_type, &rdata)) {
         return (NULL);
     }
     try {
-        self->cppobj->addRdata(PyRdata_ToRdata(rdata));
+        static_cast<s_RRset*>(self)->cppobj->addRdata(PyRdata_ToRdata(rdata));
         Py_RETURN_NONE;
     } catch (const std::bad_cast&) {
         PyErr_Clear();
@@ -324,8 +331,8 @@ RRset_getRdata(PyObject* po_self, PyObject*) {
 }
 
 PyObject*
-RRset_removeRRsig(s_RRset* self) {
-    self->cppobj->removeRRsig();
+RRset_removeRRsig(PyObject* self, PyObject*) {
+    static_cast<s_RRset*>(self)->cppobj->removeRRsig();
     Py_RETURN_NONE;
 }
 
diff --git a/src/lib/dns/python/tests/rdata_python_test.py b/src/lib/dns/python/tests/rdata_python_test.py
index 776f792..81dea5f 100644
--- a/src/lib/dns/python/tests/rdata_python_test.py
+++ b/src/lib/dns/python/tests/rdata_python_test.py
@@ -35,6 +35,14 @@ class RdataTest(unittest.TestCase):
         self.assertRaises(TypeError, Rdata, "wrong", RRClass("IN"), "192.0.2.99")
         self.assertRaises(TypeError, Rdata, RRType("A"), "wrong", "192.0.2.99")
         self.assertRaises(TypeError, Rdata, RRType("A"), RRClass("IN"), 1)
+        self.assertRaises(InvalidRdataText, Rdata, RRType("A"), RRClass("IN"),
+                          "Invalid Rdata Text")
+        self.assertRaises(CharStringTooLong, Rdata, RRType("TXT"),
+                          RRClass("IN"), ' ' * 256)
+        self.assertRaises(InvalidRdataLength, Rdata, RRType("TXT"),
+                          RRClass("IN"), bytes(65536))
+        self.assertRaises(DNSMessageFORMERR, Rdata, RRType("TXT"),
+                          RRClass("IN"), b"\xff")
 
     def test_rdata_to_wire(self):
         b = bytearray()




More information about the bind10-changes mailing list