Skip to content

Commit 76a3e51

Browse files
bpo-30243: Fixed the possibility of a crash in _json. (python#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

+4
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

+20-66
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)