Skip to content

Commit a4dfe1c

Browse files
miss-islingtonserhiy-storchaka
authored andcommitted
[3.6] bpo-31592: Fix an assertion failure in Python parser in case of a bad unicodedata.normalize(). (GH-3767) (#3836)
(cherry picked from commit 7dc46d8)
1 parent 9ef28b6 commit a4dfe1c

File tree

3 files changed

+28
-12
lines changed

3 files changed

+28
-12
lines changed

Lib/test/test_ast.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,16 @@ def test_empty_yield_from(self):
421421
compile(empty_yield_from, "<test>", "exec")
422422
self.assertIn("field value is required", str(cm.exception))
423423

424+
@support.cpython_only
425+
def test_issue31592(self):
426+
# There shouldn't be an assertion failure in case of a bad
427+
# unicodedata.normalize().
428+
import unicodedata
429+
def bad_normalize(*args):
430+
return None
431+
with support.swap_attr(unicodedata, 'normalize', bad_normalize):
432+
self.assertRaises(TypeError, ast.parse, '\u03D5')
433+
424434

425435
class ASTHelpers_Test(unittest.TestCase):
426436

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed an assertion failure in Python parser in case of a bad `unicodedata.normalize()`.
2+
Patch by Oren Milman.

Python/ast.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,6 @@ struct compiling {
589589
PyArena *c_arena; /* Arena for allocating memory. */
590590
PyObject *c_filename; /* filename */
591591
PyObject *c_normalize; /* Normalization function from unicodedata. */
592-
PyObject *c_normalize_args; /* Normalization argument tuple. */
593592
};
594593

595594
static asdl_seq *seq_for_testlist(struct compiling *, const node *);
@@ -624,12 +623,6 @@ init_normalization(struct compiling *c)
624623
Py_DECREF(m);
625624
if (!c->c_normalize)
626625
return 0;
627-
c->c_normalize_args = Py_BuildValue("(sN)", "NFKC", Py_None);
628-
if (!c->c_normalize_args) {
629-
Py_CLEAR(c->c_normalize);
630-
return 0;
631-
}
632-
PyTuple_SET_ITEM(c->c_normalize_args, 1, NULL);
633626
return 1;
634627
}
635628

@@ -645,15 +638,29 @@ new_identifier(const char *n, struct compiling *c)
645638
identifier; if so, normalize to NFKC. */
646639
if (!PyUnicode_IS_ASCII(id)) {
647640
PyObject *id2;
641+
_Py_IDENTIFIER(NFKC);
648642
if (!c->c_normalize && !init_normalization(c)) {
649643
Py_DECREF(id);
650644
return NULL;
651645
}
652-
PyTuple_SET_ITEM(c->c_normalize_args, 1, id);
653-
id2 = PyObject_Call(c->c_normalize, c->c_normalize_args, NULL);
646+
PyObject *form = _PyUnicode_FromId(&PyId_NFKC);
647+
if (form == NULL) {
648+
Py_DECREF(id);
649+
return NULL;
650+
}
651+
PyObject *args[2] = {form, id};
652+
id2 = _PyObject_FastCall(c->c_normalize, args, 2);
654653
Py_DECREF(id);
655654
if (!id2)
656655
return NULL;
656+
if (!PyUnicode_Check(id2)) {
657+
PyErr_Format(PyExc_TypeError,
658+
"unicodedata.normalize() must return a string, not "
659+
"%.200s",
660+
Py_TYPE(id2)->tp_name);
661+
Py_DECREF(id2);
662+
return NULL;
663+
}
657664
id = id2;
658665
}
659666
PyUnicode_InternInPlace(&id);
@@ -773,7 +780,6 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
773780
/* borrowed reference */
774781
c.c_filename = filename;
775782
c.c_normalize = NULL;
776-
c.c_normalize_args = NULL;
777783

778784
if (TYPE(n) == encoding_decl)
779785
n = CHILD(n, 0);
@@ -866,8 +872,6 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
866872
out:
867873
if (c.c_normalize) {
868874
Py_DECREF(c.c_normalize);
869-
PyTuple_SET_ITEM(c.c_normalize_args, 1, NULL);
870-
Py_DECREF(c.c_normalize_args);
871875
}
872876
return res;
873877
}

0 commit comments

Comments
 (0)