Skip to content

Commit 76a3e51

Browse files
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.
1 parent 898ff03 commit 76a3e51

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
@@ -317,6 +317,10 @@ Extension Modules
317317
Library
318318
-------
319319

320+
- bpo-30243: Removed the __init__ methods of _json's scanner and encoder.
321+
Misusing them could cause memory leaks or crashes. Now scanner and encoder
322+
objects are completely initialized in the __new__ methods.
323+
320324
- bpo-30215: Compiled regular expression objects with the re.LOCALE flag no
321325
longer depend on the locale at compile time. Only the locale at matching
322326
time affects the result of matching.

‎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
@@ -1200,38 +1196,21 @@ static PyObject *
12001196
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
12011197
{
12021198
PyScannerObject *s;
1203-
s = (PyScannerObject *)type->tp_alloc(type, 0);
1204-
if (s != NULL) {
1205-
s->strict = NULL;
1206-
s->object_hook = NULL;
1207-
s->object_pairs_hook = NULL;
1208-
s->parse_float = NULL;
1209-
s->parse_int = NULL;
1210-
s->parse_constant = NULL;
1211-
}
1212-
return (PyObject *)s;
1213-
}
1214-
1215-
static int
1216-
scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
1217-
{
1218-
/* Initialize Scanner object */
12191199
PyObject *ctx;
12201200
static char *kwlist[] = {"context", NULL};
1221-
PyScannerObject *s;
1222-
1223-
assert(PyScanner_Check(self));
1224-
s = (PyScannerObject *)self;
12251201

12261202
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
1227-
return -1;
1203+
return NULL;
12281204

1229-
if (s->memo == NULL) {
1230-
s->memo = PyDict_New();
1231-
if (s->memo == NULL)
1232-
goto bail;
1205+
s = (PyScannerObject *)type->tp_alloc(type, 0);
1206+
if (s == NULL) {
1207+
return NULL;
12331208
}
12341209

1210+
s->memo = PyDict_New();
1211+
if (s->memo == NULL)
1212+
goto bail;
1213+
12351214
/* All of these will fail "gracefully" so we don't need to verify them */
12361215
s->strict = PyObject_GetAttrString(ctx, "strict");
12371216
if (s->strict == NULL)
@@ -1252,16 +1231,11 @@ scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
12521231
if (s->parse_constant == NULL)
12531232
goto bail;
12541233

1255-
return 0;
1234+
return (PyObject *)s;
12561235

12571236
bail:
1258-
Py_CLEAR(s->strict);
1259-
Py_CLEAR(s->object_hook);
1260-
Py_CLEAR(s->object_pairs_hook);
1261-
Py_CLEAR(s->parse_float);
1262-
Py_CLEAR(s->parse_int);
1263-
Py_CLEAR(s->parse_constant);
1264-
return -1;
1237+
Py_DECREF(s);
1238+
return NULL;
12651239
}
12661240

12671241
PyDoc_STRVAR(scanner_doc, "JSON scanner object");
@@ -1303,7 +1277,7 @@ PyTypeObject PyScannerType = {
13031277
0, /* tp_descr_get */
13041278
0, /* tp_descr_set */
13051279
0, /* tp_dictoffset */
1306-
scanner_init, /* tp_init */
1280+
0, /* tp_init */
13071281
0,/* PyType_GenericAlloc, */ /* tp_alloc */
13081282
scanner_new, /* tp_new */
13091283
0,/* PyObject_GC_Del, */ /* tp_free */
@@ -1312,48 +1286,30 @@ PyTypeObject PyScannerType = {
13121286
static PyObject *
13131287
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
13141288
{
1315-
PyEncoderObject *s;
1316-
s = (PyEncoderObject *)type->tp_alloc(type, 0);
1317-
if (s != NULL) {
1318-
s->markers = NULL;
1319-
s->defaultfn = NULL;
1320-
s->encoder = NULL;
1321-
s->indent = NULL;
1322-
s->key_separator = NULL;
1323-
s->item_separator = NULL;
1324-
s->sort_keys = NULL;
1325-
s->skipkeys = NULL;
1326-
}
1327-
return (PyObject *)s;
1328-
}
1329-
1330-
static int
1331-
encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
1332-
{
1333-
/* initialize Encoder object */
13341289
static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
13351290

13361291
PyEncoderObject *s;
13371292
PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
13381293
PyObject *item_separator, *sort_keys, *skipkeys;
13391294
int allow_nan;
13401295

1341-
assert(PyEncoder_Check(self));
1342-
s = (PyEncoderObject *)self;
1343-
13441296
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist,
13451297
&markers, &defaultfn, &encoder, &indent,
13461298
&key_separator, &item_separator,
13471299
&sort_keys, &skipkeys, &allow_nan))
1348-
return -1;
1300+
return NULL;
13491301

13501302
if (markers != Py_None && !PyDict_Check(markers)) {
13511303
PyErr_Format(PyExc_TypeError,
13521304
"make_encoder() argument 1 must be dict or None, "
13531305
"not %.200s", Py_TYPE(markers)->tp_name);
1354-
return -1;
1306+
return NULL;
13551307
}
13561308

1309+
s = (PyEncoderObject *)type->tp_alloc(type, 0);
1310+
if (s == NULL)
1311+
return NULL;
1312+
13571313
s->markers = markers;
13581314
s->defaultfn = defaultfn;
13591315
s->encoder = encoder;
@@ -1380,7 +1336,7 @@ encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
13801336
Py_INCREF(s->item_separator);
13811337
Py_INCREF(s->sort_keys);
13821338
Py_INCREF(s->skipkeys);
1383-
return 0;
1339+
return (PyObject *)s;
13841340
}
13851341

13861342
static PyObject *
@@ -1911,7 +1867,7 @@ PyTypeObject PyEncoderType = {
19111867
0, /* tp_descr_get */
19121868
0, /* tp_descr_set */
19131869
0, /* tp_dictoffset */
1914-
encoder_init, /* tp_init */
1870+
0, /* tp_init */
19151871
0, /* tp_alloc */
19161872
encoder_new, /* tp_new */
19171873
0, /* tp_free */
@@ -1954,10 +1910,8 @@ PyInit__json(void)
19541910
PyObject *m = PyModule_Create(&jsonmodule);
19551911
if (!m)
19561912
return NULL;
1957-
PyScannerType.tp_new = PyType_GenericNew;
19581913
if (PyType_Ready(&PyScannerType) < 0)
19591914
goto fail;
1960-
PyEncoderType.tp_new = PyType_GenericNew;
19611915
if (PyType_Ready(&PyEncoderType) < 0)
19621916
goto fail;
19631917
Py_INCREF((PyObject*)&PyScannerType);

0 commit comments

Comments
 (0)