Skip to content

Commit ee22948

Browse files
[3.5] bpo-30243: Fixed the possibility of a crash in _json. (GH-1420) (#1470)
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 76a3e51)
1 parent ab6b962 commit ee22948

File tree

2 files changed

+24
-66
lines changed

2 files changed

+24
-66
lines changed

‎Misc/NEWS‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ Extension Modules
4949
Library
5050
-------
5151

52+
- bpo-30243: Removed the __init__ methods of _json's scanner and encoder.
53+
Misusing them could cause memory leaks or crashes. Now scanner and encoder
54+
objects are completely initialized in the __new__ methods.
55+
5256
- bpo-30185: Avoid KeyboardInterrupt tracebacks in forkserver helper process
5357
when Ctrl-C is received.
5458

‎Modules/_json.c‎

Lines changed: 20 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,12 @@ static PyObject *
8989
_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
9090
static PyObject *
9191
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
92-
static int
93-
scanner_init(PyObject *self, PyObject *args, PyObject *kwds);
9492
static void
9593
scanner_dealloc(PyObject *self);
9694
static int
9795
scanner_clear(PyObject *self);
9896
static PyObject *
9997
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
100-
static int
101-
encoder_init(PyObject *self, PyObject *args, PyObject *kwds);
10298
static void
10399
encoder_dealloc(PyObject *self);
104100
static int
@@ -1203,38 +1199,21 @@ static PyObject *
12031199
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
12041200
{
12051201
PyScannerObject *s;
1206-
s = (PyScannerObject *)type->tp_alloc(type, 0);
1207-
if (s != NULL) {
1208-
s->strict = NULL;
1209-
s->object_hook = NULL;
1210-
s->object_pairs_hook = NULL;
1211-
s->parse_float = NULL;
1212-
s->parse_int = NULL;
1213-
s->parse_constant = NULL;
1214-
}
1215-
return (PyObject *)s;
1216-
}
1217-
1218-
static int
1219-
scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
1220-
{
1221-
/* Initialize Scanner object */
12221202
PyObject *ctx;
12231203
static char *kwlist[] = {"context", NULL};
1224-
PyScannerObject *s;
1225-
1226-
assert(PyScanner_Check(self));
1227-
s = (PyScannerObject *)self;
12281204

12291205
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
1230-
return -1;
1206+
return NULL;
12311207

1232-
if (s->memo == NULL) {
1233-
s->memo = PyDict_New();
1234-
if (s->memo == NULL)
1235-
goto bail;
1208+
s = (PyScannerObject *)type->tp_alloc(type, 0);
1209+
if (s == NULL) {
1210+
return NULL;
12361211
}
12371212

1213+
s->memo = PyDict_New();
1214+
if (s->memo == NULL)
1215+
goto bail;
1216+
12381217
/* All of these will fail "gracefully" so we don't need to verify them */
12391218
s->strict = PyObject_GetAttrString(ctx, "strict");
12401219
if (s->strict == NULL)
@@ -1255,16 +1234,11 @@ scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
12551234
if (s->parse_constant == NULL)
12561235
goto bail;
12571236

1258-
return 0;
1237+
return (PyObject *)s;
12591238

12601239
bail:
1261-
Py_CLEAR(s->strict);
1262-
Py_CLEAR(s->object_hook);
1263-
Py_CLEAR(s->object_pairs_hook);
1264-
Py_CLEAR(s->parse_float);
1265-
Py_CLEAR(s->parse_int);
1266-
Py_CLEAR(s->parse_constant);
1267-
return -1;
1240+
Py_DECREF(s);
1241+
return NULL;
12681242
}
12691243

12701244
PyDoc_STRVAR(scanner_doc, "JSON scanner object");
@@ -1306,7 +1280,7 @@ PyTypeObject PyScannerType = {
13061280
0, /* tp_descr_get */
13071281
0, /* tp_descr_set */
13081282
0, /* tp_dictoffset */
1309-
scanner_init, /* tp_init */
1283+
0, /* tp_init */
13101284
0,/* PyType_GenericAlloc, */ /* tp_alloc */
13111285
scanner_new, /* tp_new */
13121286
0,/* PyObject_GC_Del, */ /* tp_free */
@@ -1315,48 +1289,30 @@ PyTypeObject PyScannerType = {
13151289
static PyObject *
13161290
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
13171291
{
1318-
PyEncoderObject *s;
1319-
s = (PyEncoderObject *)type->tp_alloc(type, 0);
1320-
if (s != NULL) {
1321-
s->markers = NULL;
1322-
s->defaultfn = NULL;
1323-
s->encoder = NULL;
1324-
s->indent = NULL;
1325-
s->key_separator = NULL;
1326-
s->item_separator = NULL;
1327-
s->sort_keys = NULL;
1328-
s->skipkeys = NULL;
1329-
}
1330-
return (PyObject *)s;
1331-
}
1332-
1333-
static int
1334-
encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
1335-
{
1336-
/* initialize Encoder object */
13371292
static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
13381293

13391294
PyEncoderObject *s;
13401295
PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
13411296
PyObject *item_separator, *sort_keys, *skipkeys;
13421297
int allow_nan;
13431298

1344-
assert(PyEncoder_Check(self));
1345-
s = (PyEncoderObject *)self;
1346-
13471299
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist,
13481300
&markers, &defaultfn, &encoder, &indent,
13491301
&key_separator, &item_separator,
13501302
&sort_keys, &skipkeys, &allow_nan))
1351-
return -1;
1303+
return NULL;
13521304

13531305
if (markers != Py_None && !PyDict_Check(markers)) {
13541306
PyErr_Format(PyExc_TypeError,
13551307
"make_encoder() argument 1 must be dict or None, "
13561308
"not %.200s", Py_TYPE(markers)->tp_name);
1357-
return -1;
1309+
return NULL;
13581310
}
13591311

1312+
s = (PyEncoderObject *)type->tp_alloc(type, 0);
1313+
if (s == NULL)
1314+
return NULL;
1315+
13601316
s->markers = markers;
13611317
s->defaultfn = defaultfn;
13621318
s->encoder = encoder;
@@ -1383,7 +1339,7 @@ encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
13831339
Py_INCREF(s->item_separator);
13841340
Py_INCREF(s->sort_keys);
13851341
Py_INCREF(s->skipkeys);
1386-
return 0;
1342+
return (PyObject *)s;
13871343
}
13881344

13891345
static PyObject *
@@ -1914,7 +1870,7 @@ PyTypeObject PyEncoderType = {
19141870
0, /* tp_descr_get */
19151871
0, /* tp_descr_set */
19161872
0, /* tp_dictoffset */
1917-
encoder_init, /* tp_init */
1873+
0, /* tp_init */
19181874
0, /* tp_alloc */
19191875
encoder_new, /* tp_new */
19201876
0, /* tp_free */
@@ -1957,10 +1913,8 @@ PyInit__json(void)
19571913
PyObject *m = PyModule_Create(&jsonmodule);
19581914
if (!m)
19591915
return NULL;
1960-
PyScannerType.tp_new = PyType_GenericNew;
19611916
if (PyType_Ready(&PyScannerType) < 0)
19621917
goto fail;
1963-
PyEncoderType.tp_new = PyType_GenericNew;
19641918
if (PyType_Ready(&PyEncoderType) < 0)
19651919
goto fail;
19661920
Py_INCREF((PyObject*)&PyScannerType);

0 commit comments

Comments
 (0)