Fix INTERNALERROR when accessing locals / globals with faulty `exec`

This commit is contained in:
Anthony Sottile 2020-09-11 16:44:24 -07:00
parent 389e30283c
commit 96a17b1683
3 changed files with 27 additions and 3 deletions

View File

@ -0,0 +1 @@
Fix INTERNALERROR when accessing locals / globals with faulty ``exec``.

View File

@ -246,10 +246,20 @@ class TracebackEntry:
Mostly for internal use.
"""
f = self.frame
tbh = f.f_locals.get(
"__tracebackhide__", f.f_globals.get("__tracebackhide__", False)
tbh = (
False
) # type: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]]
for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals):
# in normal cases, f_locals and f_globals are dictionaries
# however via `exec(...)` / `eval(...)` they can be other types
# (even incorrect types!).
# as such, we suppress all exceptions while accessing __tracebackhide__
try:
tbh = maybe_ns_dct["__tracebackhide__"]
except Exception:
pass
else:
break
if tbh and callable(tbh):
return tbh(None if self._excinfo is None else self._excinfo())
return tbh

View File

@ -1352,6 +1352,19 @@ raise ValueError()
)
assert out == expected_out
def test_exec_type_error_filter(self, importasmod):
"""See #7742"""
mod = importasmod(
"""\
def f():
exec("a = 1", {}, [])
"""
)
with pytest.raises(TypeError) as excinfo:
mod.f()
# previously crashed with `AttributeError: list has no attribute get`
excinfo.traceback.filter()
@pytest.mark.parametrize("style", ["short", "long"])
@pytest.mark.parametrize("encoding", [None, "utf8", "utf16"])