bpo-30243: Fixed the possibility of a crash in _json. (#1420)
It was possible to get a core dump by using uninitialized _json objects. Now __new__ methods create initialized objects. __init__ methods are removed.
This commit is contained in:
parent
898ff03e1e
commit
76a3e51a40
|
@ -317,6 +317,10 @@ Extension Modules
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- bpo-30243: Removed the __init__ methods of _json's scanner and encoder.
|
||||||
|
Misusing them could cause memory leaks or crashes. Now scanner and encoder
|
||||||
|
objects are completely initialized in the __new__ methods.
|
||||||
|
|
||||||
- bpo-30215: Compiled regular expression objects with the re.LOCALE flag no
|
- bpo-30215: Compiled regular expression objects with the re.LOCALE flag no
|
||||||
longer depend on the locale at compile time. Only the locale at matching
|
longer depend on the locale at compile time. Only the locale at matching
|
||||||
time affects the result of matching.
|
time affects the result of matching.
|
||||||
|
|
|
@ -89,16 +89,12 @@ static PyObject *
|
||||||
_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
|
_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
|
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
|
||||||
static int
|
|
||||||
scanner_init(PyObject *self, PyObject *args, PyObject *kwds);
|
|
||||||
static void
|
static void
|
||||||
scanner_dealloc(PyObject *self);
|
scanner_dealloc(PyObject *self);
|
||||||
static int
|
static int
|
||||||
scanner_clear(PyObject *self);
|
scanner_clear(PyObject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
|
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
|
||||||
static int
|
|
||||||
encoder_init(PyObject *self, PyObject *args, PyObject *kwds);
|
|
||||||
static void
|
static void
|
||||||
encoder_dealloc(PyObject *self);
|
encoder_dealloc(PyObject *self);
|
||||||
static int
|
static int
|
||||||
|
@ -1200,38 +1196,21 @@ static PyObject *
|
||||||
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
PyScannerObject *s;
|
PyScannerObject *s;
|
||||||
s = (PyScannerObject *)type->tp_alloc(type, 0);
|
|
||||||
if (s != NULL) {
|
|
||||||
s->strict = NULL;
|
|
||||||
s->object_hook = NULL;
|
|
||||||
s->object_pairs_hook = NULL;
|
|
||||||
s->parse_float = NULL;
|
|
||||||
s->parse_int = NULL;
|
|
||||||
s->parse_constant = NULL;
|
|
||||||
}
|
|
||||||
return (PyObject *)s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|
||||||
{
|
|
||||||
/* Initialize Scanner object */
|
|
||||||
PyObject *ctx;
|
PyObject *ctx;
|
||||||
static char *kwlist[] = {"context", NULL};
|
static char *kwlist[] = {"context", NULL};
|
||||||
PyScannerObject *s;
|
|
||||||
|
|
||||||
assert(PyScanner_Check(self));
|
|
||||||
s = (PyScannerObject *)self;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
|
||||||
return -1;
|
return NULL;
|
||||||
|
|
||||||
if (s->memo == NULL) {
|
s = (PyScannerObject *)type->tp_alloc(type, 0);
|
||||||
s->memo = PyDict_New();
|
if (s == NULL) {
|
||||||
if (s->memo == NULL)
|
return NULL;
|
||||||
goto bail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->memo = PyDict_New();
|
||||||
|
if (s->memo == NULL)
|
||||||
|
goto bail;
|
||||||
|
|
||||||
/* All of these will fail "gracefully" so we don't need to verify them */
|
/* All of these will fail "gracefully" so we don't need to verify them */
|
||||||
s->strict = PyObject_GetAttrString(ctx, "strict");
|
s->strict = PyObject_GetAttrString(ctx, "strict");
|
||||||
if (s->strict == NULL)
|
if (s->strict == NULL)
|
||||||
|
@ -1252,16 +1231,11 @@ scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
if (s->parse_constant == NULL)
|
if (s->parse_constant == NULL)
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
return 0;
|
return (PyObject *)s;
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
Py_CLEAR(s->strict);
|
Py_DECREF(s);
|
||||||
Py_CLEAR(s->object_hook);
|
return NULL;
|
||||||
Py_CLEAR(s->object_pairs_hook);
|
|
||||||
Py_CLEAR(s->parse_float);
|
|
||||||
Py_CLEAR(s->parse_int);
|
|
||||||
Py_CLEAR(s->parse_constant);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(scanner_doc, "JSON scanner object");
|
PyDoc_STRVAR(scanner_doc, "JSON scanner object");
|
||||||
|
@ -1303,7 +1277,7 @@ PyTypeObject PyScannerType = {
|
||||||
0, /* tp_descr_get */
|
0, /* tp_descr_get */
|
||||||
0, /* tp_descr_set */
|
0, /* tp_descr_set */
|
||||||
0, /* tp_dictoffset */
|
0, /* tp_dictoffset */
|
||||||
scanner_init, /* tp_init */
|
0, /* tp_init */
|
||||||
0,/* PyType_GenericAlloc, */ /* tp_alloc */
|
0,/* PyType_GenericAlloc, */ /* tp_alloc */
|
||||||
scanner_new, /* tp_new */
|
scanner_new, /* tp_new */
|
||||||
0,/* PyObject_GC_Del, */ /* tp_free */
|
0,/* PyObject_GC_Del, */ /* tp_free */
|
||||||
|
@ -1312,25 +1286,6 @@ PyTypeObject PyScannerType = {
|
||||||
static PyObject *
|
static PyObject *
|
||||||
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
PyEncoderObject *s;
|
|
||||||
s = (PyEncoderObject *)type->tp_alloc(type, 0);
|
|
||||||
if (s != NULL) {
|
|
||||||
s->markers = NULL;
|
|
||||||
s->defaultfn = NULL;
|
|
||||||
s->encoder = NULL;
|
|
||||||
s->indent = NULL;
|
|
||||||
s->key_separator = NULL;
|
|
||||||
s->item_separator = NULL;
|
|
||||||
s->sort_keys = NULL;
|
|
||||||
s->skipkeys = NULL;
|
|
||||||
}
|
|
||||||
return (PyObject *)s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|
||||||
{
|
|
||||||
/* initialize Encoder object */
|
|
||||||
static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
|
static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
|
||||||
|
|
||||||
PyEncoderObject *s;
|
PyEncoderObject *s;
|
||||||
|
@ -1338,22 +1293,23 @@ encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
PyObject *item_separator, *sort_keys, *skipkeys;
|
PyObject *item_separator, *sort_keys, *skipkeys;
|
||||||
int allow_nan;
|
int allow_nan;
|
||||||
|
|
||||||
assert(PyEncoder_Check(self));
|
|
||||||
s = (PyEncoderObject *)self;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist,
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist,
|
||||||
&markers, &defaultfn, &encoder, &indent,
|
&markers, &defaultfn, &encoder, &indent,
|
||||||
&key_separator, &item_separator,
|
&key_separator, &item_separator,
|
||||||
&sort_keys, &skipkeys, &allow_nan))
|
&sort_keys, &skipkeys, &allow_nan))
|
||||||
return -1;
|
return NULL;
|
||||||
|
|
||||||
if (markers != Py_None && !PyDict_Check(markers)) {
|
if (markers != Py_None && !PyDict_Check(markers)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"make_encoder() argument 1 must be dict or None, "
|
"make_encoder() argument 1 must be dict or None, "
|
||||||
"not %.200s", Py_TYPE(markers)->tp_name);
|
"not %.200s", Py_TYPE(markers)->tp_name);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s = (PyEncoderObject *)type->tp_alloc(type, 0);
|
||||||
|
if (s == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
s->markers = markers;
|
s->markers = markers;
|
||||||
s->defaultfn = defaultfn;
|
s->defaultfn = defaultfn;
|
||||||
s->encoder = encoder;
|
s->encoder = encoder;
|
||||||
|
@ -1380,7 +1336,7 @@ encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
Py_INCREF(s->item_separator);
|
Py_INCREF(s->item_separator);
|
||||||
Py_INCREF(s->sort_keys);
|
Py_INCREF(s->sort_keys);
|
||||||
Py_INCREF(s->skipkeys);
|
Py_INCREF(s->skipkeys);
|
||||||
return 0;
|
return (PyObject *)s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1911,7 +1867,7 @@ PyTypeObject PyEncoderType = {
|
||||||
0, /* tp_descr_get */
|
0, /* tp_descr_get */
|
||||||
0, /* tp_descr_set */
|
0, /* tp_descr_set */
|
||||||
0, /* tp_dictoffset */
|
0, /* tp_dictoffset */
|
||||||
encoder_init, /* tp_init */
|
0, /* tp_init */
|
||||||
0, /* tp_alloc */
|
0, /* tp_alloc */
|
||||||
encoder_new, /* tp_new */
|
encoder_new, /* tp_new */
|
||||||
0, /* tp_free */
|
0, /* tp_free */
|
||||||
|
@ -1954,10 +1910,8 @@ PyInit__json(void)
|
||||||
PyObject *m = PyModule_Create(&jsonmodule);
|
PyObject *m = PyModule_Create(&jsonmodule);
|
||||||
if (!m)
|
if (!m)
|
||||||
return NULL;
|
return NULL;
|
||||||
PyScannerType.tp_new = PyType_GenericNew;
|
|
||||||
if (PyType_Ready(&PyScannerType) < 0)
|
if (PyType_Ready(&PyScannerType) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
PyEncoderType.tp_new = PyType_GenericNew;
|
|
||||||
if (PyType_Ready(&PyEncoderType) < 0)
|
if (PyType_Ready(&PyEncoderType) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
Py_INCREF((PyObject*)&PyScannerType);
|
Py_INCREF((PyObject*)&PyScannerType);
|
||||||
|
|
Loading…
Reference in New Issue