Skip to content

Commit a39bfc9

Browse files
authored
Merge pull request #2 from carljm/funcstoo
evaluate namespaces recursively, and function namespaces, too
2 parents 1f98dce + 45dce53 commit a39bfc9

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

evalserver.py

+25-8
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,35 @@
1313
import re
1414
from socket import socket, AF_INET, SOCK_STREAM
1515
import traceback
16+
import types
17+
from typing import Any, Mapping
1618

1719

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

2123

22-
def try_exec(data: bytes) -> dict[str, str | dict[str, str]]:
24+
def get_ns(ns: Mapping[str, Any]) -> dict[str, Any]:
25+
ret = {}
26+
for k, v in ns.items():
27+
child_ns: Mapping[str, Any] | None = None
28+
if isinstance(v, type):
29+
child_ns = v.__dict__
30+
elif isinstance(v, types.FunctionType):
31+
try:
32+
child_ns = v()
33+
except Exception as e:
34+
child_ns = {"error": "run", "message": repr(e)}
35+
child: Any
36+
if child_ns is not None:
37+
child = get_ns(child_ns)
38+
else:
39+
child = deaddress(repr(v))
40+
ret[k] = child
41+
return ret
42+
43+
44+
def try_exec(data: bytes) -> dict[str, Any]:
2345
try:
2446
data_str = data.decode("utf-8")
2547
except UnicodeDecodeError:
@@ -29,17 +51,12 @@ def try_exec(data: bytes) -> dict[str, str | dict[str, str]]:
2951
except Exception as e:
3052
return {"error": "compile", "message": repr(e)}
3153
try:
32-
ns = {}
54+
ns: dict[str, Any] = {}
3355
exec(code, ns, ns)
3456
del ns["__builtins__"]
3557
except Exception as e:
3658
return {"error": "run", "message": repr(e)}
37-
classdicts = {}
38-
for k, v in ns.items():
39-
if isinstance(v, type):
40-
classdict = repr(v.__dict__)
41-
classdicts[k] = deaddress(classdict)
42-
return {"result": deaddress(repr(ns)), "classdicts": classdicts}
59+
return get_ns(ns)
4360

4461

4562
@dataclass

test_fuzz_comps.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ def statements():
236236
st.from_type(ast.Global),
237237
st.from_type(ast.Expr),
238238
st.from_type(ast.FunctionDef),
239+
st.from_type(ast.Name),
239240
classes(),
240241
)
241242

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

261263

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

273272

274273
st.register_type_strategy(

0 commit comments

Comments
 (0)