Skip to content
This repository was archived by the owner on Jul 27, 2023. It is now read-only.

Commit ac22c95

Browse files
committed
Fix infinite loop caused by form feed
1 parent db65e12 commit ac22c95

File tree

1 file changed

+377
-0
lines changed

1 file changed

+377
-0
lines changed

parser/src/lexer.rs

Lines changed: 377 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ impl<'source> Lexer<'source> {
546546
}
547547
// Form feed
548548
'\x0C' => {
549+
self.cursor.bump();
549550
indentation = Indentation::root();
550551
}
551552
_ => break,
@@ -1786,4 +1787,380 @@ mod tests {
17861787
fn triple_quoted_macos_eol() {
17871788
assert_triple_quoted(MAC_EOL);
17881789
}
1790+
1791+
#[test]
1792+
fn regression() {
1793+
for token in lex(
1794+
r#"# Tests some corner cases with isinstance() and issubclass(). While these
1795+
# tests use new style classes and properties, they actually do whitebox
1796+
# testing of error conditions uncovered when using extension types.
1797+
1798+
import unittest
1799+
import sys
1800+
import typing
1801+
from test import support
1802+
1803+
1804+
1805+
1806+
class TestIsInstanceExceptions(unittest.TestCase):
1807+
# Test to make sure that an AttributeError when accessing the instance's
1808+
# class's bases is masked. This was actually a bug in Python 2.2 and
1809+
# 2.2.1 where the exception wasn't caught but it also wasn't being cleared
1810+
# (leading to an "undetected error" in the debug build). Set up is,
1811+
# isinstance(inst, cls) where:
1812+
#
1813+
# - cls isn't a type, or a tuple
1814+
# - cls has a __bases__ attribute
1815+
# - inst has a __class__ attribute
1816+
# - inst.__class__ as no __bases__ attribute
1817+
#
1818+
# Sounds complicated, I know, but this mimics a situation where an
1819+
# extension type raises an AttributeError when its __bases__ attribute is
1820+
# gotten. In that case, isinstance() should return False.
1821+
def test_class_has_no_bases(self):
1822+
class I(object):
1823+
def getclass(self):
1824+
# This must return an object that has no __bases__ attribute
1825+
return None
1826+
__class__ = property(getclass)
1827+
1828+
class C(object):
1829+
def getbases(self):
1830+
return ()
1831+
__bases__ = property(getbases)
1832+
1833+
self.assertEqual(False, isinstance(I(), C()))
1834+
1835+
# Like above except that inst.__class__.__bases__ raises an exception
1836+
# other than AttributeError
1837+
def test_bases_raises_other_than_attribute_error(self):
1838+
class E(object):
1839+
def getbases(self):
1840+
raise RuntimeError
1841+
__bases__ = property(getbases)
1842+
1843+
class I(object):
1844+
def getclass(self):
1845+
return E()
1846+
__class__ = property(getclass)
1847+
1848+
class C(object):
1849+
def getbases(self):
1850+
return ()
1851+
__bases__ = property(getbases)
1852+
1853+
self.assertRaises(RuntimeError, isinstance, I(), C())
1854+
1855+
# Here's a situation where getattr(cls, '__bases__') raises an exception.
1856+
# If that exception is not AttributeError, it should not get masked
1857+
def test_dont_mask_non_attribute_error(self):
1858+
class I: pass
1859+
1860+
class C(object):
1861+
def getbases(self):
1862+
raise RuntimeError
1863+
__bases__ = property(getbases)
1864+
1865+
self.assertRaises(RuntimeError, isinstance, I(), C())
1866+
1867+
# Like above, except that getattr(cls, '__bases__') raises an
1868+
# AttributeError, which /should/ get masked as a TypeError
1869+
def test_mask_attribute_error(self):
1870+
class I: pass
1871+
1872+
class C(object):
1873+
def getbases(self):
1874+
raise AttributeError
1875+
__bases__ = property(getbases)
1876+
1877+
self.assertRaises(TypeError, isinstance, I(), C())
1878+
1879+
# check that we don't mask non AttributeErrors
1880+
# see: http://bugs.python.org/issue1574217
1881+
def test_isinstance_dont_mask_non_attribute_error(self):
1882+
class C(object):
1883+
def getclass(self):
1884+
raise RuntimeError
1885+
__class__ = property(getclass)
1886+
1887+
c = C()
1888+
self.assertRaises(RuntimeError, isinstance, c, bool)
1889+
1890+
# test another code path
1891+
class D: pass
1892+
self.assertRaises(RuntimeError, isinstance, c, D)
1893+
1894+
1895+
1896+
# These tests are similar to above, but tickle certain code paths in
1897+
# issubclass() instead of isinstance() -- really PyObject_IsSubclass()
1898+
# vs. PyObject_IsInstance().
1899+
class TestIsSubclassExceptions(unittest.TestCase):
1900+
def test_dont_mask_non_attribute_error(self):
1901+
class C(object):
1902+
def getbases(self):
1903+
raise RuntimeError
1904+
__bases__ = property(getbases)
1905+
1906+
class S(C): pass
1907+
1908+
self.assertRaises(RuntimeError, issubclass, C(), S())
1909+
1910+
def test_mask_attribute_error(self):
1911+
class C(object):
1912+
def getbases(self):
1913+
raise AttributeError
1914+
__bases__ = property(getbases)
1915+
1916+
class S(C): pass
1917+
1918+
self.assertRaises(TypeError, issubclass, C(), S())
1919+
1920+
# Like above, but test the second branch, where the __bases__ of the
1921+
# second arg (the cls arg) is tested. This means the first arg must
1922+
# return a valid __bases__, and it's okay for it to be a normal --
1923+
# unrelated by inheritance -- class.
1924+
def test_dont_mask_non_attribute_error_in_cls_arg(self):
1925+
class B: pass
1926+
1927+
class C(object):
1928+
def getbases(self):
1929+
raise RuntimeError
1930+
__bases__ = property(getbases)
1931+
1932+
self.assertRaises(RuntimeError, issubclass, B, C())
1933+
1934+
def test_mask_attribute_error_in_cls_arg(self):
1935+
class B: pass
1936+
1937+
class C(object):
1938+
def getbases(self):
1939+
raise AttributeError
1940+
__bases__ = property(getbases)
1941+
1942+
self.assertRaises(TypeError, issubclass, B, C())
1943+
1944+
1945+
1946+
1947+
# meta classes for creating abstract classes and instances
1948+
class AbstractClass(object):
1949+
def __init__(self, bases):
1950+
self.bases = bases
1951+
1952+
def getbases(self):
1953+
return self.bases
1954+
__bases__ = property(getbases)
1955+
1956+
def __call__(self):
1957+
return AbstractInstance(self)
1958+
1959+
class AbstractInstance(object):
1960+
def __init__(self, klass):
1961+
self.klass = klass
1962+
1963+
def getclass(self):
1964+
return self.klass
1965+
__class__ = property(getclass)
1966+
1967+
# abstract classes
1968+
AbstractSuper = AbstractClass(bases=())
1969+
1970+
AbstractChild = AbstractClass(bases=(AbstractSuper,))
1971+
1972+
# normal classes
1973+
class Super:
1974+
pass
1975+
1976+
class Child(Super):
1977+
pass
1978+
1979+
1980+
class TestIsInstanceIsSubclass(unittest.TestCase):
1981+
# Tests to ensure that isinstance and issubclass work on abstract
1982+
# classes and instances. Before the 2.2 release, TypeErrors were
1983+
# raised when boolean values should have been returned. The bug was
1984+
# triggered by mixing 'normal' classes and instances were with
1985+
# 'abstract' classes and instances. This case tries to test all
1986+
# combinations.
1987+
1988+
def test_isinstance_normal(self):
1989+
# normal instances
1990+
self.assertEqual(True, isinstance(Super(), Super))
1991+
self.assertEqual(False, isinstance(Super(), Child))
1992+
self.assertEqual(False, isinstance(Super(), AbstractSuper))
1993+
self.assertEqual(False, isinstance(Super(), AbstractChild))
1994+
1995+
self.assertEqual(True, isinstance(Child(), Super))
1996+
self.assertEqual(False, isinstance(Child(), AbstractSuper))
1997+
1998+
def test_isinstance_abstract(self):
1999+
# abstract instances
2000+
self.assertEqual(True, isinstance(AbstractSuper(), AbstractSuper))
2001+
self.assertEqual(False, isinstance(AbstractSuper(), AbstractChild))
2002+
self.assertEqual(False, isinstance(AbstractSuper(), Super))
2003+
self.assertEqual(False, isinstance(AbstractSuper(), Child))
2004+
2005+
self.assertEqual(True, isinstance(AbstractChild(), AbstractChild))
2006+
self.assertEqual(True, isinstance(AbstractChild(), AbstractSuper))
2007+
self.assertEqual(False, isinstance(AbstractChild(), Super))
2008+
self.assertEqual(False, isinstance(AbstractChild(), Child))
2009+
2010+
def test_isinstance_with_or_union(self):
2011+
self.assertTrue(isinstance(Super(), Super | int))
2012+
self.assertFalse(isinstance(None, str | int))
2013+
self.assertTrue(isinstance(3, str | int))
2014+
self.assertTrue(isinstance("", str | int))
2015+
self.assertTrue(isinstance([], typing.List | typing.Tuple))
2016+
self.assertTrue(isinstance(2, typing.List | int))
2017+
self.assertFalse(isinstance(2, typing.List | typing.Tuple))
2018+
self.assertTrue(isinstance(None, int | None))
2019+
self.assertFalse(isinstance(3.14, int | str))
2020+
with self.assertRaises(TypeError):
2021+
isinstance(2, list[int])
2022+
with self.assertRaises(TypeError):
2023+
isinstance(2, list[int] | int)
2024+
with self.assertRaises(TypeError):
2025+
isinstance(2, int | str | list[int] | float)
2026+
2027+
2028+
2029+
def test_subclass_normal(self):
2030+
# normal classes
2031+
self.assertEqual(True, issubclass(Super, Super))
2032+
self.assertEqual(False, issubclass(Super, AbstractSuper))
2033+
self.assertEqual(False, issubclass(Super, Child))
2034+
2035+
self.assertEqual(True, issubclass(Child, Child))
2036+
self.assertEqual(True, issubclass(Child, Super))
2037+
self.assertEqual(False, issubclass(Child, AbstractSuper))
2038+
self.assertTrue(issubclass(typing.List, typing.List|typing.Tuple))
2039+
self.assertFalse(issubclass(int, typing.List|typing.Tuple))
2040+
2041+
def test_subclass_abstract(self):
2042+
# abstract classes
2043+
self.assertEqual(True, issubclass(AbstractSuper, AbstractSuper))
2044+
self.assertEqual(False, issubclass(AbstractSuper, AbstractChild))
2045+
self.assertEqual(False, issubclass(AbstractSuper, Child))
2046+
2047+
self.assertEqual(True, issubclass(AbstractChild, AbstractChild))
2048+
self.assertEqual(True, issubclass(AbstractChild, AbstractSuper))
2049+
self.assertEqual(False, issubclass(AbstractChild, Super))
2050+
self.assertEqual(False, issubclass(AbstractChild, Child))
2051+
2052+
def test_subclass_tuple(self):
2053+
# test with a tuple as the second argument classes
2054+
self.assertEqual(True, issubclass(Child, (Child,)))
2055+
self.assertEqual(True, issubclass(Child, (Super,)))
2056+
self.assertEqual(False, issubclass(Super, (Child,)))
2057+
self.assertEqual(True, issubclass(Super, (Child, Super)))
2058+
self.assertEqual(False, issubclass(Child, ()))
2059+
self.assertEqual(True, issubclass(Super, (Child, (Super,))))
2060+
2061+
self.assertEqual(True, issubclass(int, (int, (float, int))))
2062+
self.assertEqual(True, issubclass(str, (str, (Child, str))))
2063+
2064+
def test_subclass_recursion_limit(self):
2065+
# make sure that issubclass raises RecursionError before the C stack is
2066+
# blown
2067+
with support.infinite_recursion():
2068+
self.assertRaises(RecursionError, blowstack, issubclass, str, str)
2069+
2070+
def test_isinstance_recursion_limit(self):
2071+
# make sure that issubclass raises RecursionError before the C stack is
2072+
# blown
2073+
with support.infinite_recursion():
2074+
self.assertRaises(RecursionError, blowstack, isinstance, '', str)
2075+
2076+
def test_subclass_with_union(self):
2077+
self.assertTrue(issubclass(int, int | float | int))
2078+
self.assertTrue(issubclass(str, str | Child | str))
2079+
self.assertFalse(issubclass(dict, float|str))
2080+
self.assertFalse(issubclass(object, float|str))
2081+
with self.assertRaises(TypeError):
2082+
issubclass(2, Child | Super)
2083+
with self.assertRaises(TypeError):
2084+
issubclass(int, list[int] | Child)
2085+
2086+
def test_issubclass_refcount_handling(self):
2087+
# bpo-39382: abstract_issubclass() didn't hold item reference while
2088+
# peeking in the bases tuple, in the single inheritance case.
2089+
class A:
2090+
@property
2091+
def __bases__(self):
2092+
return (int, )
2093+
2094+
class B:
2095+
def __init__(self):
2096+
# setting this here increases the chances of exhibiting the bug,
2097+
# probably due to memory layout changes.
2098+
self.x = 1
2099+
2100+
@property
2101+
def __bases__(self):
2102+
return (A(), )
2103+
2104+
self.assertEqual(True, issubclass(B(), int))
2105+
2106+
def test_infinite_recursion_in_bases(self):
2107+
class X:
2108+
@property
2109+
def __bases__(self):
2110+
return self.__bases__
2111+
with support.infinite_recursion():
2112+
self.assertRaises(RecursionError, issubclass, X(), int)
2113+
self.assertRaises(RecursionError, issubclass, int, X())
2114+
self.assertRaises(RecursionError, isinstance, 1, X())
2115+
2116+
def test_infinite_recursion_via_bases_tuple(self):
2117+
"""Regression test for bpo-30570."""
2118+
class Failure(object):
2119+
def __getattr__(self, attr):
2120+
return (self, None)
2121+
with support.infinite_recursion():
2122+
with self.assertRaises(RecursionError):
2123+
issubclass(Failure(), int)
2124+
2125+
def test_infinite_cycle_in_bases(self):
2126+
"""Regression test for bpo-30570."""
2127+
class X:
2128+
@property
2129+
def __bases__(self):
2130+
return (self, self, self)
2131+
with support.infinite_recursion():
2132+
self.assertRaises(RecursionError, issubclass, X(), int)
2133+
2134+
def test_infinitely_many_bases(self):
2135+
"""Regression test for bpo-30570."""
2136+
class X:
2137+
def __getattr__(self, attr):
2138+
self.assertEqual(attr, "__bases__")
2139+
class A:
2140+
pass
2141+
class B:
2142+
pass
2143+
A.__getattr__ = B.__getattr__ = X.__getattr__
2144+
return (A(), B())
2145+
with support.infinite_recursion():
2146+
self.assertRaises(RecursionError, issubclass, X(), int)
2147+
2148+
2149+
def blowstack(fxn, arg, compare_to):
2150+
# Make sure that calling isinstance with a deeply nested tuple for its
2151+
# argument will raise RecursionError eventually.
2152+
tuple_arg = (compare_to,)
2153+
for cnt in range(sys.getrecursionlimit()+5):
2154+
tuple_arg = (tuple_arg,)
2155+
fxn(arg, tuple_arg)
2156+
2157+
2158+
2159+
if __name__ == '__main__':
2160+
unittest.main()"#,
2161+
Mode::Module,
2162+
) {
2163+
dbg!(token);
2164+
}
2165+
}
17892166
}

0 commit comments

Comments
 (0)