Skip to content

Commit 7c5da94

Browse files
authored
gh-120674: Protect multi-line macros in _testbuffer.c and _testcapimodule.c (#120675)
Add do { ... } while (0) pattern.
1 parent 4bc27ab commit 7c5da94

File tree

2 files changed

+86
-60
lines changed

2 files changed

+86
-60
lines changed

Modules/_testbuffer.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ static PyTypeObject NDArray_Type;
2424
#define NDArray_Check(v) Py_IS_TYPE(v, &NDArray_Type)
2525

2626
#define CHECK_LIST_OR_TUPLE(v) \
27-
if (!PyList_Check(v) && !PyTuple_Check(v)) { \
28-
PyErr_SetString(PyExc_TypeError, \
29-
#v " must be a list or a tuple"); \
30-
return NULL; \
31-
} \
27+
do { \
28+
if (!PyList_Check(v) && !PyTuple_Check(v)) { \
29+
PyErr_SetString(PyExc_TypeError, \
30+
#v " must be a list or a tuple"); \
31+
return NULL; \
32+
} \
33+
} while (0)
3234

3335
#define PyMem_XFree(v) \
3436
do { if (v) PyMem_Free(v); } while (0)
@@ -1180,7 +1182,7 @@ init_ndbuf(PyObject *items, PyObject *shape, PyObject *strides,
11801182
Py_ssize_t itemsize;
11811183

11821184
/* ndim = len(shape) */
1183-
CHECK_LIST_OR_TUPLE(shape)
1185+
CHECK_LIST_OR_TUPLE(shape);
11841186
ndim = PySequence_Fast_GET_SIZE(shape);
11851187
if (ndim > ND_MAX_NDIM) {
11861188
PyErr_Format(PyExc_ValueError,
@@ -1190,7 +1192,7 @@ init_ndbuf(PyObject *items, PyObject *shape, PyObject *strides,
11901192

11911193
/* len(strides) = len(shape) */
11921194
if (strides) {
1193-
CHECK_LIST_OR_TUPLE(strides)
1195+
CHECK_LIST_OR_TUPLE(strides);
11941196
if (PySequence_Fast_GET_SIZE(strides) == 0)
11951197
strides = NULL;
11961198
else if (flags & ND_FORTRAN) {
@@ -1222,7 +1224,7 @@ init_ndbuf(PyObject *items, PyObject *shape, PyObject *strides,
12221224
return NULL;
12231225
}
12241226
else {
1225-
CHECK_LIST_OR_TUPLE(items)
1227+
CHECK_LIST_OR_TUPLE(items);
12261228
Py_INCREF(items);
12271229
}
12281230

Modules/_testcapimodule.c

Lines changed: 76 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,11 @@ static PyObject*
8181
test_config(PyObject *self, PyObject *Py_UNUSED(ignored))
8282
{
8383
#define CHECK_SIZEOF(FATNAME, TYPE) \
84-
if (FATNAME != sizeof(TYPE)) \
85-
return sizeof_error(self, #FATNAME, #TYPE, FATNAME, sizeof(TYPE))
84+
do { \
85+
if (FATNAME != sizeof(TYPE)) { \
86+
return sizeof_error(self, #FATNAME, #TYPE, FATNAME, sizeof(TYPE)); \
87+
} \
88+
} while (0)
8689

8790
CHECK_SIZEOF(SIZEOF_SHORT, short);
8891
CHECK_SIZEOF(SIZEOF_INT, int);
@@ -103,21 +106,25 @@ test_sizeof_c_types(PyObject *self, PyObject *Py_UNUSED(ignored))
103106
#pragma GCC diagnostic push
104107
#pragma GCC diagnostic ignored "-Wtype-limits"
105108
#endif
106-
#define CHECK_SIZEOF(TYPE, EXPECTED) \
107-
if (EXPECTED != sizeof(TYPE)) { \
108-
PyErr_Format(get_testerror(self), \
109-
"sizeof(%s) = %u instead of %u", \
110-
#TYPE, sizeof(TYPE), EXPECTED); \
111-
return (PyObject*)NULL; \
112-
}
109+
#define CHECK_SIZEOF(TYPE, EXPECTED) \
110+
do { \
111+
if (EXPECTED != sizeof(TYPE)) { \
112+
PyErr_Format(get_testerror(self), \
113+
"sizeof(%s) = %u instead of %u", \
114+
#TYPE, sizeof(TYPE), EXPECTED); \
115+
return (PyObject*)NULL; \
116+
} \
117+
} while (0)
113118
#define IS_SIGNED(TYPE) (((TYPE)-1) < (TYPE)0)
114-
#define CHECK_SIGNNESS(TYPE, SIGNED) \
115-
if (IS_SIGNED(TYPE) != SIGNED) { \
116-
PyErr_Format(get_testerror(self), \
117-
"%s signness is %i, instead of %i", \
118-
#TYPE, IS_SIGNED(TYPE), SIGNED); \
119-
return (PyObject*)NULL; \
120-
}
119+
#define CHECK_SIGNNESS(TYPE, SIGNED) \
120+
do { \
121+
if (IS_SIGNED(TYPE) != SIGNED) { \
122+
PyErr_Format(get_testerror(self), \
123+
"%s signness is %i, instead of %i", \
124+
#TYPE, IS_SIGNED(TYPE), SIGNED); \
125+
return (PyObject*)NULL; \
126+
} \
127+
} while (0)
121128

122129
/* integer types */
123130
CHECK_SIZEOF(Py_UCS1, 1);
@@ -884,27 +891,34 @@ test_string_to_double(PyObject *self, PyObject *Py_UNUSED(ignored)) {
884891
double result;
885892
const char *msg;
886893

887-
#define CHECK_STRING(STR, expected) \
888-
result = PyOS_string_to_double(STR, NULL, NULL); \
889-
if (result == -1.0 && PyErr_Occurred()) \
890-
return NULL; \
891-
if (result != (double)expected) { \
892-
msg = "conversion of " STR " to float failed"; \
893-
goto fail; \
894-
}
894+
#define CHECK_STRING(STR, expected) \
895+
do { \
896+
result = PyOS_string_to_double(STR, NULL, NULL); \
897+
if (result == -1.0 && PyErr_Occurred()) { \
898+
return NULL; \
899+
} \
900+
if (result != (double)expected) { \
901+
msg = "conversion of " STR " to float failed"; \
902+
goto fail; \
903+
} \
904+
} while (0)
895905

896-
#define CHECK_INVALID(STR) \
897-
result = PyOS_string_to_double(STR, NULL, NULL); \
898-
if (result == -1.0 && PyErr_Occurred()) { \
899-
if (PyErr_ExceptionMatches(PyExc_ValueError)) \
900-
PyErr_Clear(); \
901-
else \
902-
return NULL; \
903-
} \
904-
else { \
905-
msg = "conversion of " STR " didn't raise ValueError"; \
906-
goto fail; \
907-
}
906+
#define CHECK_INVALID(STR) \
907+
do { \
908+
result = PyOS_string_to_double(STR, NULL, NULL); \
909+
if (result == -1.0 && PyErr_Occurred()) { \
910+
if (PyErr_ExceptionMatches(PyExc_ValueError)) { \
911+
PyErr_Clear(); \
912+
} \
913+
else { \
914+
return NULL; \
915+
} \
916+
} \
917+
else { \
918+
msg = "conversion of " STR " didn't raise ValueError"; \
919+
goto fail; \
920+
} \
921+
} while (0)
908922

909923
CHECK_STRING("0.1", 0.1);
910924
CHECK_STRING("1.234", 1.234);
@@ -971,16 +985,22 @@ test_capsule(PyObject *self, PyObject *Py_UNUSED(ignored))
971985
};
972986
known_capsule *known = &known_capsules[0];
973987

974-
#define FAIL(x) { error = (x); goto exit; }
988+
#define FAIL(x) \
989+
do { \
990+
error = (x); \
991+
goto exit; \
992+
} while (0)
975993

976994
#define CHECK_DESTRUCTOR \
977-
if (capsule_error) { \
978-
FAIL(capsule_error); \
979-
} \
980-
else if (!capsule_destructor_call_count) { \
981-
FAIL("destructor not called!"); \
982-
} \
983-
capsule_destructor_call_count = 0; \
995+
do { \
996+
if (capsule_error) { \
997+
FAIL(capsule_error); \
998+
} \
999+
else if (!capsule_destructor_call_count) { \
1000+
FAIL("destructor not called!"); \
1001+
} \
1002+
capsule_destructor_call_count = 0; \
1003+
} while (0)
9841004

9851005
object = PyCapsule_New(capsule_pointer, capsule_name, capsule_destructor);
9861006
PyCapsule_SetContext(object, capsule_context);
@@ -1024,12 +1044,12 @@ test_capsule(PyObject *self, PyObject *Py_UNUSED(ignored))
10241044
static char buffer[256];
10251045
#undef FAIL
10261046
#define FAIL(x) \
1027-
{ \
1028-
sprintf(buffer, "%s module: \"%s\" attribute: \"%s\"", \
1029-
x, known->module, known->attribute); \
1030-
error = buffer; \
1031-
goto exit; \
1032-
} \
1047+
do { \
1048+
sprintf(buffer, "%s module: \"%s\" attribute: \"%s\"", \
1049+
x, known->module, known->attribute); \
1050+
error = buffer; \
1051+
goto exit; \
1052+
} while (0)
10331053

10341054
PyObject *module = PyImport_ImportModule(known->module);
10351055
if (module) {
@@ -1978,11 +1998,15 @@ test_pythread_tss_key_state(PyObject *self, PyObject *args)
19781998
"an already initialized key");
19791999
}
19802000
#define CHECK_TSS_API(expr) \
2001+
do { \
19812002
(void)(expr); \
19822003
if (!PyThread_tss_is_created(&tss_key)) { \
19832004
return raiseTestError(self, "test_pythread_tss_key_state", \
19842005
"TSS key initialization state was not " \
1985-
"preserved after calling " #expr); }
2006+
"preserved after calling " #expr); \
2007+
} \
2008+
} while (0)
2009+
19862010
CHECK_TSS_API(PyThread_tss_set(&tss_key, NULL));
19872011
CHECK_TSS_API(PyThread_tss_get(&tss_key));
19882012
#undef CHECK_TSS_API
@@ -2304,7 +2328,7 @@ test_py_setref(PyObject *self, PyObject *Py_UNUSED(ignored))
23042328
\
23052329
Py_DECREF(obj); \
23062330
Py_RETURN_NONE; \
2307-
} while (0) \
2331+
} while (0)
23082332

23092333

23102334
// Test Py_NewRef() and Py_XNewRef() macros

0 commit comments

Comments
 (0)