Python 3.8, 322 bytes, safe
from ast import*
a=input()
b=walk(parse(a,"","eval"))
c=Constant
n=Name
if not {z.__class__ for z in b}-{Load,Call,Expression,c,n}:
for x in b:
if (i:=instanceof)(x,c):
if not i(x.value, str):
break
if i(x,n):
if x.id=="getattr":
break
else:
print(eval(a,{"__builtins__":{},"getattr":getattr})==eval)
Could probably be golfed more, but I'm trying to avoid accidentally leaking anything :P
Output is True
followed by a newline
Solution:
The program only runs programs that load names or constants and call functions. It also runs the input with only the global function
getattr
(which is essentially a function implementation of the.
, soa.b == getattr(a,"b")
, so our goal is to get toeval
with only these pieces. The solution that I came up with was by building up from an expression that I came up with that could become eval using the classes that Python loads at runtime, and then slowly using pythons magic dunder methods to try to "simplify" down language features that I can't use to get togetattr(getattr(getattr(getattr(getattr(getattr(getattr(getattr(getattr(getattr,"__class__"),"mro")(),"__getitem__")(1),"__subclasses__")(),"__getitem__")(getattr(getattr(getattr(getattr(getattr(getattr(getattr(getattr,"__class__"),"mro")(),"__getitem__")(1),"__subclasses__")(),"__repr__")(),"split")(","),"index")(" <class 'codecs.Codec'>")),"decode"),"__globals__"),"__getitem__")("__builtins__"),"__getitem__")("eval")