mirror of https://github.com/python/cpython
bpo-45691: Make array of small ints static to fix use-after-free error. (GH-29366)
This commit is contained in:
parent
5a14929a6e
commit
acc89db923
|
@ -247,14 +247,6 @@ struct type_cache {
|
||||||
|
|
||||||
/* interpreter state */
|
/* 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.
|
// The PyInterpreterState typedef is in Include/pystate.h.
|
||||||
struct _is {
|
struct _is {
|
||||||
|
|
||||||
|
@ -330,12 +322,6 @@ struct _is {
|
||||||
|
|
||||||
PyObject *audit_hooks;
|
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_bytes_state bytes;
|
||||||
struct _Py_unicode_state unicode;
|
struct _Py_unicode_state unicode;
|
||||||
struct _Py_float_state float_state;
|
struct _Py_float_state float_state;
|
||||||
|
|
|
@ -11,28 +11,15 @@ extern "C" {
|
||||||
#include "pycore_interp.h" // PyInterpreterState.small_ints
|
#include "pycore_interp.h" // PyInterpreterState.small_ints
|
||||||
#include "pycore_pystate.h" // _PyThreadState_GET()
|
#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.
|
// Return a borrowed reference to the zero singleton.
|
||||||
// The function cannot return NULL.
|
// The function cannot return NULL.
|
||||||
static inline PyObject* _PyLong_GetZero(void)
|
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.
|
// Return a borrowed reference to the one singleton.
|
||||||
// The function cannot return NULL.
|
// The function cannot return NULL.
|
||||||
static inline PyObject* _PyLong_GetOne(void)
|
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_Add(PyLongObject *left, PyLongObject *right);
|
||||||
PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
|
PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
|
||||||
|
|
|
@ -11,6 +11,14 @@ extern "C" {
|
||||||
#include "pycore_atomic.h" /* _Py_atomic_address */
|
#include "pycore_atomic.h" /* _Py_atomic_address */
|
||||||
#include "pycore_gil.h" // struct _gil_runtime_state
|
#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 */
|
/* ceval state */
|
||||||
|
|
||||||
struct _ceval_runtime_state {
|
struct _ceval_runtime_state {
|
||||||
|
@ -100,6 +108,13 @@ typedef struct pyruntimestate {
|
||||||
|
|
||||||
unsigned long main_thread;
|
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
|
#define NEXITFUNCS 32
|
||||||
void (*exitfuncs[NEXITFUNCS])(void);
|
void (*exitfuncs[NEXITFUNCS])(void);
|
||||||
int nexitfuncs;
|
int nexitfuncs;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_bitutils.h" // _Py_popcount32()
|
#include "pycore_bitutils.h" // _Py_popcount32()
|
||||||
#include "pycore_interp.h" // _PY_NSMALLPOSINTS
|
#include "pycore_runtime.h" // _PY_NSMALLPOSINTS
|
||||||
#include "pycore_long.h" // __PyLong_GetSmallInt_internal()
|
#include "pycore_long.h" // _Py_SmallInts
|
||||||
#include "pycore_object.h" // _PyObject_InitVar()
|
#include "pycore_object.h" // _PyObject_InitVar()
|
||||||
#include "pycore_pystate.h" // _Py_IsMainInterpreter()
|
#include "pycore_pystate.h" // _Py_IsMainInterpreter()
|
||||||
|
|
||||||
|
@ -20,9 +20,6 @@ class int "PyObject *" "&PyLong_Type"
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ec0275e3422a36e3]*/
|
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ec0275e3422a36e3]*/
|
||||||
|
|
||||||
#define NSMALLNEGINTS _PY_NSMALLNEGINTS
|
|
||||||
#define NSMALLPOSINTS _PY_NSMALLPOSINTS
|
|
||||||
|
|
||||||
_Py_IDENTIFIER(little);
|
_Py_IDENTIFIER(little);
|
||||||
_Py_IDENTIFIER(big);
|
_Py_IDENTIFIER(big);
|
||||||
|
|
||||||
|
@ -37,8 +34,8 @@ medium_value(PyLongObject *x)
|
||||||
return ((stwodigits)Py_SIZE(x)) * x->ob_digit[0];
|
return ((stwodigits)Py_SIZE(x)) * x->ob_digit[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
|
#define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS)
|
||||||
#define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS)
|
#define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS)
|
||||||
|
|
||||||
static inline int is_medium_int(stwodigits x)
|
static inline int is_medium_int(stwodigits x)
|
||||||
{
|
{
|
||||||
|
@ -51,7 +48,7 @@ static PyObject *
|
||||||
get_small_int(sdigit ival)
|
get_small_int(sdigit ival)
|
||||||
{
|
{
|
||||||
assert(IS_SMALL_INT(ival));
|
assert(IS_SMALL_INT(ival));
|
||||||
PyObject *v = __PyLong_GetSmallInt_internal(ival);
|
PyObject *v = (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS + ival];
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -5830,17 +5827,18 @@ PyLong_GetInfo(void)
|
||||||
void
|
void
|
||||||
_PyLong_Init(PyInterpreterState *interp)
|
_PyLong_Init(PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
for (Py_ssize_t i=0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
|
if (_PyRuntime.small_ints[0].ob_base.ob_base.ob_refcnt == 0) {
|
||||||
sdigit ival = (sdigit)i - NSMALLNEGINTS;
|
for (Py_ssize_t i=0; i < _PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS; i++) {
|
||||||
int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
|
sdigit ival = (sdigit)i - _PY_NSMALLNEGINTS;
|
||||||
interp->small_ints[i].ob_base.ob_base.ob_refcnt = 1;
|
int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
|
||||||
interp->small_ints[i].ob_base.ob_base.ob_type = &PyLong_Type;
|
_PyRuntime.small_ints[i].ob_base.ob_base.ob_refcnt = 1;
|
||||||
interp->small_ints[i].ob_base.ob_size = size;
|
_PyRuntime.small_ints[i].ob_base.ob_base.ob_type = &PyLong_Type;
|
||||||
interp->small_ints[i].ob_digit[0] = (digit)abs(ival);
|
_PyRuntime.small_ints[i].ob_base.ob_size = size;
|
||||||
|
_PyRuntime.small_ints[i].ob_digit[0] = (digit)abs(ival);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyLong_InitTypes(void)
|
_PyLong_InitTypes(void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue