Commit 718fb741 authored by Evan Simpson's avatar Evan Simpson

Fix RestrictedPython.compiler stacksize computations, which could cause...

Fix RestrictedPython.compiler stacksize computations, which could cause segmentation faults when incorrect.  Incremented PythonScripts magic number to force recompilation of Scripts.
parent a44a6e19
......@@ -17,7 +17,7 @@ This product provides support for Script objects containing restricted
Python code.
"""
__version__='$Revision: 1.37 $'[11:-2]
__version__='$Revision: 1.38 $'[11:-2]
import sys, os, traceback, re, marshal
from Globals import DTMLFile, MessageDialog, package_home
......@@ -41,7 +41,7 @@ Python_magic = imp.get_magic()
del imp
# This should only be incremented to force recompilation.
Script_magic = 2
Script_magic = 3
manage_addPythonScriptForm = DTMLFile('www/pyScriptAdd', globals())
_default_file = os.path.join(package_home(globals()),
......
"""A flow graph representation for Python bytecode"""
from __future__ import nested_scopes
import dis
import new
import string
......@@ -372,6 +373,7 @@ class PyFlowGraph(FlowGraph):
def getCode(self):
"""Get a Python code object"""
if self.stage == RAW:
self.computeStackDepth()
self.flattenGraph()
if self.stage == FLAT:
self.convertArgs()
......@@ -399,6 +401,36 @@ class PyFlowGraph(FlowGraph):
if io:
sys.stdout = save
def computeStackDepth(self):
"""Compute the max stack depth.
Approach is to compute the stack effect of each basic block.
Then find the path through the code with the largest total
effect.
"""
depth = {}
exit = None
for b in self.getBlocks():
depth[b] = findDepth(b.getInstructions())
seen = {}
def max_depth(b, d):
if seen.has_key(b):
return d
seen[b] = 1
d = d + depth[b]
children = b.get_children()
if children:
return max([max_depth(c, d) for c in children])
else:
if not b.label == "exit":
return max_depth(self.exit, d)
else:
return d
self.stacksize = max_depth(self.entry, 0)
def flattenGraph(self):
"""Arrange the blocks in order and resolve jumps"""
assert self.stage == RAW
......@@ -685,16 +717,10 @@ class StackDepthTracker:
maxDepth = 0
for i in insts:
opname = i[0]
delta = self.effect.get(opname, 0)
if delta > 1:
depth = depth + delta
elif delta < 0:
if depth > maxDepth:
maxDepth = depth
delta = self.effect.get(opname)
if delta is not None:
depth = depth + delta
else:
if depth > maxDepth:
maxDepth = depth
# now check patterns
for pat, pat_delta in self.patterns:
if opname[:len(pat)] == pat:
......@@ -702,12 +728,14 @@ class StackDepthTracker:
depth = depth + delta
break
# if we still haven't found a match
if delta == 0:
if delta is None:
meth = getattr(self, opname, None)
if meth is not None:
depth = depth + meth(i[1])
if depth < 0:
depth = 0
if depth > maxDepth:
maxDepth = depth
return maxDepth
effect = {
......@@ -742,6 +770,11 @@ class StackDepthTracker:
'IMPORT_STAR': -1,
'IMPORT_NAME': 0,
'IMPORT_FROM': 1,
'LOAD_ATTR': 0, # unlike other loads
# close enough...
'SETUP_EXCEPT': 3,
'SETUP_FINALLY': 3,
'FOR_ITER': 1,
}
# use pattern match
patterns = [
......@@ -753,20 +786,20 @@ class StackDepthTracker:
# UNPACK_SEQUENCE, BUILD_TUPLE,
# BUILD_LIST, CALL_FUNCTION, MAKE_FUNCTION, BUILD_SLICE
def UNPACK_SEQUENCE(self, count):
return count
return count-1
def BUILD_TUPLE(self, count):
return -count
return 1-count
def BUILD_LIST(self, count):
return -count
return 1-count
def CALL_FUNCTION(self, argc):
hi, lo = divmod(argc, 256)
return lo + hi * 2
return -(lo + hi * 2)
def CALL_FUNCTION_VAR(self, argc):
return self.CALL_FUNCTION(argc)+1
return self.CALL_FUNCTION(argc)-1
def CALL_FUNCTION_KW(self, argc):
return self.CALL_FUNCTION(argc)+1
return self.CALL_FUNCTION(argc)-1
def CALL_FUNCTION_VAR_KW(self, argc):
return self.CALL_FUNCTION(argc)+2
return self.CALL_FUNCTION(argc)-2
def MAKE_FUNCTION(self, argc):
return -argc
def BUILD_SLICE(self, argc):
......@@ -774,5 +807,7 @@ class StackDepthTracker:
return -1
elif argc == 3:
return -2
def DUP_TOPX(self, argc):
return argc
findDepth = StackDepthTracker().findDepth
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment