Browse Source

[trac363] use larger size type for PyArg_ParseTuple()

chenzhengzhang 14 years ago
parent
commit
3e6c2a9c09

+ 7 - 3
src/lib/dns/python/edns_python.cc

@@ -297,11 +297,15 @@ EDNS_getUDPSize(const s_EDNS* const self) {
 
 PyObject*
 EDNS_setUDPSize(s_EDNS* self, PyObject* args) {
-    unsigned int size;
-    if (!PyArg_ParseTuple(args, "I", &size)) {
+    long size;
+    if (!PyArg_ParseTuple(args, "l", &size)) {
+        PyErr_Clear();
+        PyErr_SetString(PyExc_TypeError,
+                        "No valid type in set_udp_size argument");
         return (NULL);
     }
-    if (size > 65535) {
+    if (size < 0 || size > 0xffff) {
+        PyErr_Clear();
         PyErr_SetString(PyExc_OverflowError,
                         "UDP size is not an unsigned 16-bit integer");
         return (NULL);

+ 28 - 12
src/lib/dns/python/message_python.cc

@@ -226,9 +226,9 @@ static PyTypeObject message_type = {
 
 static int
 Message_init(s_Message* self, PyObject* args) {
-    unsigned int i;
+    long i;
     
-    if (PyArg_ParseTuple(args, "I", &i)) {
+    if (PyArg_ParseTuple(args, "l", &i)) {
         PyErr_Clear();
         if (i == Message::PARSE) {
             self->message = new Message(Message::PARSE);
@@ -274,17 +274,18 @@ Message_getHeaderFlag(s_Message* self, PyObject* args) {
 
 static PyObject*
 Message_setHeaderFlag(s_Message* self, PyObject* args) {
-    int messageflag;
+    long messageflag;
     PyObject *on = Py_True;
 
-    if (!PyArg_ParseTuple(args, "i|O!", &messageflag, &PyBool_Type, &on)) {
+    if (!PyArg_ParseTuple(args, "l|O!", &messageflag, &PyBool_Type, &on)) {
         PyErr_Clear();
         PyErr_SetString(PyExc_TypeError,
                         "no valid type in set_header_flag argument");
         return (NULL);
     }
-    if (messageflag < 0) {
-        PyErr_SetString(PyExc_TypeError, "invalid Message header flag");
+    if (messageflag < 0 || messageflag > 0xffff) {
+        PyErr_Clear();
+        PyErr_SetString(PyExc_OverflowError, "Message header flag out of range");
         return (NULL);
     }
 
@@ -310,10 +311,20 @@ Message_getQid(s_Message* self) {
 
 static PyObject*
 Message_setQid(s_Message* self, PyObject* args) {
-    uint16_t id;
-    if (!PyArg_ParseTuple(args, "H", &id)) {
+    int id;
+    if (!PyArg_ParseTuple(args, "i", &id)) {
+        PyErr_Clear();
+        PyErr_SetString(PyExc_TypeError,
+                        "no valid type in set_qid argument");
+        return (NULL);
+    }
+    if (id < 0 || id > 0xffff) {
+        PyErr_Clear();
+        PyErr_SetString(PyExc_OverflowError,
+                        "Message id out of range");
         return (NULL);
     }
+
     try {
         self->message->setQid(id);
         Py_RETURN_NONE;
@@ -565,12 +576,17 @@ Message_addQuestion(s_Message* self, PyObject* args) {
 static PyObject*
 Message_addRRset(s_Message* self, PyObject* args) {
     PyObject *sign = Py_False;
-    unsigned int section;
+    int section;
     s_RRset* rrset;
-    if (!PyArg_ParseTuple(args, "IO!|O!", &section, &rrset_type, &rrset,
+    if (!PyArg_ParseTuple(args, "iO!|O!", &section, &rrset_type, &rrset,
                           &PyBool_Type, &sign)) {
         return (NULL);
     }
+    if (section < 0 || section > 3) {
+        PyErr_Clear();
+        PyErr_SetString(PyExc_OverflowError, "Message section number out of range");
+        return (NULL);
+    }
 
     try {
         self->message->addRRset(static_cast<Message::Section>(section),
@@ -591,8 +607,8 @@ Message_addRRset(s_Message* self, PyObject* args) {
 
 static PyObject*
 Message_clear(s_Message* self, PyObject* args) {
-    unsigned int i;
-    if (PyArg_ParseTuple(args, "I", &i)) {
+    long i;
+    if (PyArg_ParseTuple(args, "l", &i)) {
         PyErr_Clear();
         if (i == Message::PARSE) {
             self->message->clear(Message::PARSE);

+ 13 - 4
src/lib/dns/python/messagerenderer_python.cc

@@ -178,8 +178,17 @@ static PyObject*
 MessageRenderer_setLengthLimit(s_MessageRenderer* self,
                                PyObject* args)
 {
-    unsigned int lengthlimit;
-    if (!PyArg_ParseTuple(args, "I", &lengthlimit)) {
+    long lengthlimit;
+    if (!PyArg_ParseTuple(args, "l", &lengthlimit)) {
+        PyErr_Clear();
+        PyErr_SetString(PyExc_TypeError,
+                        "No valid type in set_length_limit argument");
+        return (NULL);
+    }
+    if (lengthlimit < 0 || lengthlimit > 0xffff) {
+        PyErr_Clear();
+        PyErr_SetString(PyExc_OverflowError,
+                        "MessageRenderer length limit out of range");
         return (NULL);
     }
     self->messagerenderer->setLengthLimit(lengthlimit);
@@ -190,8 +199,8 @@ static PyObject*
 MessageRenderer_setCompressMode(s_MessageRenderer* self,
                                PyObject* args)
 {
-    unsigned int mode;
-    if (!PyArg_ParseTuple(args, "I", &mode)) {
+    long mode;
+    if (!PyArg_ParseTuple(args, "l", &mode)) {
         return (NULL);
     }
 

+ 37 - 8
src/lib/dns/python/name_python.cc

@@ -321,14 +321,20 @@ Name_init(s_Name* self, PyObject* args) {
     PyObject* bytes_obj;
     const char* bytes;
     Py_ssize_t len;
-    unsigned int position = 0;
+    long position = 0;
 
     // It was not a string (see comment above), so try bytes, and
     // create with buffer object
-    if (PyArg_ParseTuple(args, "O|IO!", &bytes_obj, &position,
+    if (PyArg_ParseTuple(args, "O|lO!", &bytes_obj, &position,
                          &PyBool_Type, &downcase) &&
                          PyObject_AsCharBuffer(bytes_obj, &bytes, &len) != -1) {
         try {
+            if (position < 0 || position > 0xffff) {
+                PyErr_Clear();
+                PyErr_SetString(PyExc_OverflowError,
+                                "Name index out of range");
+                return (-1);
+            }
             InputBuffer buffer(bytes, len);
 
             buffer.setPosition(position);
@@ -363,10 +369,17 @@ Name_destroy(s_Name* self) {
 
 static PyObject*
 Name_at(s_Name* self, PyObject* args) {
-    unsigned int pos;
-    if (!PyArg_ParseTuple(args, "I", &pos)) {
+    long pos;
+    if (!PyArg_ParseTuple(args, "l", &pos)) {
+        return (NULL);
+    }
+    if (pos < 0 || pos > 0xffff) {
+        PyErr_Clear();
+        PyErr_SetString(PyExc_OverflowError,
+                        "name index out of range");
         return (NULL);
     }
+
     try {
         return (Py_BuildValue("I", self->name->at(pos)));
     } catch (const isc::OutOfRange&) {
@@ -459,10 +472,16 @@ Name_equals(s_Name* self, PyObject* args) {
 
 static PyObject* 
 Name_split(s_Name* self, PyObject* args) {
-    unsigned int first, n;
+    long first, n;
     s_Name* ret = NULL;
-    
-    if (PyArg_ParseTuple(args, "II", &first, &n)) {
+
+    if (PyArg_ParseTuple(args, "ll", &first, &n)) {
+        if (first < 0 || first > 0xffff || n < 0 || n > 0xffff) {
+            PyErr_Clear();
+            PyErr_SetString(PyExc_OverflowError,
+                            "name index out of range");
+            return (NULL);
+        }
         ret = PyObject_New(s_Name, &name_type);
         if (ret != NULL) {
             ret->name = NULL;
@@ -477,7 +496,13 @@ Name_split(s_Name* self, PyObject* args) {
                 return (NULL);
             }
         }
-    } else if (PyArg_ParseTuple(args, "I", &n)) {
+    } else if (PyArg_ParseTuple(args, "l", &n)) {
+        if (n < 0 || n > 0xffff) {
+            PyErr_Clear();
+            PyErr_SetString(PyExc_OverflowError,
+                            "name index out of range");
+            return (NULL);
+        }
         ret = PyObject_New(s_Name, &name_type);
         if (ret != NULL) {
             ret->name = NULL;
@@ -493,6 +518,10 @@ Name_split(s_Name* self, PyObject* args) {
             }
         }
     }
+
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "No valid type in split argument");
     return (ret);
 }
 #include <iostream>

+ 1 - 1
src/lib/dns/python/question_python.cc

@@ -169,7 +169,7 @@ Question_init(s_Question* self, PyObject* args) {
     }
 
     self->question = QuestionPtr();
-    
+
     PyErr_Clear();
     PyErr_SetString(PyExc_TypeError,
                     "no valid type in constructor argument");

+ 4 - 4
src/lib/dns/python/rcode_python.cc

@@ -171,16 +171,16 @@ PyTypeObject rcode_type = {
 
 int
 Rcode_init(s_Rcode* const self, PyObject* args) {
-    int code = 0;
-    int ext_code = 0;
+    long code = 0;
+    long ext_code = 0;
 
-    if (PyArg_ParseTuple(args, "i", &code)) {
+    if (PyArg_ParseTuple(args, "l", &code)) {
         if (code < 0 || code > 0xffff) {
             PyErr_SetString(PyExc_OverflowError, "Rcode out of range");
             return (-1);
         }
         ext_code = -1;
-    } else if (PyArg_ParseTuple(args, "ii", &code, &ext_code)) {
+    } else if (PyArg_ParseTuple(args, "ll", &code, &ext_code)) {
         if (code < 0 || code > 0xff || ext_code < 0 || ext_code > 0xff) {
             PyErr_SetString(PyExc_OverflowError, "Rcode out of range");
             return (-1);

+ 6 - 5
src/lib/dns/python/rrclass_python.cc

@@ -152,7 +152,7 @@ static PyTypeObject rrclass_type = {
 static int
 RRClass_init(s_RRClass* self, PyObject* args) {
     const char* s;
-    unsigned int i;
+    long i;
     PyObject* bytes = NULL;
     // The constructor argument can be a string ("IN"), an integer (1),
     // or a sequence of numbers between 0 and 65535 (wire code)
@@ -165,10 +165,11 @@ RRClass_init(s_RRClass* self, PyObject* args) {
         if (PyArg_ParseTuple(args, "s", &s)) {
             self->rrclass = new RRClass(s);
             return (0);
-        } else if (PyArg_ParseTuple(args, "I", &i)) {
-            PyErr_Clear();
-            if (i > 65535) {
-                PyErr_SetString(po_InvalidRRClass, "RR class number too high");
+        } else if (PyArg_ParseTuple(args, "l", &i)) {
+            if (i < 0 || i > 0xffff) {
+                PyErr_Clear();
+                PyErr_SetString(PyExc_OverflowError,
+                                "RR class number out of range");
                 return (-1);
             }
             self->rrclass = new RRClass(i);

+ 5 - 1
src/lib/dns/python/rrttl_python.cc

@@ -158,8 +158,12 @@ RRTTL_init(s_RRTTL* self, PyObject* args) {
         if (PyArg_ParseTuple(args, "s", &s)) {
             self->rrttl = new RRTTL(s);
             return (0);
-        } else if (PyArg_ParseTuple(args, "I", &i)) {
+        } else if (PyArg_ParseTuple(args, "k", &i)) {
             PyErr_Clear();
+            if (i > 0xffffffff) {
+                PyErr_SetString(po_InvalidRRTTL, "RR TTL number out of range");
+                return (-1);
+            }
             self->rrttl = new RRTTL(i);
             return (0);
         } else if (PyArg_ParseTuple(args, "O", &bytes) &&

+ 4 - 4
src/lib/dns/python/rrtype_python.cc

@@ -182,7 +182,7 @@ static PyTypeObject rrtype_type = {
 static int
 RRType_init(s_RRType* self, PyObject* args) {
     const char* s;
-    unsigned int i;
+    long i;
     PyObject* bytes = NULL;
     // The constructor argument can be a string ("A"), an integer (1),
     // or a sequence of numbers between 0 and 65535 (wire code)
@@ -195,10 +195,10 @@ RRType_init(s_RRType* self, PyObject* args) {
         if (PyArg_ParseTuple(args, "s", &s)) {
             self->rrtype = new RRType(s);
             return (0);
-        } else if (PyArg_ParseTuple(args, "I", &i)) {
+        } else if (PyArg_ParseTuple(args, "l", &i)) {
             PyErr_Clear();
-            if (i > 65535) {
-                PyErr_SetString(po_InvalidRRType, "RR Type number too high");
+            if (i < 0 || i > 0xffff) {
+                PyErr_SetString(PyExc_OverflowError, "RR Type number out of range");
                 return (-1);
             }
             self->rrtype = new RRType(i);

+ 1 - 1
src/lib/dns/python/tests/edns_python_test.py

@@ -71,7 +71,7 @@ class EDNSTest(unittest.TestCase):
 
         # Range check.  We need to do this at the binding level, so we need
         # explicit tests for it.
-        self.assertRaises(OverflowError, edns.set_udp_size, 65536)
+        self.assertRaises(OverflowError, edns.set_udp_size, 0x10000)
         self.assertRaises(OverflowError, edns.set_udp_size, -1)
 
     def test_get_version(self):

+ 10 - 3
src/lib/dns/python/tests/message_python_test.py

@@ -80,8 +80,10 @@ class MessageTest(unittest.TestCase):
                                         "2001:db8::134"))
 
         self.bogus_section = Message.SECTION_ADDITIONAL + 1
+        self.bogus_below_section = Message.SECTION_QUESTION - 1
 
     def test_init(self):
+        self.assertRaises(TypeError, Message, -1)
         self.assertRaises(TypeError, Message, 3)
         self.assertRaises(TypeError, Message, "wrong")
 
@@ -109,20 +111,23 @@ class MessageTest(unittest.TestCase):
         self.assertRaises(InvalidParameter, self.r.set_header_flag, 0)
         self.assertRaises(InvalidParameter, self.r.set_header_flag, 0x7000)
         self.assertRaises(InvalidParameter, self.r.set_header_flag, 0x0800)
-        self.assertRaises(InvalidParameter, self.r.set_header_flag, 0x10000)
         self.assertRaises(TypeError, self.r.set_header_flag, 0x80000000)
-        # this would cause overflow and result in a "valid" flag
         self.assertRaises(TypeError, self.r.set_header_flag,
                           Message.HEADERFLAG_AA | 0x100000000)
-        self.assertRaises(TypeError, self.r.set_header_flag, -1)
+        # this would cause overflow and result in a "valid" flag
+        self.assertRaises(OverflowError, self.r.set_header_flag, 0x10000)
+        self.assertRaises(OverflowError, self.r.set_header_flag, -1)
 
         self.assertRaises(InvalidMessageOperation,
                           self.p.set_header_flag, Message.HEADERFLAG_AA)
 
     def test_set_qid(self):
         self.assertRaises(TypeError, self.r.set_qid, "wrong")
+        self.assertRaises(OverflowError, self.r.set_qid, -1)
+        self.assertRaises(OverflowError, self.r.set_qid, 0x10000)
         self.assertRaises(InvalidMessageOperation,
                           self.p.set_qid, 123)
+
         self.r.set_qid(1234)
         self.assertEqual(1234, self.r.get_qid())
 
@@ -239,6 +244,8 @@ class MessageTest(unittest.TestCase):
                           Message.SECTION_ANSWER, self.rrset_a)
         self.assertRaises(OverflowError, self.r.add_rrset,
                           self.bogus_section, self.rrset_a)
+        self.assertRaises(OverflowError, self.r.add_rrset,
+                          self.bogus_below_section, self.rrset_a)
 
     def test_clear(self):
         self.assertEqual(None, self.r.clear(Message.PARSE))

+ 2 - 0
src/lib/dns/python/tests/messagerenderer_python_test.py

@@ -98,6 +98,8 @@ class MessageRendererTest(unittest.TestCase):
         renderer.set_length_limit(1024)
         self.assertEqual(1024, renderer.get_length_limit())
         self.assertRaises(TypeError, renderer.set_length_limit, "wrong")
+        self.assertRaises(OverflowError, renderer.set_length_limit, -1)
+        self.assertRaises(OverflowError, renderer.set_length_limit, 0x10000)
 
     def test_messagerenderer_set_compress_mode(self):
         renderer = MessageRenderer()

+ 12 - 1
src/lib/dns/python/tests/name_python_test.py

@@ -95,12 +95,16 @@ class NameTest(unittest.TestCase):
         b = bytearray()
         b += b'\x07example'*32 + b'\x03com\x00'
         self.assertRaises(DNSMessageFORMERR, Name, b, 0)
+        self.assertRaises(OverflowError, Name, b, -1)
+        self.assertRaises(OverflowError, Name, b, 0x10000)
 
     def test_at(self):
         self.assertEqual(7, self.name1.at(0))
         self.assertEqual(101, self.name1.at(1))
         self.assertRaises(IndexError, self.name1.at, 100)
         self.assertRaises(TypeError, self.name1.at, "wrong")
+        self.assertRaises(OverflowError, self.name1.at, -1)
+        self.assertRaises(OverflowError, self.name1.at, 0x10000)
 
     def test_get_length(self):
         self.assertEqual(13, self.name1.get_length())
@@ -153,12 +157,20 @@ class NameTest(unittest.TestCase):
         self.assertRaises(TypeError, self.name1.split, 1, "wrong")
         self.assertRaises(IndexError, self.name1.split, 123, 1)
         self.assertRaises(IndexError, self.name1.split, 1, 123)
+        # Out of range
+        self.assertRaises(OverflowError, self.name1.split, -1, 123)
+        self.assertRaises(OverflowError, self.name1.split, 0, -1)
+        self.assertRaises(OverflowError, self.name1.split, 1, 0x10000)
+        self.assertRaises(OverflowError, self.name1.split, 0x10000, 5)
 
         s = self.name1.split(1)
         self.assertEqual("com.", s.to_text())
         s = self.name1.split(0)
         self.assertEqual("example.com.", s.to_text())
         self.assertRaises(IndexError, self.name1.split, 123)
+        # Out of range
+        self.assertRaises(OverflowError, self.name1.split, 0x10000)
+        self.assertRaises(OverflowError, self.name1.split, -123)
 
     def test_reverse(self):
         self.assertEqual("com.example.", self.name1.reverse().to_text())
@@ -169,7 +181,6 @@ class NameTest(unittest.TestCase):
         self.assertEqual("example.com.example.com.", self.name1.concatenate(self.name1).to_text())
         self.assertRaises(TypeError, self.name1.concatenate, "wrong")
         self.assertRaises(TooLongName, self.name1.concatenate, Name("example."*31))
-        
 
     def test_downcase(self):
         self.assertEqual("EXAMPLE.com.", self.name4.to_text())

+ 1 - 1
src/lib/dns/python/tests/question_python_test.py

@@ -45,7 +45,7 @@ class QuestionTest(unittest.TestCase):
     # tests below based on cpp unit tests
     # also tests get_name, get_class and get_type
     def test_from_wire(self):
-        
+
         q = question_from_wire("question_fromWire")
 
         self.assertEqual(self.example_name1, q.get_name())

+ 2 - 1
src/lib/dns/python/tests/rrclass_python_test.py

@@ -32,7 +32,8 @@ class RRClassTest(unittest.TestCase):
         b = bytearray(1)
         b[0] = 123
         self.assertRaises(TypeError, RRClass, b)
-        self.assertRaises(InvalidRRClass, RRClass, 65536)
+        self.assertRaises(OverflowError, RRClass, 65536)
+        self.assertRaises(OverflowError, RRClass, -12)
         self.assertEqual(self.c1, RRClass(1))
         b = bytearray()
         self.c1.to_wire(b)

+ 1 - 1
src/lib/dns/python/tests/rrtype_python_test.py

@@ -32,7 +32,7 @@ class TestModuleSpec(unittest.TestCase):
 
 
     def test_init(self):
-        self.assertRaises(InvalidRRType, RRType, 65537)
+        self.assertRaises(OverflowError, RRType, 65537)
         b = bytearray(b'\x00\x01')
         self.assertEqual(RRType("A"), RRType(b))
         b = bytearray(b'\x01')