Skip to content

Commit aec95c2

Browse files
committed
CHECK_TUPLE_ITEMS, CHECK_LIST macros
1 parent 52ffffe commit aec95c2

1 file changed

Lines changed: 27 additions & 17 deletions

File tree

Modules/_remote_debugging/binary_io_writer.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@
4444
} \
4545
} while (0)
4646

47+
#define CHECK_TUPLE_ITEMS(obj, n) do { \
48+
if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) < (n)) { \
49+
PyErr_Format(PyExc_TypeError, \
50+
#obj " must be a tuple of at least %zd items", \
51+
(Py_ssize_t)(n)); \
52+
return -1; \
53+
} \
54+
} while (0)
55+
56+
#define CHECK_LIST(obj) do { \
57+
if (!PyList_Check(obj)) { \
58+
PyErr_SetString(PyExc_TypeError, #obj " must be a list"); \
59+
return -1; \
60+
} \
61+
} while (0)
62+
4763
/* ============================================================================
4864
* WRITER-SPECIFIC UTILITY HELPERS
4965
* ============================================================================ */
@@ -838,8 +854,8 @@ build_frame_stack(BinaryWriter *writer, PyObject *frame_list,
838854
*curr_depth = (stack_depth < MAX_STACK_DEPTH) ? stack_depth : MAX_STACK_DEPTH;
839855

840856
for (Py_ssize_t k = 0; k < (Py_ssize_t)*curr_depth; k++) {
841-
/* Use unchecked accessors since we control the data structures */
842857
PyObject *frame_info = PyList_GET_ITEM(frame_list, k);
858+
CHECK_TUPLE_ITEMS(frame_info, 4);
843859

844860
/* Get filename, location, funcname, opcode from FrameInfo using unchecked access */
845861
PyObject *filename = PyStructSequence_GET_ITEM(frame_info, 0);
@@ -854,20 +870,13 @@ build_frame_stack(BinaryWriter *writer, PyObject *frame_list,
854870
int32_t end_column = LOCATION_NOT_AVAILABLE;
855871

856872
if (location != Py_None) {
873+
CHECK_TUPLE_ITEMS(location, 4);
857874
/* LocationInfo is a struct sequence or tuple with:
858875
* (lineno, end_lineno, column, end_column) */
859-
PyObject *lineno_obj = PyTuple_Check(location) ?
860-
PyTuple_GET_ITEM(location, 0) :
861-
PyStructSequence_GET_ITEM(location, 0);
862-
PyObject *end_lineno_obj = PyTuple_Check(location) ?
863-
PyTuple_GET_ITEM(location, 1) :
864-
PyStructSequence_GET_ITEM(location, 1);
865-
PyObject *column_obj = PyTuple_Check(location) ?
866-
PyTuple_GET_ITEM(location, 2) :
867-
PyStructSequence_GET_ITEM(location, 2);
868-
PyObject *end_column_obj = PyTuple_Check(location) ?
869-
PyTuple_GET_ITEM(location, 3) :
870-
PyStructSequence_GET_ITEM(location, 3);
876+
PyObject *lineno_obj = PyTuple_GET_ITEM(location, 0);
877+
PyObject *end_lineno_obj = PyTuple_GET_ITEM(location, 1);
878+
PyObject *column_obj = PyTuple_GET_ITEM(location, 2);
879+
PyObject *end_column_obj = PyTuple_GET_ITEM(location, 3);
871880

872881
PYLONG_TO_INT32_OR_DEFAULT(lineno_obj, lineno, LOCATION_NOT_AVAILABLE);
873882
PYLONG_TO_INT32_OR_DEFAULT(end_lineno_obj, end_lineno, LOCATION_NOT_AVAILABLE);
@@ -925,9 +934,11 @@ static int
925934
process_thread_sample(BinaryWriter *writer, PyObject *thread_info,
926935
uint32_t interpreter_id, uint64_t timestamp_us)
927936
{
937+
CHECK_TUPLE_ITEMS(thread_info, 3);
928938
PyObject *thread_id_obj = PyStructSequence_GET_ITEM(thread_info, 0);
929939
PyObject *status_obj = PyStructSequence_GET_ITEM(thread_info, 1);
930940
PyObject *frame_list = PyStructSequence_GET_ITEM(thread_info, 2);
941+
CHECK_LIST(frame_list);
931942

932943
uint64_t thread_id = PyLong_AsUnsignedLongLong(thread_id_obj);
933944
if (thread_id == (uint64_t)-1 && PyErr_Occurred()) {
@@ -1010,17 +1021,16 @@ process_thread_sample(BinaryWriter *writer, PyObject *thread_info,
10101021
int
10111022
binary_writer_write_sample(BinaryWriter *writer, PyObject *stack_frames, uint64_t timestamp_us)
10121023
{
1013-
if (!PyList_Check(stack_frames)) {
1014-
PyErr_SetString(PyExc_TypeError, "stack_frames must be a list");
1015-
return -1;
1016-
}
1024+
CHECK_LIST(stack_frames);
10171025

10181026
Py_ssize_t num_interpreters = PyList_GET_SIZE(stack_frames);
10191027
for (Py_ssize_t i = 0; i < num_interpreters; i++) {
10201028
PyObject *interp_info = PyList_GET_ITEM(stack_frames, i);
1029+
CHECK_TUPLE_ITEMS(interp_info, 2);
10211030

10221031
PyObject *interp_id_obj = PyStructSequence_GET_ITEM(interp_info, 0);
10231032
PyObject *threads = PyStructSequence_GET_ITEM(interp_info, 1);
1033+
CHECK_LIST(threads);
10241034

10251035
unsigned long interp_id_long = PyLong_AsUnsignedLong(interp_id_obj);
10261036
if (interp_id_long == (unsigned long)-1 && PyErr_Occurred()) {

0 commit comments

Comments
 (0)