From d988c0b6bd1c5965fdc51428119e9104211e688f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 19 Apr 2018 09:16:43 +0300 Subject: [PATCH] [2.7] bpo-33308: Fix a crash in the parser module when convert an ST object. (GH-6519) (GH-6532) Converting with line_info=False and col_info=True crashed before. (cherry picked from commit e5362eaa75a154c6e91c5b1c47719d0a0f5ca48b) --- Lib/test/test_parser.py | 29 ++++++++++++++----- .../2018-04-18-19-12-25.bpo-33308.fW75xi.rst | 2 ++ Modules/parsermodule.c | 6 ++-- 3 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-04-18-19-12-25.bpo-33308.fW75xi.rst diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 34b9cbb8c16..73974a96f03 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -263,21 +263,19 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): # An absolutely minimal test of position information. Better # tests would be a big project. code = "def f(x):\n return x + 1" - st1 = parser.suite(code) - st2 = st1.totuple(line_info=1, col_info=1) + st = parser.suite(code) def walk(tree): node_type = tree[0] next = tree[1] - if isinstance(next, tuple): + if isinstance(next, (tuple, list)): for elt in tree[1:]: for x in walk(elt): yield x else: yield tree - terminals = list(walk(st2)) - self.assertEqual([ + expected = [ (1, 'def', 1, 0), (1, 'f', 1, 4), (7, '(', 1, 5), @@ -293,8 +291,25 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): (4, '', 2, 16), (6, '', 2, -1), (4, '', 2, -1), - (0, '', 2, -1)], - terminals) + (0, '', 2, -1), + ] + + self.assertEqual(list(walk(st.totuple(line_info=True, col_info=True))), + expected) + self.assertEqual(list(walk(st.totuple())), + [(t, n) for t, n, l, c in expected]) + self.assertEqual(list(walk(st.totuple(line_info=True))), + [(t, n, l) for t, n, l, c in expected]) + self.assertEqual(list(walk(st.totuple(col_info=True))), + [(t, n, c) for t, n, l, c in expected]) + self.assertEqual(list(walk(st.tolist(line_info=True, col_info=True))), + [list(x) for x in expected]) + self.assertEqual(list(walk(parser.st2tuple(st, line_info=True, + col_info=True))), + expected) + self.assertEqual(list(walk(parser.st2list(st, line_info=True, + col_info=True))), + [list(x) for x in expected]) # diff --git a/Misc/NEWS.d/next/Library/2018-04-18-19-12-25.bpo-33308.fW75xi.rst b/Misc/NEWS.d/next/Library/2018-04-18-19-12-25.bpo-33308.fW75xi.rst new file mode 100644 index 00000000000..586004a3c6c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-18-19-12-25.bpo-33308.fW75xi.rst @@ -0,0 +1,2 @@ +Fixed a crash in the :mod:`parser` module when converting an ST object to a +tree of tuples or lists with ``line_info=False`` and ``col_info=True``. diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index 79555428d1b..fcc618d5d90 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -121,10 +121,10 @@ node2tuple(node *n, /* node to convert */ if (result != NULL) { (void) addelem(result, 0, PyInt_FromLong(TYPE(n))); (void) addelem(result, 1, PyString_FromString(STR(n))); - if (lineno == 1) + if (lineno) (void) addelem(result, 2, PyInt_FromLong(n->n_lineno)); - if (col_offset == 1) - (void) addelem(result, 3, PyInt_FromLong(n->n_col_offset)); + if (col_offset) + (void) addelem(result, 2 + lineno, PyInt_FromLong(n->n_col_offset)); } return (result); }