forked from ethanchewy/PythonBuddy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_stackcheck.py
More file actions
120 lines (105 loc) · 3.31 KB
/
test_stackcheck.py
File metadata and controls
120 lines (105 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from rpython.conftest import option
from rpython.translator.translator import TranslationContext, graphof
from rpython.translator.backendopt.all import backend_optimizations
from rpython.translator.transform import insert_ll_stackcheck
from rpython.memory.gctransform import shadowstack
def _follow_path_naive(block, cur_path, accum):
cur_path = (cur_path, block)
if not block.exits:
ops = []
while cur_path:
block = cur_path[1]
ops.extend(reversed(block.operations))
cur_path = cur_path[0]
accum.append(list(reversed(ops)))
return
for link in block.exits:
_follow_path_naive(link.target, cur_path, accum)
# explodes on loops!
def paths_naive(g):
accum = []
_follow_path_naive(g.startblock, None, accum)
return accum
def direct_target(spaceop):
return spaceop.args[0].value._obj.graph.name
def direct_calls(p):
names = []
for spaceop in p:
if spaceop.opname == 'direct_call':
names.append(direct_target(spaceop))
return names
def check(g, funcname, ignore=None):
paths = paths_naive(g)
relevant = []
for p in paths:
funcs_called = direct_calls(p)
if funcname in funcs_called and ignore not in funcs_called:
assert 'stack_check___' in funcs_called
assert (funcs_called.index(funcname) >
funcs_called.index('stack_check___'))
relevant.append(p)
return relevant
class A(object):
def __init__(self, n):
self.n = n
def f(a):
x = A(a.n+1)
if x.n == 10:
return
f(x)
def g(n):
f(A(n))
return 0
def test_simple():
t = TranslationContext()
a = t.buildannotator()
a.build_types(g, [int])
a.simplify()
t.buildrtyper().specialize()
backend_optimizations(t)
t.checkgraphs()
n = insert_ll_stackcheck(t)
t.checkgraphs()
assert n == 1
if option.view:
t.view()
check(graphof(t, f), 'f')
def test_gctransformed():
t = TranslationContext()
a = t.buildannotator()
a.build_types(g, [int])
a.simplify()
t.buildrtyper().specialize()
backend_optimizations(t)
t.checkgraphs()
n = insert_ll_stackcheck(t)
t.checkgraphs()
assert n == 1
exctransf = t.getexceptiontransformer()
f_graph = graphof(t, f)
exctransf.create_exception_handling(f_graph)
if option.view:
f_graph.show()
check(f_graph, 'f')
class GCTransform(shadowstack.ShadowStackFrameworkGCTransformer):
from rpython.memory.gc.generation import GenerationGC as \
GCClass
GC_PARAMS = {}
gctransf = GCTransform(t)
gctransf.transform_graph(f_graph)
if option.view:
f_graph.show()
relevant = check(f_graph, 'f')
for p in relevant:
in_between = False
reload = 0
for spaceop in p:
if spaceop.opname == 'direct_call':
target = direct_target(spaceop)
if target == 'f':
in_between = False
elif target == 'stack_check___':
in_between = True
if in_between and spaceop.opname == 'gc_reload_possibly_moved':
reload += 1
assert reload == 0