[2.7] [3.5] bpo-30070: Fixed leaks and crashes in errors handling in the parser module. (GH-1131). (GH-1185) (#1189)
(cherry picked from commit a79f4c219531c05fc8f670c1e4bbf12c081935d3).
(cherry picked from commit 952a05e4e2cf082b74a1676a2804f1f43a9b7702)
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c
index 2434c67..7955542 100644
--- a/Modules/parsermodule.c
+++ b/Modules/parsermodule.c
@@ -740,6 +740,9 @@
Py_ssize_t i;
int err;
+ if (len < 0) {
+ return NULL;
+ }
for (i = 1; i < len; ++i) {
/* elem must always be a sequence, however simple */
PyObject* elem = PySequence_GetItem(tuple, i);
@@ -766,7 +769,7 @@
PyErr_SetObject(parser_error, err);
Py_XDECREF(err);
Py_XDECREF(elem);
- return (0);
+ return NULL;
}
if (ISTERMINAL(type)) {
Py_ssize_t len = PyObject_Size(elem);
@@ -774,40 +777,53 @@
if ((len != 2) && (len != 3)) {
err_string("terminal nodes must have 2 or 3 entries");
- return 0;
+ Py_DECREF(elem);
+ return NULL;
}
temp = PySequence_GetItem(elem, 1);
- if (temp == NULL)
- return 0;
+ if (temp == NULL) {
+ Py_DECREF(elem);
+ return NULL;
+ }
if (!PyString_Check(temp)) {
PyErr_Format(parser_error,
"second item in terminal node must be a string,"
" found %s",
Py_TYPE(temp)->tp_name);
Py_DECREF(temp);
- return 0;
+ Py_DECREF(elem);
+ return NULL;
}
if (len == 3) {
PyObject *o = PySequence_GetItem(elem, 2);
- if (o != NULL) {
- if (PyInt_Check(o))
- *line_num = PyInt_AS_LONG(o);
- else {
- PyErr_Format(parser_error,
- "third item in terminal node must be an"
- " integer, found %s",
- Py_TYPE(temp)->tp_name);
- Py_DECREF(o);
- Py_DECREF(temp);
- return 0;
- }
- Py_DECREF(o);
+ if (o == NULL) {
+ Py_DECREF(temp);
+ Py_DECREF(elem);
+ return NULL;
}
+ if (PyInt_Check(o))
+ *line_num = PyInt_AS_LONG(o);
+ else {
+ PyErr_Format(parser_error,
+ "third item in terminal node must be an"
+ " integer, found %s",
+ Py_TYPE(temp)->tp_name);
+ Py_DECREF(o);
+ Py_DECREF(temp);
+ Py_DECREF(elem);
+ return NULL;
+ }
+ Py_DECREF(o);
}
len = PyString_GET_SIZE(temp) + 1;
strn = (char *)PyObject_MALLOC(len);
- if (strn != NULL)
- (void) memcpy(strn, PyString_AS_STRING(temp), len);
+ if (strn == NULL) {
+ Py_DECREF(temp);
+ Py_DECREF(elem);
+ PyErr_NoMemory();
+ return NULL;
+ }
+ (void) memcpy(strn, PyString_AS_STRING(temp), len);
Py_DECREF(temp);
}
else if (!ISNONTERMINAL(type)) {
@@ -815,18 +831,21 @@
* It has to be one or the other; this is an error.
* Raise an exception.
*/
- PyObject *err = Py_BuildValue("os", elem, "unknown node type.");
+ PyObject *err = Py_BuildValue("Os", elem, "unknown node type.");
PyErr_SetObject(parser_error, err);
Py_XDECREF(err);
- Py_XDECREF(elem);
- return (0);
+ Py_DECREF(elem);
+ return NULL;
}
err = PyNode_AddChild(root, type, strn, *line_num, 0);
if (err == E_NOMEM) {
+ Py_DECREF(elem);
PyObject_FREE(strn);
- return (node *) PyErr_NoMemory();
+ PyErr_NoMemory();
+ return NULL;
}
if (err == E_OVERFLOW) {
+ Py_DECREF(elem);
PyObject_FREE(strn);
PyErr_SetString(PyExc_ValueError,
"unsupported number of child nodes");
@@ -837,14 +856,14 @@
node* new_child = CHILD(root, i - 1);
if (new_child != build_node_children(elem, new_child, line_num)) {
- Py_XDECREF(elem);
- return (0);
+ Py_DECREF(elem);
+ return NULL;
}
}
else if (type == NEWLINE) { /* It's true: we increment the */
++(*line_num); /* line number *after* the newline! */
}
- Py_XDECREF(elem);
+ Py_DECREF(elem);
}
return root;
}
@@ -879,8 +898,23 @@
if (num == encoding_decl) {
encoding = PySequence_GetItem(tuple, 2);
+ if (encoding == NULL) {
+ PyErr_SetString(parser_error, "missed encoding");
+ return NULL;
+ }
+ if (!PyString_Check(encoding)) {
+ PyErr_Format(parser_error,
+ "encoding must be a string, found %.200s",
+ Py_TYPE(encoding)->tp_name);
+ Py_DECREF(encoding);
+ return NULL;
+ }
/* tuple isn't borrowed anymore here, need to DECREF */
tuple = PySequence_GetSlice(tuple, 0, 2);
+ if (tuple == NULL) {
+ Py_DECREF(encoding);
+ return NULL;
+ }
}
res = PyNode_New(num);
if (res != NULL) {
@@ -892,19 +926,27 @@
Py_ssize_t len;
len = PyString_GET_SIZE(encoding) + 1;
res->n_str = (char *)PyObject_MALLOC(len);
- if (res->n_str != NULL)
- (void) memcpy(res->n_str, PyString_AS_STRING(encoding), len);
- Py_DECREF(encoding);
- Py_DECREF(tuple);
+ if (res->n_str == NULL) {
+ PyNode_Free(res);
+ Py_DECREF(encoding);
+ Py_DECREF(tuple);
+ PyErr_NoMemory();
+ return NULL;
+ }
+ (void) memcpy(res->n_str, PyString_AS_STRING(encoding), len);
}
}
+ if (encoding != NULL) {
+ Py_DECREF(encoding);
+ Py_DECREF(tuple);
+ }
}
else {
/* The tuple is illegal -- if the number is neither TERMINAL nor
* NONTERMINAL, we can't use it. Not sure the implementation
* allows this condition, but the API doesn't preclude it.
*/
- PyObject *err = Py_BuildValue("os", tuple,
+ PyObject *err = Py_BuildValue("Os", tuple,
"Illegal component tuple.");
PyErr_SetObject(parser_error, err);
Py_XDECREF(err);
@@ -3371,7 +3413,6 @@
result = Py_BuildValue("O(O)", pickle_constructor, tuple);
Py_DECREF(tuple);
}
- Py_DECREF(empty_dict);
Py_DECREF(newargs);
}
finally: