summaryrefslogtreecommitdiff
path: root/Include
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2021-11-03 16:22:32 +0000
committerGitHub <noreply@github.com>2021-11-03 16:22:32 +0000
commitacc89db9233abf4d903af9a7595a2ed7478fe7d3 (patch)
treefb08e91bc2dab4db12daace28c778749a293a20f /Include
parent5a14929a6e4fab672e2f83a86773618e973b22a6 (diff)
downloadcpython-git-acc89db9233abf4d903af9a7595a2ed7478fe7d3.tar.gz
bpo-45691: Make array of small ints static to fix use-after-free error. (GH-29366)
Diffstat (limited to 'Include')
-rw-r--r--Include/internal/pycore_interp.h14
-rw-r--r--Include/internal/pycore_long.h17
-rw-r--r--Include/internal/pycore_runtime.h15
3 files changed, 17 insertions, 29 deletions
diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index 8bd3dc064e..18f2143200 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -247,14 +247,6 @@ struct type_cache {
/* interpreter state */
-#define _PY_NSMALLPOSINTS 257
-#define _PY_NSMALLNEGINTS 5
-
-// _PyLong_GetZero() and _PyLong_GetOne() must always be available
-#if _PY_NSMALLPOSINTS < 2
-# error "_PY_NSMALLPOSINTS must be greater than 1"
-#endif
-
// The PyInterpreterState typedef is in Include/pystate.h.
struct _is {
@@ -330,12 +322,6 @@ struct _is {
PyObject *audit_hooks;
- /* Small integers are preallocated in this array so that they
- can be shared.
- The integers that are preallocated are those in the range
- -_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive).
- */
- PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
struct _Py_bytes_state bytes;
struct _Py_unicode_state unicode;
struct _Py_float_state float_state;
diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h
index 773025b4a5..2f786083e4 100644
--- a/Include/internal/pycore_long.h
+++ b/Include/internal/pycore_long.h
@@ -11,28 +11,15 @@ extern "C" {
#include "pycore_interp.h" // PyInterpreterState.small_ints
#include "pycore_pystate.h" // _PyThreadState_GET()
-// Don't call this function but _PyLong_GetZero() and _PyLong_GetOne()
-static inline PyObject* __PyLong_GetSmallInt_internal(int value)
-{
- PyInterpreterState *interp = _PyInterpreterState_GET();
- assert(-_PY_NSMALLNEGINTS <= value && value < _PY_NSMALLPOSINTS);
- size_t index = _PY_NSMALLNEGINTS + value;
- PyObject *obj = (PyObject*)&interp->small_ints[index];
- // _PyLong_GetZero(), _PyLong_GetOne() and get_small_int() must not be
- // called before _PyLong_Init() nor after _PyLong_Fini().
- assert(obj != NULL);
- return obj;
-}
-
// Return a borrowed reference to the zero singleton.
// The function cannot return NULL.
static inline PyObject* _PyLong_GetZero(void)
-{ return __PyLong_GetSmallInt_internal(0); }
+{ return (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS]; }
// Return a borrowed reference to the one singleton.
// The function cannot return NULL.
static inline PyObject* _PyLong_GetOne(void)
-{ return __PyLong_GetSmallInt_internal(1); }
+{ return (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS+1]; }
PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index bcd710c449..9df833c270 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -11,6 +11,14 @@ extern "C" {
#include "pycore_atomic.h" /* _Py_atomic_address */
#include "pycore_gil.h" // struct _gil_runtime_state
+#define _PY_NSMALLPOSINTS 257
+#define _PY_NSMALLNEGINTS 5
+
+// _PyLong_GetZero() and _PyLong_GetOne() must always be available
+#if _PY_NSMALLPOSINTS < 2
+# error "_PY_NSMALLPOSINTS must be greater than 1"
+#endif
+
/* ceval state */
struct _ceval_runtime_state {
@@ -100,6 +108,13 @@ typedef struct pyruntimestate {
unsigned long main_thread;
+ /* Small integers are preallocated in this array so that they
+ * can be shared.
+ * The integers that are preallocated are those in the range
+ *-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive).
+ */
+ PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
+
#define NEXITFUNCS 32
void (*exitfuncs[NEXITFUNCS])(void);
int nexitfuncs;