Skip to content

Commit

Permalink
Merge pull request #2 from carljm/funcstoo
Browse files Browse the repository at this point in the history
evaluate namespaces recursively, and function namespaces, too
  • Loading branch information
carljm committed May 18, 2023
2 parents 1f98dce + 45dce53 commit a39bfc9
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 13 deletions.
33 changes: 25 additions & 8 deletions evalserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,35 @@
import re
from socket import socket, AF_INET, SOCK_STREAM
import traceback
import types
from typing import Any, Mapping


def deaddress(text: str) -> str:
return re.sub(r"0x[0-9a-f]+", "0x...", text)


def try_exec(data: bytes) -> dict[str, str | dict[str, str]]:
def get_ns(ns: Mapping[str, Any]) -> dict[str, Any]:
ret = {}
for k, v in ns.items():
child_ns: Mapping[str, Any] | None = None
if isinstance(v, type):
child_ns = v.__dict__
elif isinstance(v, types.FunctionType):
try:
child_ns = v()
except Exception as e:
child_ns = {"error": "run", "message": repr(e)}
child: Any
if child_ns is not None:
child = get_ns(child_ns)
else:
child = deaddress(repr(v))
ret[k] = child
return ret


def try_exec(data: bytes) -> dict[str, Any]:
try:
data_str = data.decode("utf-8")
except UnicodeDecodeError:
Expand All @@ -29,17 +51,12 @@ def try_exec(data: bytes) -> dict[str, str | dict[str, str]]:
except Exception as e:
return {"error": "compile", "message": repr(e)}
try:
ns = {}
ns: dict[str, Any] = {}
exec(code, ns, ns)
del ns["__builtins__"]
except Exception as e:
return {"error": "run", "message": repr(e)}
classdicts = {}
for k, v in ns.items():
if isinstance(v, type):
classdict = repr(v.__dict__)
classdicts[k] = deaddress(classdict)
return {"result": deaddress(repr(ns)), "classdicts": classdicts}
return get_ns(ns)


@dataclass
Expand Down
9 changes: 4 additions & 5 deletions test_fuzz_comps.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ def statements():
st.from_type(ast.Global),
st.from_type(ast.Expr),
st.from_type(ast.FunctionDef),
st.from_type(ast.Name),
classes(),
)

Expand All @@ -255,7 +256,8 @@ def functions(draw):
name = draw(identifiers())
arg_names = draw(st.sets(identifiers(), min_size=0, max_size=3))
args = ast.arguments(args=[ast.arg(name) for name in arg_names], defaults=[])
stmts = draw(st.lists(statements(), min_size=1, max_size=10))
stmts = draw(st.lists(statements(), min_size=1, max_size=5))
stmts += [ast.Return(ast.Call(ast.Name("locals"), [], []))]
return ast.FunctionDef(name, args, stmts, [])


Expand All @@ -265,10 +267,7 @@ def functions(draw):
def module_level_statements():
# require top-level class or function; plain module-level comprehensions are
# not very interesting in terms of finding scoping bugs
return st.one_of(
st.from_type(ast.ClassDef),
st.from_type(ast.FunctionDef)
)
return st.one_of(st.from_type(ast.ClassDef), st.from_type(ast.FunctionDef))


st.register_type_strategy(
Expand Down

0 comments on commit a39bfc9

Please sign in to comment.