Skip to content

Commit 5d7a18f

Browse files
[2.7] bpo-30243: Fixed the possibility of a crash in _json. (GH-1420) (#1471)
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 d81f9e2 commit 5d7a18f

File tree

2 files changed

+22
-65
lines changed

2 files changed

+22
-65
lines changed

‎Misc/NEWS‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ Extension Modules
4242
Library
4343
-------
4444

45+
- bpo-30243: Removed the __init__ methods of _json's scanner and encoder.
46+
Misusing them could cause memory leaks or crashes. Now scanner and encoder
47+
objects are completely initialized in the __new__ methods.
48+
4549
- Revert bpo-26293 for zipfile breakage. See also bpo-29094.
4650

4751
- bpo-30070: Fixed leaks and crashes in errors handling in the parser module.

‎Modules/_json.c‎

Lines changed: 18 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,12 @@ static PyObject *
9595
_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
9696
static PyObject *
9797
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
98-
static int
99-
scanner_init(PyObject *self, PyObject *args, PyObject *kwds);
10098
static void
10199
scanner_dealloc(PyObject *self);
102100
static int
103101
scanner_clear(PyObject *self);
104102
static PyObject *
105103
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
106-
static int
107-
encoder_init(PyObject *self, PyObject *args, PyObject *kwds);
108104
static void
109105
encoder_dealloc(PyObject *self);
110106
static int
@@ -1707,32 +1703,15 @@ static PyObject *
17071703
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
17081704
{
17091705
PyScannerObject *s;
1710-
s = (PyScannerObject *)type->tp_alloc(type, 0);
1711-
if (s != NULL) {
1712-
s->encoding = NULL;
1713-
s->strict = NULL;
1714-
s->object_hook = NULL;
1715-
s->pairs_hook = NULL;
1716-
s->parse_float = NULL;
1717-
s->parse_int = NULL;
1718-
s->parse_constant = NULL;
1719-
}
1720-
return (PyObject *)s;
1721-
}
1722-
1723-
static int
1724-
scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
1725-
{
1726-
/* Initialize Scanner object */
17271706
PyObject *ctx;
17281707
static char *kwlist[] = {"context", NULL};
1729-
PyScannerObject *s;
1730-
1731-
assert(PyScanner_Check(self));
1732-
s = (PyScannerObject *)self;
17331708

17341709
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
1735-
return -1;
1710+
return NULL;
1711+
1712+
s = (PyScannerObject *)type->tp_alloc(type, 0);
1713+
if (s == NULL)
1714+
return NULL;
17361715

17371716
/* PyString_AS_STRING is used on encoding */
17381717
s->encoding = PyObject_GetAttrString(ctx, "encoding");
@@ -1776,17 +1755,11 @@ scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
17761755
if (s->parse_constant == NULL)
17771756
goto bail;
17781757

1779-
return 0;
1758+
return (PyObject *)s;
17801759

17811760
bail:
1782-
Py_CLEAR(s->encoding);
1783-
Py_CLEAR(s->strict);
1784-
Py_CLEAR(s->object_hook);
1785-
Py_CLEAR(s->pairs_hook);
1786-
Py_CLEAR(s->parse_float);
1787-
Py_CLEAR(s->parse_int);
1788-
Py_CLEAR(s->parse_constant);
1789-
return -1;
1761+
Py_DECREF(s);
1762+
return NULL;
17901763
}
17911764

17921765
PyDoc_STRVAR(scanner_doc, "JSON scanner object");
@@ -1829,7 +1802,7 @@ PyTypeObject PyScannerType = {
18291802
0, /* tp_descr_get */
18301803
0, /* tp_descr_set */
18311804
0, /* tp_dictoffset */
1832-
scanner_init, /* tp_init */
1805+
0, /* tp_init */
18331806
0,/* PyType_GenericAlloc, */ /* tp_alloc */
18341807
scanner_new, /* tp_new */
18351808
0,/* PyObject_GC_Del, */ /* tp_free */
@@ -1838,51 +1811,33 @@ PyTypeObject PyScannerType = {
18381811
static PyObject *
18391812
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
18401813
{
1841-
PyEncoderObject *s;
1842-
s = (PyEncoderObject *)type->tp_alloc(type, 0);
1843-
if (s != NULL) {
1844-
s->markers = NULL;
1845-
s->defaultfn = NULL;
1846-
s->encoder = NULL;
1847-
s->indent = NULL;
1848-
s->key_separator = NULL;
1849-
s->item_separator = NULL;
1850-
s->sort_keys = NULL;
1851-
s->skipkeys = NULL;
1852-
}
1853-
return (PyObject *)s;
1854-
}
1855-
1856-
static int
1857-
encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
1858-
{
1859-
/* initialize Encoder object */
18601814
static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
18611815

18621816
PyEncoderObject *s;
18631817
PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
18641818
PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan_obj;
18651819
int allow_nan;
18661820

1867-
assert(PyEncoder_Check(self));
1868-
s = (PyEncoderObject *)self;
1869-
18701821
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist,
18711822
&markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator,
18721823
&sort_keys, &skipkeys, &allow_nan_obj))
1873-
return -1;
1824+
return NULL;
18741825

18751826
allow_nan = PyObject_IsTrue(allow_nan_obj);
18761827
if (allow_nan < 0)
1877-
return -1;
1828+
return NULL;
18781829

18791830
if (markers != Py_None && !PyDict_Check(markers)) {
18801831
PyErr_Format(PyExc_TypeError,
18811832
"make_encoder() argument 1 must be dict or None, "
18821833
"not %.200s", Py_TYPE(markers)->tp_name);
1883-
return -1;
1834+
return NULL;
18841835
}
18851836

1837+
s = (PyEncoderObject *)type->tp_alloc(type, 0);
1838+
if (s == NULL)
1839+
return NULL;
1840+
18861841
s->markers = markers;
18871842
s->defaultfn = defaultfn;
18881843
s->encoder = encoder;
@@ -1902,7 +1857,7 @@ encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
19021857
Py_INCREF(s->item_separator);
19031858
Py_INCREF(s->sort_keys);
19041859
Py_INCREF(s->skipkeys);
1905-
return 0;
1860+
return (PyObject *)s;
19061861
}
19071862

19081863
static PyObject *
@@ -2423,7 +2378,7 @@ PyTypeObject PyEncoderType = {
24232378
0, /* tp_descr_get */
24242379
0, /* tp_descr_set */
24252380
0, /* tp_dictoffset */
2426-
encoder_init, /* tp_init */
2381+
0, /* tp_init */
24272382
0, /* tp_alloc */
24282383
encoder_new, /* tp_new */
24292384
0, /* tp_free */
@@ -2448,10 +2403,8 @@ void
24482403
init_json(void)
24492404
{
24502405
PyObject *m;
2451-
PyScannerType.tp_new = PyType_GenericNew;
24522406
if (PyType_Ready(&PyScannerType) < 0)
24532407
return;
2454-
PyEncoderType.tp_new = PyType_GenericNew;
24552408
if (PyType_Ready(&PyEncoderType) < 0)
24562409
return;
24572410
m = Py_InitModule3("_json", speedups_methods, module_doc);

0 commit comments

Comments
 (0)