Commit 76a3e51a authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

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.
parent 898ff03e
...@@ -317,6 +317,10 @@ Extension Modules ...@@ -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 * ...@@ -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 * ...@@ -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) ...@@ -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 = { ...@@ -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 = { ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment