1818static PyObject *
1919parse_tuple_message (PyObject * self , PyObject * args )
2020{
21- PyObject * typ ;
22- PyObject * ob ;
2321 PyObject * rob ;
22+ PyObject * ob ;
23+ PyObject * typ ;
2424 const char * data ;
25+ Py_ssize_t dlen = 0 ;
2526 uint16_t cnatt = 0 , natts = 0 ;
2627 uint32_t attsize = 0 ;
2728 uint32_t position = 0 ;
28- Py_ssize_t dlen = 0 ;
2929
30- if (PyArg_ParseTuple (args , "Oy#" , & typ , & data , & dlen ) < 0 )
30+ if (! PyArg_ParseTuple (args , "Oy#" , & typ , & data , & dlen ))
3131 return (NULL );
3232
33+ /*
34+ * Validate that the given "typ" is in fact a PyTuple_Type subtype.
35+ */
3336 if (typ != Py_None )
3437 {
3538 if (!PyObject_IsSubclass (typ , (PyObject * ) & PyTuple_Type ))
@@ -67,9 +70,11 @@ parse_tuple_message(PyObject *self, PyObject *args)
6770 /*
6871 * FEARME: A bit much for saving a reallocation/copy?
6972 *
70- * This is expected to be used as a classmethod on a tuple subtype.
73+ * This is expected to be used as a classmethod on a tuple subtype that
74+ * has *no* additional attributes.
75+ *
7176 * If the subtype has a custom __new__ routine, this could
72- * be problematic, but it would probably only lead to AttributeErrors
77+ * be problematic, but it *should* only lead to AttributeErrors.
7378 */
7479 rob = ((PyTypeObject * ) typ )-> tp_alloc ((PyTypeObject * ) typ , natts );
7580 if (rob == NULL )
@@ -86,7 +91,10 @@ parse_tuple_message(PyObject *self, PyObject *args)
8691 if (position + 4 > dlen )
8792 {
8893 PyErr_Format (PyExc_ValueError ,
89- "not enough data for attribute %d" , cnatt );
94+ "not enough data available for attribute %d's size header: "
95+ "needed %d bytes, but only %lu remain at position %lu" ,
96+ cnatt , 4 , dlen - position , position
97+ );
9098 goto cleanup ;
9199 }
92100
@@ -110,21 +118,23 @@ parse_tuple_message(PyObject *self, PyObject *args)
110118 * so it is unexpected for an attsize to cause wrap-around.
111119 */
112120 PyErr_Format (PyExc_ValueError ,
113- "tuple data caused position (uint32_t) wrap-around on attribute %d" ,
114- cnatt
121+ "tuple data caused position (uint32_t) "
122+ "to wrap on attribute %d, position %lu + size %lu" ,
123+ cnatt , position , attsize
115124 );
116125 goto cleanup ;
117126 }
118127
119128 if (position + attsize > dlen )
120129 {
121130 PyErr_Format (PyExc_ValueError ,
122- "not enough data for attribute %d, size %d , "
123- "but only %d remaining bytes in message" ,
131+ "not enough data for attribute %d, size %lu , "
132+ "as only %lu bytes remain in message" ,
124133 cnatt , attsize , dlen - position
125134 );
126135 goto cleanup ;
127136 }
137+
128138 ob = PyBytes_FromStringAndSize (data + position , attsize );
129139 if (ob == NULL )
130140 {
@@ -143,7 +153,7 @@ parse_tuple_message(PyObject *self, PyObject *args)
143153 if (position != dlen )
144154 {
145155 PyErr_Format (PyExc_ValueError ,
146- "invalid tuple message, %d remaining "
156+ "invalid tuple message, %lu remaining "
147157 "bytes after processing %d attributes" ,
148158 dlen - position , cnatt
149159 );
@@ -157,6 +167,10 @@ parse_tuple_message(PyObject *self, PyObject *args)
157167 return (NULL );
158168}
159169
170+ /*
171+ * process the tuple with the associated callables while
172+ * calling the third object in cases of failure to generalize the exception.
173+ */
160174static PyObject *
161175process_tuple (PyObject * self , PyObject * args )
162176{
@@ -249,11 +263,13 @@ process_tuple(PyObject *self, PyObject *args)
249263 failargs = PyTuple_New (3 );
250264 if (failargs != NULL )
251265 {
266+ /* args for the exception "handler" */
252267 PyTuple_SET_ITEM (failargs , 0 , procs );
253268 Py_INCREF (procs );
254269 PyTuple_SET_ITEM (failargs , 1 , tup );
255270 Py_INCREF (tup );
256271 PyTuple_SET_ITEM (failargs , 2 , failedat );
272+
257273 r = PyObject_CallObject (fail , failargs );
258274 Py_DECREF (failargs );
259275 if (r != NULL )
0 commit comments