diff options
author | Oren Milman <orenmn@gmail.com> | 2017-09-30 17:16:24 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2017-09-30 17:16:24 (GMT) |
commit | 7dc46d8cf5854d9f4ce3271b29c21aea4872e8ad (patch) | |
tree | 65d6f6876bfd7c627d9090e1bfadf24b99c970a8 | |
parent | f4ea642cb60556231e714089a79d3c59c202661e (diff) | |
download | cpython-7dc46d8cf5854d9f4ce3271b29c21aea4872e8ad.zip cpython-7dc46d8cf5854d9f4ce3271b29c21aea4872e8ad.tar.gz cpython-7dc46d8cf5854d9f4ce3271b29c21aea4872e8ad.tar.bz2 |
bpo-31592: Fix an assertion failure in Python parser in case of a bad unicodedata.normalize(). (#3767)
-rw-r--r-- | Lib/test/test_ast.py | 10 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2017-09-26-16-05-04.bpo-31592.IFBZj9.rst | 2 | ||||
-rw-r--r-- | Python/ast.c | 28 |
3 files changed, 28 insertions, 12 deletions
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 2f59527..aa53503 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -431,6 +431,16 @@ class AST_Tests(unittest.TestCase): compile(empty_yield_from, "<test>", "exec") self.assertIn("field value is required", str(cm.exception)) + @support.cpython_only + def test_issue31592(self): + # There shouldn't be an assertion failure in case of a bad + # unicodedata.normalize(). + import unicodedata + def bad_normalize(*args): + return None + with support.swap_attr(unicodedata, 'normalize', bad_normalize): + self.assertRaises(TypeError, ast.parse, '\u03D5') + class ASTHelpers_Test(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-26-16-05-04.bpo-31592.IFBZj9.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-26-16-05-04.bpo-31592.IFBZj9.rst new file mode 100644 index 0000000..29f3461 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-26-16-05-04.bpo-31592.IFBZj9.rst @@ -0,0 +1,2 @@ +Fixed an assertion failure in Python parser in case of a bad `unicodedata.normalize()`. +Patch by Oren Milman. diff --git a/Python/ast.c b/Python/ast.c index fd42c00..33356da 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -594,7 +594,6 @@ struct compiling { PyArena *c_arena; /* Arena for allocating memory. */ PyObject *c_filename; /* filename */ PyObject *c_normalize; /* Normalization function from unicodedata. */ - PyObject *c_normalize_args; /* Normalization argument tuple. */ }; static asdl_seq *seq_for_testlist(struct compiling *, const node *); @@ -631,12 +630,6 @@ init_normalization(struct compiling *c) Py_DECREF(m); if (!c->c_normalize) return 0; - c->c_normalize_args = Py_BuildValue("(sN)", "NFKC", Py_None); - if (!c->c_normalize_args) { - Py_CLEAR(c->c_normalize); - return 0; - } - PyTuple_SET_ITEM(c->c_normalize_args, 1, NULL); return 1; } @@ -652,15 +645,29 @@ new_identifier(const char *n, struct compiling *c) identifier; if so, normalize to NFKC. */ if (!PyUnicode_IS_ASCII(id)) { PyObject *id2; + _Py_IDENTIFIER(NFKC); if (!c->c_normalize && !init_normalization(c)) { Py_DECREF(id); return NULL; } - PyTuple_SET_ITEM(c->c_normalize_args, 1, id); - id2 = PyObject_Call(c->c_normalize, c->c_normalize_args, NULL); + PyObject *form = _PyUnicode_FromId(&PyId_NFKC); + if (form == NULL) { + Py_DECREF(id); + return NULL; + } + PyObject *args[2] = {form, id}; + id2 = _PyObject_FastCall(c->c_normalize, args, 2); Py_DECREF(id); if (!id2) return NULL; + if (!PyUnicode_Check(id2)) { + PyErr_Format(PyExc_TypeError, + "unicodedata.normalize() must return a string, not " + "%.200s", + Py_TYPE(id2)->tp_name); + Py_DECREF(id2); + return NULL; + } id = id2; } PyUnicode_InternInPlace(&id); @@ -779,7 +786,6 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags, /* borrowed reference */ c.c_filename = filename; c.c_normalize = NULL; - c.c_normalize_args = NULL; if (TYPE(n) == encoding_decl) n = CHILD(n, 0); @@ -872,8 +878,6 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags, out: if (c.c_normalize) { Py_DECREF(c.c_normalize); - PyTuple_SET_ITEM(c.c_normalize_args, 1, NULL); - Py_DECREF(c.c_normalize_args); } return res; } |