[3.6] bpo-30243: Fixed the possibility of a crash in _json. (GH-1420) (#1469)

It was possible to get a core dump by using uninitialized
_json objects. Now __new__ methods create initialized objects.
__init__ methods are removed..
(cherry picked from commit 76a3e51a40)
This commit is contained in:
Serhiy Storchaka 2017-05-05 10:40:30 +03:00 committed by GitHub
parent 9d02f56296
commit 39b73dd513
2 changed files with 24 additions and 66 deletions

View file

@ -36,6 +36,10 @@ Core and Builtins
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-30185: Avoid KeyboardInterrupt tracebacks in forkserver helper process - bpo-30185: Avoid KeyboardInterrupt tracebacks in forkserver helper process
when Ctrl-C is received. when Ctrl-C is received.

View file

@ -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
@ -1203,38 +1199,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)
@ -1255,16 +1234,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");
@ -1306,7 +1280,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 */
@ -1315,25 +1289,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;
@ -1341,22 +1296,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;
@ -1383,7 +1339,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 *
@ -1914,7 +1870,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 */
@ -1957,10 +1913,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);