From d65c700a2e4a9dbc625f84e6bb9bedd12e182c19 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 22 Nov 2018 02:56:20 +0100 Subject: [PATCH] bpo-35059: Add assertion to _PyObject_CAST() _PyObject_CAST() and _PyVarObject_CAST() macros now require that the type of the argument has a size. For example, _PyObject_CAST(frame) now raises a compilation error if frame type is "struct _frame*" but "struct _frame" is not defined. _PyObject_CAST() and _PyVarObject_CAST() macros now raise a compilation error if the argument is a "PyObject" or a "PyObject**". Partially revert b37672daf61740fe1ff9d805f6d74bc5ef04012b to show that _PyObject_CAST() accepts non-trivial expressions. --- Include/object.h | 31 ++++++++++++++++++++++++++----- Modules/_ssl.c | 9 +++------ Objects/weakrefobject.c | 3 +-- Python/pystate.c | 1 + 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/Include/object.h b/Include/object.h index cdcdca85c633a1b..9d3a367ec7d9fd9 100644 --- a/Include/object.h +++ b/Include/object.h @@ -112,16 +112,37 @@ typedef struct _object { struct _typeobject *ob_type; } PyObject; -/* Cast argument to PyObject* type. */ -#define _PyObject_CAST(op) ((PyObject*)(op)) - typedef struct { PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ } PyVarObject; -/* Cast argument to PyVarObject* type. */ -#define _PyVarObject_CAST(op) ((PyVarObject*)(op)) +/* sizeof(*op) doesn't work on Visual Studio with void*: + sizeof(void) raises a compilation error. + + sizeof(*op) is incompatible with Py_LIMITED_API which doesn't define + structures. */ +#if !defined(_MSC_VER) && !defined(Py_LIMITED_API) +/* _PyObject_CAST(op): Cast argument to PyObject* type. + + Raise a compilation error if the argument type is PyObject or PyObject**. + + Detect for example the bug "&item" instead of "item" in: + + const char *func(PyObject *item) { return Py_TYPE(&item)->tp_name; } + + Note: sizeof(op) doesn't evaluate 'op', so sizeof(op) has no side effect. */ +# define _PyObject_CAST(op) \ + ((PyObject*)(op) + Py_BUILD_ASSERT_EXPR(sizeof(*(op)) != sizeof(op))) + +/* _PyVarObject_CAST(op): Cast argument to PyVarObject* type. + Similar to _PyObject_CAST(). */ +# define _PyVarObject_CAST(op) \ + ((PyVarObject*)(op) + Py_BUILD_ASSERT_EXPR(sizeof(*(op)) != sizeof(op))) +#else +# define _PyObject_CAST(op) ((PyObject*)(op)) +# define _PyVarObject_CAST(op) ((PyVarObject*)(op)) +#endif /* defined(_MSC_VER) */ #define Py_REFCNT(ob) (_PyObject_CAST(ob)->ob_refcnt) #define Py_TYPE(ob) (_PyObject_CAST(ob)->ob_type) diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 85819f5b0509029..93498f475609d06 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -5983,12 +5983,9 @@ PyInit__ssl(void) PyModule_AddIntConstant(m, "PROTO_TLSv1_2", PY_PROTO_TLSv1_2); PyModule_AddIntConstant(m, "PROTO_TLSv1_3", PY_PROTO_TLSv1_3); -#define addbool(m, key, value) \ - do { \ - PyObject *bool_obj = (value) ? Py_True : Py_False; \ - Py_INCREF(bool_obj); \ - PyModule_AddObject((m), (key), bool_obj); \ - } while (0) +#define addbool(m, v, b) \ + Py_INCREF((b) ? Py_True : Py_False); \ + PyModule_AddObject((m), (v), (b) ? Py_True : Py_False); #if HAVE_SNI addbool(m, "HAS_SNI", 1); diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index 9227aa688f47e1d..9f492e4b25e49fa 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -833,8 +833,7 @@ PyWeakref_NewProxy(PyObject *ob, PyObject *callback) to avoid violating the invariants of the list of weakrefs for ob. */ Py_DECREF(result); - result = proxy; - Py_INCREF(result); + Py_INCREF(result = proxy); goto skip_insert; } prev = ref; diff --git a/Python/pystate.c b/Python/pystate.c index f86f5a96f07450d..e7b9363d565b0da 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -2,6 +2,7 @@ /* Thread and interpreter state structures and their interfaces */ #include "Python.h" +#include "frameobject.h" #include "pycore_pymem.h" #include "pycore_pystate.h"