[Python-3000-checkins] r55301 - in python/branches/p3yk: Doc/lib/lib.tex Doc/lib/libbastion.tex Doc/lib/librestricted.tex Doc/lib/librexec.tex Doc/ref/ref3.tex Include/ceval.h Include/frameobject.h Lib/Bastion.py Lib/ihooks.py Lib/imputil.py Lib/inspect.py Lib/new.py Lib/pickle.py Lib/pickletools.py Lib/rexec.py Lib/test/test___all__.py Lib/test/test_bastion.py Lib/test/test_descr.py Lib/test/test_sundry.py Lib/types.py Misc/NEWS Modules/cPickle.c Objects/fileobject.c Objects/frameobject.c Objects/funcobject.c Objects/methodobject.c Python/ceval.c Python/marshal.c Python/structmember.c

brett.cannon python-3000-checkins at python.org
Mon May 14 02:38:12 CEST 2007


Author: brett.cannon
Date: Mon May 14 02:38:05 2007
New Revision: 55301

Removed:
   python/branches/p3yk/Doc/lib/libbastion.tex
   python/branches/p3yk/Doc/lib/librestricted.tex
   python/branches/p3yk/Doc/lib/librexec.tex
   python/branches/p3yk/Lib/Bastion.py
   python/branches/p3yk/Lib/rexec.py
   python/branches/p3yk/Lib/test/test_bastion.py
Modified:
   python/branches/p3yk/Doc/lib/lib.tex
   python/branches/p3yk/Doc/ref/ref3.tex
   python/branches/p3yk/Include/ceval.h
   python/branches/p3yk/Include/frameobject.h
   python/branches/p3yk/Lib/ihooks.py
   python/branches/p3yk/Lib/imputil.py
   python/branches/p3yk/Lib/inspect.py
   python/branches/p3yk/Lib/new.py
   python/branches/p3yk/Lib/pickle.py
   python/branches/p3yk/Lib/pickletools.py
   python/branches/p3yk/Lib/test/test___all__.py
   python/branches/p3yk/Lib/test/test_descr.py
   python/branches/p3yk/Lib/test/test_sundry.py
   python/branches/p3yk/Lib/types.py
   python/branches/p3yk/Misc/NEWS
   python/branches/p3yk/Modules/cPickle.c
   python/branches/p3yk/Objects/fileobject.c
   python/branches/p3yk/Objects/frameobject.c
   python/branches/p3yk/Objects/funcobject.c
   python/branches/p3yk/Objects/methodobject.c
   python/branches/p3yk/Python/ceval.c
   python/branches/p3yk/Python/marshal.c
   python/branches/p3yk/Python/structmember.c
Log:
Remove rexec and Bastion from the stdlib.  This also eliminates the need for
f_restricted on frames.  This in turn negates the need for
PyEval_GetRestricted() and PyFrame_IsRestricted().


Modified: python/branches/p3yk/Doc/lib/lib.tex
==============================================================================
--- python/branches/p3yk/Doc/lib/lib.tex	(original)
+++ python/branches/p3yk/Doc/lib/lib.tex	Mon May 14 02:38:05 2007
@@ -388,9 +388,6 @@
 \input{custominterp}		% Custom interpreter
 \input{libcode}
 \input{libcodeop}
-\input{librestricted}           % Restricted Execution
-\input{librexec}
-\input{libbastion}
 
 
 \input{modules}			% Importing Modules

Deleted: /python/branches/p3yk/Doc/lib/libbastion.tex
==============================================================================
--- /python/branches/p3yk/Doc/lib/libbastion.tex	Mon May 14 02:38:05 2007
+++ (empty file)
@@ -1,57 +0,0 @@
-\section{\module{Bastion} ---
-         Restricting access to objects}
-
-\declaremodule{standard}{Bastion}
-\modulesynopsis{Providing restricted access to objects.}
-\moduleauthor{Barry Warsaw}{bwarsaw at python.org}
-\versionchanged[Disabled module]{2.3}
-
-\begin{notice}[warning]
-  The documentation has been left in place to help in reading old code
-  that uses the module.
-\end{notice}
-
-% I'm concerned that the word 'bastion' won't be understood by people
-% for whom English is a second language, making the module name
-% somewhat mysterious.  Thus, the brief definition... --amk
-
-According to the dictionary, a bastion is ``a fortified area or
-position'', or ``something that is considered a stronghold.''  It's a
-suitable name for this module, which provides a way to forbid access
-to certain attributes of an object.  It must always be used with the
-\refmodule{rexec} module, in order to allow restricted-mode programs
-access to certain safe attributes of an object, while denying access
-to other, unsafe attributes.
-
-% I've punted on the issue of documenting keyword arguments for now.
-
-\begin{funcdesc}{Bastion}{object\optional{, filter\optional{,
-                          name\optional{, class}}}}
-Protect the object \var{object}, returning a bastion for the
-object.  Any attempt to access one of the object's attributes will
-have to be approved by the \var{filter} function; if the access is
-denied an \exception{AttributeError} exception will be raised.
-
-If present, \var{filter} must be a function that accepts a string
-containing an attribute name, and returns true if access to that
-attribute will be permitted; if \var{filter} returns false, the access
-is denied.  The default filter denies access to any function beginning
-with an underscore (\character{_}).  The bastion's string representation
-will be \samp{<Bastion for \var{name}>} if a value for
-\var{name} is provided; otherwise, \samp{repr(\var{object})} will be
-used.
-
-\var{class}, if present, should be a subclass of \class{BastionClass}; 
-see the code in \file{bastion.py} for the details.  Overriding the
-default \class{BastionClass} will rarely be required.
-\end{funcdesc}
-
-
-\begin{classdesc}{BastionClass}{getfunc, name}
-Class which actually implements bastion objects.  This is the default
-class used by \function{Bastion()}.  The \var{getfunc} parameter is a
-function which returns the value of an attribute which should be
-exposed to the restricted execution environment when called with the
-name of the attribute as the only parameter.  \var{name} is used to
-construct the \function{repr()} of the \class{BastionClass} instance.
-\end{classdesc}

Deleted: /python/branches/p3yk/Doc/lib/librestricted.tex
==============================================================================
--- /python/branches/p3yk/Doc/lib/librestricted.tex	Mon May 14 02:38:05 2007
+++ (empty file)
@@ -1,66 +0,0 @@
-\chapter{Restricted Execution \label{restricted}}
-
-\begin{notice}[warning]
-   In Python 2.3 these modules have been disabled due to various known
-   and not readily fixable security holes.  The modules are still
-   documented here to help in reading old code that uses the
-   \module{rexec} and \module{Bastion} modules.
-\end{notice}
-
-\emph{Restricted execution} is the basic framework in Python that allows
-for the segregation of trusted and untrusted code.  The framework is based on the
-notion that trusted Python code (a \emph{supervisor}) can create a
-``padded cell' (or environment) with limited permissions, and run the
-untrusted code within this cell.  The untrusted code cannot break out
-of its cell, and can only interact with sensitive system resources
-through interfaces defined and managed by the trusted code.  The term
-``restricted execution'' is favored over ``safe-Python''
-since true safety is hard to define, and is determined by the way the
-restricted environment is created.  Note that the restricted
-environments can be nested, with inner cells creating subcells of
-lesser, but never greater, privilege.
-
-An interesting aspect of Python's restricted execution model is that
-the interfaces presented to untrusted code usually have the same names
-as those presented to trusted code.  Therefore no special interfaces
-need to be learned to write code designed to run in a restricted
-environment.  And because the exact nature of the padded cell is
-determined by the supervisor, different restrictions can be imposed,
-depending on the application.  For example, it might be deemed
-``safe'' for untrusted code to read any file within a specified
-directory, but never to write a file.  In this case, the supervisor
-may redefine the built-in \function{open()} function so that it raises
-an exception whenever the \var{mode} parameter is \code{'w'}.  It
-might also perform a \cfunction{chroot()}-like operation on the
-\var{filename} parameter, such that root is always relative to some
-safe ``sandbox'' area of the filesystem.  In this case, the untrusted
-code would still see an built-in \function{open()} function in its
-environment, with the same calling interface.  The semantics would be
-identical too, with \exception{IOError}s being raised when the
-supervisor determined that an unallowable parameter is being used.
-
-The Python run-time determines whether a particular code block is
-executing in restricted execution mode based on the identity of the
-\code{__builtins__} object in its global variables: if this is (the
-dictionary of) the standard \refmodule[builtin]{__builtin__} module,
-the code is deemed to be unrestricted, else it is deemed to be
-restricted.
-
-Python code executing in restricted mode faces a number of limitations
-that are designed to prevent it from escaping from the padded cell.
-For instance, the function object attribute \member{func_globals} and
-the class and instance object attribute \member{__dict__} are
-unavailable.
-
-Two modules provide the framework for setting up restricted execution
-environments:
-
-\localmoduletable
-
-\begin{seealso}
-  \seetitle[http://grail.sourceforge.net/]{Grail Home Page}
-           {Grail, an Internet browser written in Python, uses these
-            modules to support Python applets.  More
-            information on the use of Python's restricted execution
-            mode in Grail is available on the Web site.}
-\end{seealso}

Deleted: /python/branches/p3yk/Doc/lib/librexec.tex
==============================================================================
--- /python/branches/p3yk/Doc/lib/librexec.tex	Mon May 14 02:38:05 2007
+++ (empty file)
@@ -1,275 +0,0 @@
-\section{\module{rexec} ---
-         Restricted execution framework}
-
-\declaremodule{standard}{rexec}
-\modulesynopsis{Basic restricted execution framework.}
-\versionchanged[Disabled module]{2.3}
-
-\begin{notice}[warning]
-  The documentation has been left in place to help in reading old code
-  that uses the module.
-\end{notice}
-
-This module contains the \class{RExec} class, which supports
-\method{r_exec()}, \method{r_eval()}, \method{r_execfile()}, and
-\method{r_import()} methods, which are restricted versions of the standard
-Python functions \method{exec()}, \method{eval()}, \method{execfile()} and
-the \keyword{import} statement.
-Code executed in this restricted environment will
-only have access to modules and functions that are deemed safe; you
-can subclass \class{RExec} to add or remove capabilities as desired.
-
-\begin{notice}[warning]
-  While the \module{rexec} module is designed to perform as described
-  below, it does have a few known vulnerabilities which could be
-  exploited by carefully written code.  Thus it should not be relied
-  upon in situations requiring ``production ready'' security.  In such
-  situations, execution via sub-processes or very careful
-  ``cleansing'' of both code and data to be processed may be
-  necessary.  Alternatively, help in patching known \module{rexec}
-  vulnerabilities would be welcomed.
-\end{notice}
-
-\begin{notice}
-  The \class{RExec} class can prevent code from performing unsafe
-  operations like reading or writing disk files, or using TCP/IP
-  sockets.  However, it does not protect against code using extremely
-  large amounts of memory or processor time.
-\end{notice}
-
-\begin{classdesc}{RExec}{\optional{hooks\optional{, verbose}}}
-Returns an instance of the \class{RExec} class.  
-
-\var{hooks} is an instance of the \class{RHooks} class or a subclass of it.
-If it is omitted or \code{None}, the default \class{RHooks} class is
-instantiated.
-Whenever the \module{rexec} module searches for a module (even a
-built-in one) or reads a module's code, it doesn't actually go out to
-the file system itself.  Rather, it calls methods of an \class{RHooks}
-instance that was passed to or created by its constructor.  (Actually,
-the \class{RExec} object doesn't make these calls --- they are made by
-a module loader object that's part of the \class{RExec} object.  This
-allows another level of flexibility, which can be useful when changing
-the mechanics of \keyword{import} within the restricted environment.)
-
-By providing an alternate \class{RHooks} object, we can control the
-file system accesses made to import a module, without changing the
-actual algorithm that controls the order in which those accesses are
-made.  For instance, we could substitute an \class{RHooks} object that
-passes all filesystem requests to a file server elsewhere, via some
-RPC mechanism such as ILU.  Grail's applet loader uses this to support
-importing applets from a URL for a directory.
-
-If \var{verbose} is true, additional debugging output may be sent to
-standard output.
-\end{classdesc}
-
-It is important to be aware that code running in a restricted
-environment can still call the \function{sys.exit()} function.  To
-disallow restricted code from exiting the interpreter, always protect
-calls that cause restricted code to run with a
-\keyword{try}/\keyword{except} statement that catches the
-\exception{SystemExit} exception.  Removing the \function{sys.exit()}
-function from the restricted environment is not sufficient --- the
-restricted code could still use \code{raise SystemExit}.  Removing
-\exception{SystemExit} is not a reasonable option; some library code
-makes use of this and would break were it not available.
-
-
-\begin{seealso}
-  \seetitle[http://grail.sourceforge.net/]{Grail Home Page}{Grail is a
-            Web browser written entirely in Python.  It uses the
-            \module{rexec} module as a foundation for supporting
-            Python applets, and can be used as an example usage of
-            this module.}
-\end{seealso}
-
-
-\subsection{RExec Objects \label{rexec-objects}}
-
-\class{RExec} instances support the following methods:
-
-\begin{methoddesc}[RExec]{r_eval}{code}
-\var{code} must either be a string containing a Python expression, or
-a compiled code object, which will be evaluated in the restricted
-environment's \module{__main__} module.  The value of the expression or
-code object will be returned.
-\end{methoddesc}
-
-\begin{methoddesc}[RExec]{r_exec}{code}
-\var{code} must either be a string containing one or more lines of
-Python code, or a compiled code object, which will be executed in the
-restricted environment's \module{__main__} module.
-\end{methoddesc}
-
-\begin{methoddesc}[RExec]{r_execfile}{filename}
-Execute the Python code contained in the file \var{filename} in the
-restricted environment's \module{__main__} module.
-\end{methoddesc}
-
-Methods whose names begin with \samp{s_} are similar to the functions
-beginning with \samp{r_}, but the code will be granted access to
-restricted versions of the standard I/O streams \code{sys.stdin},
-\code{sys.stderr}, and \code{sys.stdout}.
-
-\begin{methoddesc}[RExec]{s_eval}{code}
-\var{code} must be a string containing a Python expression, which will
-be evaluated in the restricted environment.  
-\end{methoddesc}
-
-\begin{methoddesc}[RExec]{s_exec}{code}
-\var{code} must be a string containing one or more lines of Python code,
-which will be executed in the restricted environment.  
-\end{methoddesc}
-
-\begin{methoddesc}[RExec]{s_execfile}{code}
-Execute the Python code contained in the file \var{filename} in the
-restricted environment.
-\end{methoddesc}
-
-\class{RExec} objects must also support various methods which will be
-implicitly called by code executing in the restricted environment.
-Overriding these methods in a subclass is used to change the policies
-enforced by a restricted environment.
-
-\begin{methoddesc}[RExec]{r_import}{modulename\optional{, globals\optional{,
-                                    locals\optional{, fromlist}}}}
-Import the module \var{modulename}, raising an \exception{ImportError}
-exception if the module is considered unsafe.
-\end{methoddesc}
-
-\begin{methoddesc}[RExec]{r_open}{filename\optional{, mode\optional{, bufsize}}}
-Method called when \function{open()} is called in the restricted
-environment.  The arguments are identical to those of \function{open()},
-and a file object (or a class instance compatible with file objects)
-should be returned.  \class{RExec}'s default behaviour is allow opening
-any file for reading, but forbidding any attempt to write a file.  See
-the example below for an implementation of a less restrictive
-\method{r_open()}.
-\end{methoddesc}
-
-\begin{methoddesc}[RExec]{r_reload}{module}
-Reload the module object \var{module}, re-parsing and re-initializing it.  
-\end{methoddesc}
-
-\begin{methoddesc}[RExec]{r_unload}{module}
-Unload the module object \var{module} (remove it from the
-restricted environment's \code{sys.modules} dictionary).
-\end{methoddesc}
-
-And their equivalents with access to restricted standard I/O streams:
-
-\begin{methoddesc}[RExec]{s_import}{modulename\optional{, globals\optional{,
-                                    locals\optional{, fromlist}}}}
-Import the module \var{modulename}, raising an \exception{ImportError}
-exception if the module is considered unsafe.
-\end{methoddesc}
-
-\begin{methoddesc}[RExec]{s_reload}{module}
-Reload the module object \var{module}, re-parsing and re-initializing it.  
-\end{methoddesc}
-
-\begin{methoddesc}[RExec]{s_unload}{module}
-Unload the module object \var{module}.   
-% XXX what are the semantics of this?  
-\end{methoddesc}
-
-
-\subsection{Defining restricted environments \label{rexec-extension}}
-
-The \class{RExec} class has the following class attributes, which are
-used by the \method{__init__()} method.  Changing them on an existing
-instance won't have any effect; instead, create a subclass of
-\class{RExec} and assign them new values in the class definition.
-Instances of the new class will then use those new values.  All these
-attributes are tuples of strings.
-
-\begin{memberdesc}[RExec]{nok_builtin_names}
-Contains the names of built-in functions which will \emph{not} be
-available to programs running in the restricted environment.  The
-value for \class{RExec} is \code{('open', 'reload', '__import__')}.
-(This gives the exceptions, because by far the majority of built-in
-functions are harmless.  A subclass that wants to override this
-variable should probably start with the value from the base class and
-concatenate additional forbidden functions --- when new dangerous
-built-in functions are added to Python, they will also be added to
-this module.)
-\end{memberdesc}
-
-\begin{memberdesc}[RExec]{ok_builtin_modules}
-Contains the names of built-in modules which can be safely imported.
-The value for \class{RExec} is \code{('audioop', 'array', 'binascii',
-'cmath', 'errno', 'imageop', 'marshal', 'math', 'md5', 'operator',
-'parser', 'regex', 'select', 'sha', '_sre', 'strop',
-'struct', 'time')}.  A similar remark about overriding this variable
-applies --- use the value from the base class as a starting point.
-\end{memberdesc}
-
-\begin{memberdesc}[RExec]{ok_path}
-Contains the directories which will be searched when an \keyword{import}
-is performed in the restricted environment.  
-The value for \class{RExec} is the same as \code{sys.path} (at the time
-the module is loaded) for unrestricted code.
-\end{memberdesc}
-
-\begin{memberdesc}[RExec]{ok_posix_names}
-% Should this be called ok_os_names?
-Contains the names of the functions in the \refmodule{os} module which will be
-available to programs running in the restricted environment.  The
-value for \class{RExec} is \code{('error', 'fstat', 'listdir',
-'lstat', 'readlink', 'stat', 'times', 'uname', 'getpid', 'getppid',
-'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid')}.
-\end{memberdesc}
-
-\begin{memberdesc}[RExec]{ok_sys_names}
-Contains the names of the functions and variables in the \refmodule{sys}
-module which will be available to programs running in the restricted
-environment.  The value for \class{RExec} is \code{('ps1', 'ps2',
-'copyright', 'version', 'platform', 'exit', 'maxint')}.
-\end{memberdesc}
-
-\begin{memberdesc}[RExec]{ok_file_types}
-Contains the file types from which modules are allowed to be loaded.
-Each file type is an integer constant defined in the \refmodule{imp} module.
-The meaningful values are \constant{PY_SOURCE}, \constant{PY_COMPILED}, and
-\constant{C_EXTENSION}.  The value for \class{RExec} is \code{(C_EXTENSION,
-PY_SOURCE)}.  Adding \constant{PY_COMPILED} in subclasses is not recommended;
-an attacker could exit the restricted execution mode by putting a forged
-byte-compiled file (\file{.pyc}) anywhere in your file system, for example
-by writing it to \file{/tmp} or uploading it to the \file{/incoming}
-directory of your public FTP server.
-\end{memberdesc}
-
-
-\subsection{An example}
-
-Let us say that we want a slightly more relaxed policy than the
-standard \class{RExec} class.  For example, if we're willing to allow
-files in \file{/tmp} to be written, we can subclass the \class{RExec}
-class:
-
-\begin{verbatim}
-class TmpWriterRExec(rexec.RExec):
-    def r_open(self, file, mode='r', buf=-1):
-        if mode in ('r', 'rb'):
-            pass
-        elif mode in ('w', 'wb', 'a', 'ab'):
-            # check filename : must begin with /tmp/
-            if file[:5]!='/tmp/': 
-                raise IOError, "can't write outside /tmp"
-            elif (string.find(file, '/../') >= 0 or
-                 file[:3] == '../' or file[-3:] == '/..'):
-                raise IOError, "'..' in filename forbidden"
-        else: raise IOError, "Illegal open() mode"
-        return open(file, mode, buf)
-\end{verbatim}
-%
-Notice that the above code will occasionally forbid a perfectly valid
-filename; for example, code in the restricted environment won't be
-able to open a file called \file{/tmp/foo/../bar}.  To fix this, the
-\method{r_open()} method would have to simplify the filename to
-\file{/tmp/bar}, which would require splitting apart the filename and
-performing various operations on it.  In cases where security is at
-stake, it may be preferable to write simple code which is sometimes
-overly restrictive, instead of more general code that is also more
-complex and may harbor a subtle security hole.

Modified: python/branches/p3yk/Doc/ref/ref3.tex
==============================================================================
--- python/branches/p3yk/Doc/ref/ref3.tex	(original)
+++ python/branches/p3yk/Doc/ref/ref3.tex	Mon May 14 02:38:05 2007
@@ -941,10 +941,8 @@
 frame; \member{f_locals} is the dictionary used to look up local
 variables; \member{f_globals} is used for global variables;
 \member{f_builtins} is used for built-in (intrinsic) names;
-\member{f_restricted} is a flag indicating whether the function is
-executing in restricted execution mode; \member{f_lasti} gives the
-precise instruction (this is an index into the bytecode string of
-the code object).
+ \member{f_lasti} gives the precise instruction (this is an index into
+ the bytecode string of the code object).
 \withsubitem{(frame attribute)}{
   \ttindex{f_back}
   \ttindex{f_code}
@@ -952,7 +950,6 @@
   \ttindex{f_locals}
   \ttindex{f_lasti}
   \ttindex{f_builtins}
-  \ttindex{f_restricted}}
 
 Special writable attributes: \member{f_trace}, if not \code{None}, is
 a function called at the start of each source code line (this is used

Modified: python/branches/p3yk/Include/ceval.h
==============================================================================
--- python/branches/p3yk/Include/ceval.h	(original)
+++ python/branches/p3yk/Include/ceval.h	Mon May 14 02:38:05 2007
@@ -33,7 +33,6 @@
 PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void);
 PyAPI_FUNC(PyObject *) PyEval_GetLocals(void);
 PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void);
-PyAPI_FUNC(int) PyEval_GetRestricted(void);
 
 /* Look at the current frame's (if any) code's co_flags, and turn on
    the corresponding compiler flags in cf->cf_flags.  Return 1 if any

Modified: python/branches/p3yk/Include/frameobject.h
==============================================================================
--- python/branches/p3yk/Include/frameobject.h	(original)
+++ python/branches/p3yk/Include/frameobject.h	Mon May 14 02:38:05 2007
@@ -52,8 +52,6 @@
 PyAPI_DATA(PyTypeObject) PyFrame_Type;
 
 #define PyFrame_Check(op) ((op)->ob_type == &PyFrame_Type)
-#define PyFrame_IsRestricted(f) \
-	((f)->f_builtins != (f)->f_tstate->interp->builtins)
 
 PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *,
                                        PyObject *, PyObject *);

Deleted: /python/branches/p3yk/Lib/Bastion.py
==============================================================================
--- /python/branches/p3yk/Lib/Bastion.py	Mon May 14 02:38:05 2007
+++ (empty file)
@@ -1,177 +0,0 @@
-"""Bastionification utility.
-
-A bastion (for another object -- the 'original') is an object that has
-the same methods as the original but does not give access to its
-instance variables.  Bastions have a number of uses, but the most
-obvious one is to provide code executing in restricted mode with a
-safe interface to an object implemented in unrestricted mode.
-
-The bastionification routine has an optional second argument which is
-a filter function.  Only those methods for which the filter method
-(called with the method name as argument) returns true are accessible.
-The default filter method returns true unless the method name begins
-with an underscore.
-
-There are a number of possible implementations of bastions.  We use a
-'lazy' approach where the bastion's __getattr__() discipline does all
-the work for a particular method the first time it is used.  This is
-usually fastest, especially if the user doesn't call all available
-methods.  The retrieved methods are stored as instance variables of
-the bastion, so the overhead is only occurred on the first use of each
-method.
-
-Detail: the bastion class has a __repr__() discipline which includes
-the repr() of the original object.  This is precomputed when the
-bastion is created.
-
-"""
-
-__all__ = ["BastionClass", "Bastion"]
-
-from types import MethodType
-
-
-class BastionClass:
-
-    """Helper class used by the Bastion() function.
-
-    You could subclass this and pass the subclass as the bastionclass
-    argument to the Bastion() function, as long as the constructor has
-    the same signature (a get() function and a name for the object).
-
-    """
-
-    def __init__(self, get, name):
-        """Constructor.
-
-        Arguments:
-
-        get - a function that gets the attribute value (by name)
-        name - a human-readable name for the original object
-               (suggestion: use repr(object))
-
-        """
-        self._get_ = get
-        self._name_ = name
-
-    def __repr__(self):
-        """Return a representation string.
-
-        This includes the name passed in to the constructor, so that
-        if you print the bastion during debugging, at least you have
-        some idea of what it is.
-
-        """
-        return "<Bastion for %s>" % self._name_
-
-    def __getattr__(self, name):
-        """Get an as-yet undefined attribute value.
-
-        This calls the get() function that was passed to the
-        constructor.  The result is stored as an instance variable so
-        that the next time the same attribute is requested,
-        __getattr__() won't be invoked.
-
-        If the get() function raises an exception, this is simply
-        passed on -- exceptions are not cached.
-
-        """
-        attribute = self._get_(name)
-        self.__dict__[name] = attribute
-        return attribute
-
-
-def Bastion(object, filter = lambda name: name[:1] != '_',
-            name=None, bastionclass=BastionClass):
-    """Create a bastion for an object, using an optional filter.
-
-    See the Bastion module's documentation for background.
-
-    Arguments:
-
-    object - the original object
-    filter - a predicate that decides whether a function name is OK;
-             by default all names are OK that don't start with '_'
-    name - the name of the object; default repr(object)
-    bastionclass - class used to create the bastion; default BastionClass
-
-    """
-
-    raise RuntimeError, "This code is not secure in Python 2.2 and later"
-
-    # Note: we define *two* ad-hoc functions here, get1 and get2.
-    # Both are intended to be called in the same way: get(name).
-    # It is clear that the real work (getting the attribute
-    # from the object and calling the filter) is done in get1.
-    # Why can't we pass get1 to the bastion?  Because the user
-    # would be able to override the filter argument!  With get2,
-    # overriding the default argument is no security loophole:
-    # all it does is call it.
-    # Also notice that we can't place the object and filter as
-    # instance variables on the bastion object itself, since
-    # the user has full access to all instance variables!
-
-    def get1(name, object=object, filter=filter):
-        """Internal function for Bastion().  See source comments."""
-        if filter(name):
-            attribute = getattr(object, name)
-            if type(attribute) == MethodType:
-                return attribute
-        raise AttributeError, name
-
-    def get2(name, get1=get1):
-        """Internal function for Bastion().  See source comments."""
-        return get1(name)
-
-    if name is None:
-        name = repr(object)
-    return bastionclass(get2, name)
-
-
-def _test():
-    """Test the Bastion() function."""
-    class Original:
-        def __init__(self):
-            self.sum = 0
-        def add(self, n):
-            self._add(n)
-        def _add(self, n):
-            self.sum = self.sum + n
-        def total(self):
-            return self.sum
-    o = Original()
-    b = Bastion(o)
-    testcode = """if 1:
-    b.add(81)
-    b.add(18)
-    print "b.total() =", b.total()
-    try:
-        print "b.sum =", b.sum,
-    except:
-        print "inaccessible"
-    else:
-        print "accessible"
-    try:
-        print "b._add =", b._add,
-    except:
-        print "inaccessible"
-    else:
-        print "accessible"
-    try:
-        print "b._get_.__defaults__ =", map(type, b._get_.__defaults__),
-    except:
-        print "inaccessible"
-    else:
-        print "accessible"
-    \n"""
-    exec(testcode)
-    print('='*20, "Using rexec:", '='*20)
-    import rexec
-    r = rexec.RExec()
-    m = r.add_module('__main__')
-    m.b = b
-    r.r_exec(testcode)
-
-
-if __name__ == '__main__':
-    _test()

Modified: python/branches/p3yk/Lib/ihooks.py
==============================================================================
--- python/branches/p3yk/Lib/ihooks.py	(original)
+++ python/branches/p3yk/Lib/ihooks.py	Mon May 14 02:38:05 2007
@@ -8,7 +8,7 @@
 the built-in function __import__ in order to change the semantics of
 the import statement, until now it has been difficult to combine the
 effect of different __import__ hacks, like loading modules from URLs
-by rimport.py, or restricted execution by rexec.py.
+by rimport.py.
 
 This module defines three new concepts:
 

Modified: python/branches/p3yk/Lib/imputil.py
==============================================================================
--- python/branches/p3yk/Lib/imputil.py	(original)
+++ python/branches/p3yk/Lib/imputil.py	Mon May 14 02:38:05 2007
@@ -674,7 +674,6 @@
 #   push MAL's mapper into sys.path[0] as a cache (hard-coded for apps)
 #
 # from Guido:
-#   need to change sys.* references for rexec environs
 #   need hook for MAL's walk-me-up import strategy, or Tim's absolute strategy
 #   watch out for sys.modules[...] is None
 #   flag to force absolute imports? (speeds _determine_import_context and
@@ -714,7 +713,7 @@
 # > However, we still have a tension occurring here:
 # >
 # > 1) implementing policy in ImportManager assists in single-point policy
-# >    changes for app/rexec situations
+# >    changes for app situations
 # > 2) implementing policy in Importer assists in package-private policy
 # >    changes for normal, operating conditions
 # >

Modified: python/branches/p3yk/Lib/inspect.py
==============================================================================
--- python/branches/p3yk/Lib/inspect.py	(original)
+++ python/branches/p3yk/Lib/inspect.py	Mon May 14 02:38:05 2007
@@ -161,7 +161,6 @@
         f_lasti         index of last attempted instruction in bytecode
         f_lineno        current line number in Python source code
         f_locals        local namespace seen by this frame
-        f_restricted    0 or 1 if frame is in restricted execution mode
         f_trace         tracing function for this frame, or None"""
     return isinstance(object, types.FrameType)
 
@@ -674,7 +673,7 @@
     """Get information about the arguments accepted by a code object.
 
     Three things are returned: (args, varargs, varkw), where
-    'args' is the list of argument names, possibly containing nested 
+    'args' is the list of argument names, possibly containing nested
     lists. Keyword-only arguments are appended. 'varargs' and 'varkw'
     are the names of the * and ** arguments or None."""
     args, varargs, kwonlyargs, varkw = _getfullargs(co)
@@ -751,7 +750,7 @@
     'args' will include keyword-only argument names.
     'varargs' and 'varkw' are the names of the * and ** arguments or None.
     'defaults' is an n-tuple of the default values of the last n arguments.
-        
+
     Use the getfullargspec() API for Python-3000 code, as annotations
     and keyword arguments are supported. getargspec() will raise ValueError
     if the func has either annotations or keyword arguments.
@@ -767,7 +766,7 @@
 def getfullargspec(func):
     """Get the names and default values of a function's arguments.
 
-    A tuple of seven things is returned: (args, varargs, kwonlyargs, 
+    A tuple of seven things is returned: (args, varargs, kwonlyargs,
     kwonlydefaults, varkw, defaults, annotations).
     'args' is a list of the argument names (it may contain nested lists).
     'varargs' and 'varkw' are the names of the * and ** arguments or None.
@@ -775,7 +774,7 @@
     'kwonlyargs' is a list of keyword-only argument names.
     'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults.
     'annotations' is a dictionary mapping argument names to annotations.
-    
+
     The first four items in the tuple correspond to getargspec().
     """
 
@@ -784,7 +783,7 @@
     if not isfunction(func):
         raise TypeError('arg is not a Python function')
     args, varargs, kwonlyargs, varkw = _getfullargs(func.__code__)
-    return (args, varargs, varkw, func.__defaults__, 
+    return (args, varargs, varkw, func.__defaults__,
             kwonlyargs, func.__kwdefaults__, func.__annotations__)
 
 def getargvalues(frame):
@@ -816,12 +815,12 @@
             return annotation.__name__
         return annotation.__module__+'.'+annotation.__name__
     return repr(annotation)
-    
+
 def formatannotationrelativeto(object):
-  module = getattr(object, '__module__', None)
-  def _formatannotation(annotation):
-      return formatannotation(annotation, module)
-  return _formatannotation
+    module = getattr(object, '__module__', None)
+    def _formatannotation(annotation):
+        return formatannotation(annotation, module)
+    return _formatannotation
 
 def formatargspec(args, varargs=None, varkw=None, defaults=None,
                   kwonlyargs=(), kwonlydefaults={}, annotations={},
@@ -832,7 +831,7 @@
                   formatreturns=lambda text: ' -> ' + text,
                   formatannotation=formatannotation,
                   join=joinseq):
-    """Format an argument spec from the values returned by getargspec 
+    """Format an argument spec from the values returned by getargspec
     or getfullargspec.
 
     The first seven arguments are (args, varargs, varkw, defaults,

Modified: python/branches/p3yk/Lib/new.py
==============================================================================
--- python/branches/p3yk/Lib/new.py	(original)
+++ python/branches/p3yk/Lib/new.py	Mon May 14 02:38:05 2007
@@ -8,9 +8,4 @@
 from types import FunctionType as function
 from types import MethodType as instancemethod
 from types import ModuleType as module
-
-# CodeType is not accessible in restricted execution mode
-try:
-    from types import CodeType as code
-except ImportError:
-    pass
+from types import CodeType as code

Modified: python/branches/p3yk/Lib/pickle.py
==============================================================================
--- python/branches/p3yk/Lib/pickle.py	(original)
+++ python/branches/p3yk/Lib/pickle.py	Mon May 14 02:38:05 2007
@@ -1026,14 +1026,9 @@
         if (not args and
                 type(klass) is ClassType and
                 not hasattr(klass, "__getinitargs__")):
-            try:
-                value = _EmptyClass()
-                value.__class__ = klass
-                instantiated = 1
-            except RuntimeError:
-                # In restricted execution, assignment to inst.__class__ is
-                # prohibited
-                pass
+            value = _EmptyClass()
+            value.__class__ = klass
+            instantiated = 1
         if not instantiated:
             try:
                 value = klass(*args)
@@ -1199,20 +1194,7 @@
         if isinstance(state, tuple) and len(state) == 2:
             state, slotstate = state
         if state:
-            try:
-                inst.__dict__.update(state)
-            except RuntimeError:
-                # XXX In restricted execution, the instance's __dict__
-                # is not accessible.  Use the old way of unpickling
-                # the instance variables.  This is a semantic
-                # difference when unpickling in restricted
-                # vs. unrestricted modes.
-                # Note, however, that cPickle has never tried to do the
-                # .update() business, and always uses
-                #     PyObject_SetItem(inst.__dict__, key, value) in a
-                # loop over state.items().
-                for k, v in state.items():
-                    setattr(inst, k, v)
+            inst.__dict__.update(state)
         if slotstate:
             for k, v in slotstate.items():
                 setattr(inst, k, v)

Modified: python/branches/p3yk/Lib/pickletools.py
==============================================================================
--- python/branches/p3yk/Lib/pickletools.py	(original)
+++ python/branches/p3yk/Lib/pickletools.py	Mon May 14 02:38:05 2007
@@ -1548,13 +1548,6 @@
       the object is updated via
 
           anyobject.__dict__.update(argument)
-
-      This may raise RuntimeError in restricted execution mode (which
-      disallows access to __dict__ directly); in that case, the object
-      is updated instead via
-
-          for k, v in argument.items():
-              anyobject[k] = v
       """),
 
     I(name='INST',
@@ -1590,11 +1583,7 @@
       calling __init__() is current wisdom).  In this case, an instance of
       an old-style dummy class is created, and then we try to rebind its
       __class__ attribute to the desired class object.  If this succeeds,
-      the new instance object is pushed on the stack, and we're done.  In
-      restricted execution mode it can fail (assignment to __class__ is
-      disallowed), and I'm not really sure what happens then -- it looks
-      like the code ends up calling the class object's __init__ anyway,
-      via falling into the next case.
+      the new instance object is pushed on the stack, and we're done.
 
       Else (the argtuple is not empty, it's not an old-style class object,
       or the class object does have a __getinitargs__ attribute), the code

Deleted: /python/branches/p3yk/Lib/rexec.py
==============================================================================
--- /python/branches/p3yk/Lib/rexec.py	Mon May 14 02:38:05 2007
+++ (empty file)
@@ -1,585 +0,0 @@
-"""Restricted execution facilities.
-
-The class RExec exports methods r_exec(), r_eval(), r_execfile(), and
-r_import(), which correspond roughly to the built-in operations
-exec, eval(), execfile() and import, but executing the code in an
-environment that only exposes those built-in operations that are
-deemed safe.  To this end, a modest collection of 'fake' modules is
-created which mimics the standard modules by the same names.  It is a
-policy decision which built-in modules and operations are made
-available; this module provides a reasonable default, but derived
-classes can change the policies e.g. by overriding or extending class
-variables like ok_builtin_modules or methods like make_sys().
-
-XXX To do:
-- r_open should allow writing tmp dir
-- r_exec etc. with explicit globals/locals? (Use rexec("exec ... in ...")?)
-
-"""
-
-
-import sys
-import __builtin__
-import os
-import ihooks
-import imp
-
-__all__ = ["RExec"]
-
-class FileBase:
-
-    ok_file_methods = ('fileno', 'flush', 'isatty', 'read', 'readline',
-            'readlines', 'seek', 'tell', 'write', 'writelines',
-            '__iter__')
-
-
-class FileWrapper(FileBase):
-
-    # XXX This is just like a Bastion -- should use that!
-
-    def __init__(self, f):
-        for m in self.ok_file_methods:
-            if not hasattr(self, m) and hasattr(f, m):
-                setattr(self, m, getattr(f, m))
-
-    def close(self):
-        self.flush()
-
-
-TEMPLATE = """
-def %s(self, *args):
-        return getattr(self.mod, self.name).%s(*args)
-"""
-
-class FileDelegate(FileBase):
-
-    def __init__(self, mod, name):
-        self.mod = mod
-        self.name = name
-
-    for m in FileBase.ok_file_methods + ('close',):
-        exec(TEMPLATE % (m, m))
-
-
-class RHooks(ihooks.Hooks):
-
-    def __init__(self, *args):
-        # Hacks to support both old and new interfaces:
-        # old interface was RHooks(rexec[, verbose])
-        # new interface is RHooks([verbose])
-        verbose = 0
-        rexec = None
-        if args and type(args[-1]) == type(0):
-            verbose = args[-1]
-            args = args[:-1]
-        if args and hasattr(args[0], '__class__'):
-            rexec = args[0]
-            args = args[1:]
-        if args:
-            raise TypeError, "too many arguments"
-        ihooks.Hooks.__init__(self, verbose)
-        self.rexec = rexec
-
-    def set_rexec(self, rexec):
-        # Called by RExec instance to complete initialization
-        self.rexec = rexec
-
-    def get_suffixes(self):
-        return self.rexec.get_suffixes()
-
-    def is_builtin(self, name):
-        return self.rexec.is_builtin(name)
-
-    def init_builtin(self, name):
-        m = __import__(name)
-        return self.rexec.copy_except(m, ())
-
-    def init_frozen(self, name): raise SystemError, "don't use this"
-    def load_source(self, *args): raise SystemError, "don't use this"
-    def load_compiled(self, *args): raise SystemError, "don't use this"
-    def load_package(self, *args): raise SystemError, "don't use this"
-
-    def load_dynamic(self, name, filename, file):
-        return self.rexec.load_dynamic(name, filename, file)
-
-    def add_module(self, name):
-        return self.rexec.add_module(name)
-
-    def modules_dict(self):
-        return self.rexec.modules
-
-    def default_path(self):
-        return self.rexec.modules['sys'].path
-
-
-# XXX Backwards compatibility
-RModuleLoader = ihooks.FancyModuleLoader
-RModuleImporter = ihooks.ModuleImporter
-
-
-class RExec(ihooks._Verbose):
-    """Basic restricted execution framework.
-
-    Code executed in this restricted environment will only have access to
-    modules and functions that are deemed safe; you can subclass RExec to
-    add or remove capabilities as desired.
-
-    The RExec class can prevent code from performing unsafe operations like
-    reading or writing disk files, or using TCP/IP sockets.  However, it does
-    not protect against code using extremely large amounts of memory or
-    processor time.
-
-    """
-
-    ok_path = tuple(sys.path)           # That's a policy decision
-
-    ok_builtin_modules = ('audioop', 'array', 'binascii',
-                          'cmath', 'errno', 'imageop',
-                          'marshal', 'math', 'md5', 'operator',
-                          'parser', 'select',
-                          'sha', '_sre', 'strop', 'struct', 'time',
-                          '_weakref')
-
-    ok_posix_names = ('error', 'fstat', 'listdir', 'lstat', 'readlink',
-                      'stat', 'times', 'uname', 'getpid', 'getppid',
-                      'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid')
-
-    ok_sys_names = ('byteorder', 'copyright', 'exit', 'getdefaultencoding',
-                    'getrefcount', 'hexversion', 'maxint', 'maxunicode',
-                    'platform', 'ps1', 'ps2', 'version', 'version_info')
-
-    nok_builtin_names = ('open', 'file', 'reload', '__import__')
-
-    ok_file_types = (imp.C_EXTENSION, imp.PY_SOURCE)
-
-    def __init__(self, hooks = None, verbose = 0):
-        """Returns an instance of the RExec class.
-
-        The hooks parameter is an instance of the RHooks class or a subclass
-        of it.  If it is omitted or None, the default RHooks class is
-        instantiated.
-
-        Whenever the RExec module searches for a module (even a built-in one)
-        or reads a module's code, it doesn't actually go out to the file
-        system itself.  Rather, it calls methods of an RHooks instance that
-        was passed to or created by its constructor.  (Actually, the RExec
-        object doesn't make these calls --- they are made by a module loader
-        object that's part of the RExec object.  This allows another level of
-        flexibility, which can be useful when changing the mechanics of
-        import within the restricted environment.)
-
-        By providing an alternate RHooks object, we can control the file
-        system accesses made to import a module, without changing the
-        actual algorithm that controls the order in which those accesses are
-        made.  For instance, we could substitute an RHooks object that
-        passes all filesystem requests to a file server elsewhere, via some
-        RPC mechanism such as ILU.  Grail's applet loader uses this to support
-        importing applets from a URL for a directory.
-
-        If the verbose parameter is true, additional debugging output may be
-        sent to standard output.
-
-        """
-
-        raise RuntimeError, "This code is not secure in Python 2.2 and later"
-
-        ihooks._Verbose.__init__(self, verbose)
-        # XXX There's a circular reference here:
-        self.hooks = hooks or RHooks(verbose)
-        self.hooks.set_rexec(self)
-        self.modules = {}
-        self.ok_dynamic_modules = self.ok_builtin_modules
-        list = []
-        for mname in self.ok_builtin_modules:
-            if mname in sys.builtin_module_names:
-                list.append(mname)
-        self.ok_builtin_modules = tuple(list)
-        self.set_trusted_path()
-        self.make_builtin()
-        self.make_initial_modules()
-        # make_sys must be last because it adds the already created
-        # modules to its builtin_module_names
-        self.make_sys()
-        self.loader = RModuleLoader(self.hooks, verbose)
-        self.importer = RModuleImporter(self.loader, verbose)
-
-    def set_trusted_path(self):
-        # Set the path from which dynamic modules may be loaded.
-        # Those dynamic modules must also occur in ok_builtin_modules
-        self.trusted_path = filter(os.path.isabs, sys.path)
-
-    def load_dynamic(self, name, filename, file):
-        if name not in self.ok_dynamic_modules:
-            raise ImportError, "untrusted dynamic module: %s" % name
-        if name in sys.modules:
-            src = sys.modules[name]
-        else:
-            src = imp.load_dynamic(name, filename, file)
-        dst = self.copy_except(src, [])
-        return dst
-
-    def make_initial_modules(self):
-        self.make_main()
-        self.make_osname()
-
-    # Helpers for RHooks
-
-    def get_suffixes(self):
-        return [item   # (suff, mode, type)
-                for item in imp.get_suffixes()
-                if item[2] in self.ok_file_types]
-
-    def is_builtin(self, mname):
-        return mname in self.ok_builtin_modules
-
-    # The make_* methods create specific built-in modules
-
-    def make_builtin(self):
-        m = self.copy_except(__builtin__, self.nok_builtin_names)
-        m.__import__ = self.r_import
-        m.reload = self.r_reload
-        m.open = m.file = self.r_open
-
-    def make_main(self):
-        m = self.add_module('__main__')
-
-    def make_osname(self):
-        osname = os.name
-        src = __import__(osname)
-        dst = self.copy_only(src, self.ok_posix_names)
-        dst.environ = e = {}
-        for key, value in os.environ.items():
-            e[key] = value
-
-    def make_sys(self):
-        m = self.copy_only(sys, self.ok_sys_names)
-        m.modules = self.modules
-        m.argv = ['RESTRICTED']
-        m.path = map(None, self.ok_path)
-        m.exc_info = self.r_exc_info
-        m = self.modules['sys']
-        l = self.modules.keys() + list(self.ok_builtin_modules)
-        l.sort()
-        m.builtin_module_names = tuple(l)
-
-    # The copy_* methods copy existing modules with some changes
-
-    def copy_except(self, src, exceptions):
-        dst = self.copy_none(src)
-        for name in dir(src):
-            setattr(dst, name, getattr(src, name))
-        for name in exceptions:
-            try:
-                delattr(dst, name)
-            except AttributeError:
-                pass
-        return dst
-
-    def copy_only(self, src, names):
-        dst = self.copy_none(src)
-        for name in names:
-            try:
-                value = getattr(src, name)
-            except AttributeError:
-                continue
-            setattr(dst, name, value)
-        return dst
-
-    def copy_none(self, src):
-        m = self.add_module(src.__name__)
-        m.__doc__ = src.__doc__
-        return m
-
-    # Add a module -- return an existing module or create one
-
-    def add_module(self, mname):
-        m = self.modules.get(mname)
-        if m is None:
-            self.modules[mname] = m = self.hooks.new_module(mname)
-        m.__builtins__ = self.modules['__builtin__']
-        return m
-
-    # The r* methods are public interfaces
-
-    def r_exec(self, code):
-        """Execute code within a restricted environment.
-
-        The code parameter must either be a string containing one or more
-        lines of Python code, or a compiled code object, which will be
-        executed in the restricted environment's __main__ module.
-
-        """
-        m = self.add_module('__main__')
-        exec(code, m.__dict__)
-
-    def r_eval(self, code):
-        """Evaluate code within a restricted environment.
-
-        The code parameter must either be a string containing a Python
-        expression, or a compiled code object, which will be evaluated in
-        the restricted environment's __main__ module.  The value of the
-        expression or code object will be returned.
-
-        """
-        m = self.add_module('__main__')
-        return eval(code, m.__dict__)
-
-    def r_execfile(self, file):
-        """Execute the Python code in the file in the restricted
-        environment's __main__ module.
-
-        """
-        m = self.add_module('__main__')
-        execfile(file, m.__dict__)
-
-    def r_import(self, mname, globals={}, locals={}, fromlist=[]):
-        """Import a module, raising an ImportError exception if the module
-        is considered unsafe.
-
-        This method is implicitly called by code executing in the
-        restricted environment.  Overriding this method in a subclass is
-        used to change the policies enforced by a restricted environment.
-
-        """
-        return self.importer.import_module(mname, globals, locals, fromlist)
-
-    def r_reload(self, m):
-        """Reload the module object, re-parsing and re-initializing it.
-
-        This method is implicitly called by code executing in the
-        restricted environment.  Overriding this method in a subclass is
-        used to change the policies enforced by a restricted environment.
-
-        """
-        return self.importer.reload(m)
-
-    def r_unload(self, m):
-        """Unload the module.
-
-        Removes it from the restricted environment's sys.modules dictionary.
-
-        This method is implicitly called by code executing in the
-        restricted environment.  Overriding this method in a subclass is
-        used to change the policies enforced by a restricted environment.
-
-        """
-        return self.importer.unload(m)
-
-    # The s_* methods are similar but also swap std{in,out,err}
-
-    def make_delegate_files(self):
-        s = self.modules['sys']
-        self.delegate_stdin = FileDelegate(s, 'stdin')
-        self.delegate_stdout = FileDelegate(s, 'stdout')
-        self.delegate_stderr = FileDelegate(s, 'stderr')
-        self.restricted_stdin = FileWrapper(sys.stdin)
-        self.restricted_stdout = FileWrapper(sys.stdout)
-        self.restricted_stderr = FileWrapper(sys.stderr)
-
-    def set_files(self):
-        if not hasattr(self, 'save_stdin'):
-            self.save_files()
-        if not hasattr(self, 'delegate_stdin'):
-            self.make_delegate_files()
-        s = self.modules['sys']
-        s.stdin = self.restricted_stdin
-        s.stdout = self.restricted_stdout
-        s.stderr = self.restricted_stderr
-        sys.stdin = self.delegate_stdin
-        sys.stdout = self.delegate_stdout
-        sys.stderr = self.delegate_stderr
-
-    def reset_files(self):
-        self.restore_files()
-        s = self.modules['sys']
-        self.restricted_stdin = s.stdin
-        self.restricted_stdout = s.stdout
-        self.restricted_stderr = s.stderr
-
-
-    def save_files(self):
-        self.save_stdin = sys.stdin
-        self.save_stdout = sys.stdout
-        self.save_stderr = sys.stderr
-
-    def restore_files(self):
-        sys.stdin = self.save_stdin
-        sys.stdout = self.save_stdout
-        sys.stderr = self.save_stderr
-
-    def s_apply(self, func, args=(), kw={}):
-        self.save_files()
-        try:
-            self.set_files()
-            r = func(*args, **kw)
-        finally:
-            self.restore_files()
-        return r
-
-    def s_exec(self, *args):
-        """Execute code within a restricted environment.
-
-        Similar to the r_exec() method, but the code will be granted access
-        to restricted versions of the standard I/O streams sys.stdin,
-        sys.stderr, and sys.stdout.
-
-        The code parameter must either be a string containing one or more
-        lines of Python code, or a compiled code object, which will be
-        executed in the restricted environment's __main__ module.
-
-        """
-        return self.s_apply(self.r_exec, args)
-
-    def s_eval(self, *args):
-        """Evaluate code within a restricted environment.
-
-        Similar to the r_eval() method, but the code will be granted access
-        to restricted versions of the standard I/O streams sys.stdin,
-        sys.stderr, and sys.stdout.
-
-        The code parameter must either be a string containing a Python
-        expression, or a compiled code object, which will be evaluated in
-        the restricted environment's __main__ module.  The value of the
-        expression or code object will be returned.
-
-        """
-        return self.s_apply(self.r_eval, args)
-
-    def s_execfile(self, *args):
-        """Execute the Python code in the file in the restricted
-        environment's __main__ module.
-
-        Similar to the r_execfile() method, but the code will be granted
-        access to restricted versions of the standard I/O streams sys.stdin,
-        sys.stderr, and sys.stdout.
-
-        """
-        return self.s_apply(self.r_execfile, args)
-
-    def s_import(self, *args):
-        """Import a module, raising an ImportError exception if the module
-        is considered unsafe.
-
-        This method is implicitly called by code executing in the
-        restricted environment.  Overriding this method in a subclass is
-        used to change the policies enforced by a restricted environment.
-
-        Similar to the r_import() method, but has access to restricted
-        versions of the standard I/O streams sys.stdin, sys.stderr, and
-        sys.stdout.
-
-        """
-        return self.s_apply(self.r_import, args)
-
-    def s_reload(self, *args):
-        """Reload the module object, re-parsing and re-initializing it.
-
-        This method is implicitly called by code executing in the
-        restricted environment.  Overriding this method in a subclass is
-        used to change the policies enforced by a restricted environment.
-
-        Similar to the r_reload() method, but has access to restricted
-        versions of the standard I/O streams sys.stdin, sys.stderr, and
-        sys.stdout.
-
-        """
-        return self.s_apply(self.r_reload, args)
-
-    def s_unload(self, *args):
-        """Unload the module.
-
-        Removes it from the restricted environment's sys.modules dictionary.
-
-        This method is implicitly called by code executing in the
-        restricted environment.  Overriding this method in a subclass is
-        used to change the policies enforced by a restricted environment.
-
-        Similar to the r_unload() method, but has access to restricted
-        versions of the standard I/O streams sys.stdin, sys.stderr, and
-        sys.stdout.
-
-        """
-        return self.s_apply(self.r_unload, args)
-
-    # Restricted open(...)
-
-    def r_open(self, file, mode='r', buf=-1):
-        """Method called when open() is called in the restricted environment.
-
-        The arguments are identical to those of the open() function, and a
-        file object (or a class instance compatible with file objects)
-        should be returned.  RExec's default behaviour is allow opening
-        any file for reading, but forbidding any attempt to write a file.
-
-        This method is implicitly called by code executing in the
-        restricted environment.  Overriding this method in a subclass is
-        used to change the policies enforced by a restricted environment.
-
-        """
-        mode = str(mode)
-        if mode not in ('r', 'rb'):
-            raise IOError, "can't open files for writing in restricted mode"
-        return open(file, mode, buf)
-
-    # Restricted version of sys.exc_info()
-
-    def r_exc_info(self):
-        ty, va, tr = sys.exc_info()
-        tr = None
-        return ty, va, tr
-
-
-def test():
-    import getopt, traceback
-    opts, args = getopt.getopt(sys.argv[1:], 'vt:')
-    verbose = 0
-    trusted = []
-    for o, a in opts:
-        if o == '-v':
-            verbose = verbose+1
-        if o == '-t':
-            trusted.append(a)
-    r = RExec(verbose=verbose)
-    if trusted:
-        r.ok_builtin_modules = r.ok_builtin_modules + tuple(trusted)
-    if args:
-        r.modules['sys'].argv = args
-        r.modules['sys'].path.insert(0, os.path.dirname(args[0]))
-    else:
-        r.modules['sys'].path.insert(0, "")
-    fp = sys.stdin
-    if args and args[0] != '-':
-        try:
-            fp = open(args[0])
-        except IOError as msg:
-            print("%s: can't open file %r" % (sys.argv[0], args[0]))
-            return 1
-    if fp.isatty():
-        try:
-            import readline
-        except ImportError:
-            pass
-        import code
-        class RestrictedConsole(code.InteractiveConsole):
-            def runcode(self, co):
-                self.locals['__builtins__'] = r.modules['__builtin__']
-                r.s_apply(code.InteractiveConsole.runcode, (self, co))
-        try:
-            RestrictedConsole(r.modules['__main__'].__dict__).interact()
-        except SystemExit as n:
-            return n
-    else:
-        text = fp.read()
-        fp.close()
-        c = compile(text, fp.name, 'exec')
-        try:
-            r.s_exec(c)
-        except SystemExit as n:
-            return n
-        except:
-            traceback.print_exc()
-            return 1
-
-
-if __name__ == '__main__':
-    sys.exit(test())

Modified: python/branches/p3yk/Lib/test/test___all__.py
==============================================================================
--- python/branches/p3yk/Lib/test/test___all__.py	(original)
+++ python/branches/p3yk/Lib/test/test___all__.py	Mon May 14 02:38:05 2007
@@ -35,7 +35,6 @@
             import _socket
 
         self.check_all("BaseHTTPServer")
-        self.check_all("Bastion")
         self.check_all("CGIHTTPServer")
         self.check_all("ConfigParser")
         self.check_all("Cookie")
@@ -124,7 +123,6 @@
         self.check_all("random")
         self.check_all("re")
         self.check_all("repr")
-        self.check_all("rexec")
         self.check_all("rfc822")
         self.check_all("rlcompleter")
         self.check_all("robotparser")

Deleted: /python/branches/p3yk/Lib/test/test_bastion.py
==============================================================================
--- /python/branches/p3yk/Lib/test/test_bastion.py	Mon May 14 02:38:05 2007
+++ (empty file)
@@ -1,3 +0,0 @@
-##import Bastion
-##
-##Bastion._test()

Modified: python/branches/p3yk/Lib/test/test_descr.py
==============================================================================
--- python/branches/p3yk/Lib/test/test_descr.py	(original)
+++ python/branches/p3yk/Lib/test/test_descr.py	Mon May 14 02:38:05 2007
@@ -2452,49 +2452,6 @@
             raise TestFailed("expected TypeError from bogus keyword "
                              "argument to %r" % constructor)
 
-def restricted():
-    # XXX This test is disabled because rexec is not deemed safe
-    return
-    import rexec
-    if verbose:
-        print("Testing interaction with restricted execution ...")
-
-    sandbox = rexec.RExec()
-
-    code1 = """f = open(%r, 'w')""" % TESTFN
-    code2 = """f = open(%r, 'w')""" % TESTFN
-    code3 = """\
-f = open(%r)
-t = type(f)  # a sneaky way to get the file() constructor
-f.close()
-f = t(%r, 'w')  # rexec can't catch this by itself
-""" % (TESTFN, TESTFN)
-
-    f = open(TESTFN, 'w')  # Create the file so code3 can find it.
-    f.close()
-
-    try:
-        for code in code1, code2, code3:
-            try:
-                sandbox.r_exec(code)
-            except IOError as msg:
-                if str(msg).find("restricted") >= 0:
-                    outcome = "OK"
-                else:
-                    outcome = "got an exception, but not an expected one"
-            else:
-                outcome = "expected a restricted-execution exception"
-
-            if outcome != "OK":
-                raise TestFailed("%s, in %r" % (outcome, code))
-
-    finally:
-        try:
-            import os
-            os.unlink(TESTFN)
-        except:
-            pass
-
 def str_subclass_as_dict_key():
     if verbose:
         print("Testing a str subclass used as dict key ..")
@@ -4173,7 +4130,6 @@
     supers()
     inherits()
     keywords()
-    restricted()
     str_subclass_as_dict_key()
     classic_comparisons()
     rich_comparisons()

Modified: python/branches/p3yk/Lib/test/test_sundry.py
==============================================================================
--- python/branches/p3yk/Lib/test/test_sundry.py	(original)
+++ python/branches/p3yk/Lib/test/test_sundry.py	Mon May 14 02:38:05 2007
@@ -49,7 +49,6 @@
 import pstats
 import py_compile
 import pydoc
-import rexec
 import rlcompleter
 import sched
 import smtplib

Modified: python/branches/p3yk/Lib/types.py
==============================================================================
--- python/branches/p3yk/Lib/types.py	(original)
+++ python/branches/p3yk/Lib/types.py	Mon May 14 02:38:05 2007
@@ -42,11 +42,7 @@
 def _f(): pass
 FunctionType = type(_f)
 LambdaType = type(lambda: None)         # Same as FunctionType
-try:
-    CodeType = type(_f.__code__)
-except RuntimeError:
-    # Execution in restricted environment
-    pass
+CodeType = type(_f.__code__)
 
 def _g():
     yield 1
@@ -67,14 +63,9 @@
 try:
     raise TypeError
 except TypeError:
-    try:
-        tb = sys.exc_info()[2]
-        TracebackType = type(tb)
-        FrameType = type(tb.tb_frame)
-    except AttributeError:
-        # In the restricted environment, exc_info returns (None, None,
-        # None) Then, tb.tb_frame gives an attribute error
-        pass
+    tb = sys.exc_info()[2]
+    TracebackType = type(tb)
+    FrameType = type(tb.tb_frame)
     tb = None; del tb
 
 SliceType = slice

Modified: python/branches/p3yk/Misc/NEWS
==============================================================================
--- python/branches/p3yk/Misc/NEWS	(original)
+++ python/branches/p3yk/Misc/NEWS	Mon May 14 02:38:05 2007
@@ -26,6 +26,9 @@
 Core and Builtins
 -----------------
 
+- Remove the f_restricted attribute from frames.  This naturally leads to teh
+  removal of PyEval_GetRestricted() and PyFrame_IsRestricted().
+
 - PEP 3132 was accepted. That means that you can do ``a, *b = range(5)``
   to assign 0 to a and [1, 2, 3, 4] to b.
 
@@ -175,6 +178,9 @@
 Library
 -------
 
+- Remove Bastion and rexec as they have been disabled since Python 2.3 (this
+  also leads to the C API support for restricted execution).
+
 - Remove obsolete IRIX modules: al, cd, cl, fl, fm, gl, imgfile, sgi, sv.
 
 - Remove bsddb185 module it was obsolete.

Modified: python/branches/p3yk/Modules/cPickle.c
==============================================================================
--- python/branches/p3yk/Modules/cPickle.c	(original)
+++ python/branches/p3yk/Modules/cPickle.c	Mon May 14 02:38:05 2007
@@ -2711,21 +2711,8 @@
 		}
 	}
 
-	if (PyEval_GetRestricted()) {
-		/* Restricted execution, get private tables */
-		PyObject *m = PyImport_Import(copy_reg_str);
-
-		if (m == NULL)
-			goto err;
-		self->dispatch_table = PyObject_GetAttr(m, dispatch_table_str);
-		Py_DECREF(m);
-		if (self->dispatch_table == NULL)
-			goto err;
-	}
-	else {
-		self->dispatch_table = dispatch_table;
-		Py_INCREF(dispatch_table);
-	}
+	self->dispatch_table = dispatch_table;
+	Py_INCREF(dispatch_table);
 	PyObject_GC_Track(self);
 
 	return self;

Modified: python/branches/p3yk/Objects/fileobject.c
==============================================================================
--- python/branches/p3yk/Objects/fileobject.c	(original)
+++ python/branches/p3yk/Objects/fileobject.c	Mon May 14 02:38:05 2007
@@ -207,15 +207,6 @@
 		goto cleanup;
 	}
 
-	/* rexec.py can't stop a user from getting the file() constructor --
-	   all they have to do is get *any* file object f, and then do
-	   type(f).  Here we prevent them from doing damage with it. */
-	if (PyEval_GetRestricted()) {
-		PyErr_SetString(PyExc_IOError,
-		"file() constructor not accessible in restricted mode");
-		f = NULL;
-		goto cleanup;
-	}
 	errno = 0;
 
 #ifdef MS_WINDOWS

Modified: python/branches/p3yk/Objects/frameobject.c
==============================================================================
--- python/branches/p3yk/Objects/frameobject.c	(original)
+++ python/branches/p3yk/Objects/frameobject.c	Mon May 14 02:38:05 2007
@@ -340,18 +340,12 @@
 	return 0;
 }
 
-static PyObject *
-frame_getrestricted(PyFrameObject *f, void *closure)
-{
-	return PyBool_FromLong(PyFrame_IsRestricted(f));
-}
 
 static PyGetSetDef frame_getsetlist[] = {
 	{"f_locals",	(getter)frame_getlocals, NULL, NULL},
 	{"f_lineno",	(getter)frame_getlineno,
 			(setter)frame_setlineno, NULL},
 	{"f_trace",	(getter)frame_gettrace, (setter)frame_settrace, NULL},
-	{"f_restricted",(getter)frame_getrestricted,NULL, NULL},
 	{0}
 };
 

Modified: python/branches/p3yk/Objects/funcobject.c
==============================================================================
--- python/branches/p3yk/Objects/funcobject.c	(original)
+++ python/branches/p3yk/Objects/funcobject.c	Mon May 14 02:38:05 2007
@@ -234,21 +234,9 @@
         {NULL}  /* Sentinel */
 };
 
-static int
-restricted(void)
-{
-	if (!PyEval_GetRestricted())
-		return 0;
-	PyErr_SetString(PyExc_RuntimeError,
-		"function attributes not accessible in restricted mode");
-	return 1;
-}
-
 static PyObject *
 func_get_dict(PyFunctionObject *op)
 {
-	if (restricted())
-		return NULL;
 	if (op->func_dict == NULL) {
 		op->func_dict = PyDict_New();
 		if (op->func_dict == NULL)
@@ -263,8 +251,6 @@
 {
 	PyObject *tmp;
 
-	if (restricted())
-		return -1;
 	/* It is illegal to del f.func_dict */
 	if (value == NULL) {
 		PyErr_SetString(PyExc_TypeError,
@@ -287,8 +273,6 @@
 static PyObject *
 func_get_code(PyFunctionObject *op)
 {
-	if (restricted())
-		return NULL;
 	Py_INCREF(op->func_code);
 	return op->func_code;
 }
@@ -299,8 +283,6 @@
 	PyObject *tmp;
 	Py_ssize_t nfree, nclosure;
 
-	if (restricted())
-		return -1;
 	/* Not legal to del f.func_code or to set it to anything
 	 * other than a code object. */
 	if (value == NULL || !PyCode_Check(value)) {
@@ -338,8 +320,6 @@
 {
 	PyObject *tmp;
 
-	if (restricted())
-		return -1;
 	/* Not legal to del f.func_name or to set it to anything
 	 * other than a string object. */
 	if (value == NULL || !PyString_Check(value)) {
@@ -357,8 +337,6 @@
 static PyObject *
 func_get_defaults(PyFunctionObject *op)
 {
-	if (restricted())
-		return NULL;
 	if (op->func_defaults == NULL) {
 		Py_INCREF(Py_None);
 		return Py_None;
@@ -372,8 +350,6 @@
 {
 	PyObject *tmp;
 
-	if (restricted())
-		return -1;
 	/* Legal to del f.func_defaults.
 	 * Can only set func_defaults to NULL or a tuple. */
 	if (value == Py_None)
@@ -393,8 +369,6 @@
 static PyObject *
 func_get_kwdefaults(PyFunctionObject *op)
 {
-	if (restricted())
-		return NULL;
 	if (op->func_kwdefaults == NULL) {
 		Py_INCREF(Py_None);
 		return Py_None;
@@ -407,9 +381,6 @@
 func_set_kwdefaults(PyFunctionObject *op, PyObject *value)
 {
 	PyObject *tmp;
-    
-	if (restricted())
-		return -1;
 
 	if (value == Py_None)
 		value = NULL;

Modified: python/branches/p3yk/Objects/methodobject.c
==============================================================================
--- python/branches/p3yk/Objects/methodobject.c	(original)
+++ python/branches/p3yk/Objects/methodobject.c	Mon May 14 02:38:05 2007
@@ -158,11 +158,7 @@
 meth_get__self__(PyCFunctionObject *m, void *closure)
 {
 	PyObject *self;
-	if (PyEval_GetRestricted()) {
-		PyErr_SetString(PyExc_RuntimeError,
-			"method.__self__ not accessible in restricted mode");
-		return NULL;
-	}
+
 	self = m->m_self;
 	if (self == NULL)
 		self = Py_None;

Modified: python/branches/p3yk/Python/ceval.c
==============================================================================
--- python/branches/p3yk/Python/ceval.c	(original)
+++ python/branches/p3yk/Python/ceval.c	Mon May 14 02:38:05 2007
@@ -3367,13 +3367,6 @@
 }
 
 int
-PyEval_GetRestricted(void)
-{
-	PyFrameObject *current_frame = PyEval_GetFrame();
-	return current_frame == NULL ? 0 : PyFrame_IsRestricted(current_frame);
-}
-
-int
 PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
 {
 	PyFrameObject *current_frame = PyEval_GetFrame();

Modified: python/branches/p3yk/Python/marshal.c
==============================================================================
--- python/branches/p3yk/Python/marshal.c	(original)
+++ python/branches/p3yk/Python/marshal.c	Mon May 14 02:38:05 2007
@@ -802,13 +802,7 @@
 		return v3;
 
 	case TYPE_CODE:
-		if (PyEval_GetRestricted()) {
-			PyErr_SetString(PyExc_RuntimeError,
-				"cannot unmarshal code objects in "
-				"restricted execution mode");
-			return NULL;
-		}
-		else {
+		{
 			int argcount;
 			int kwonlyargcount;
 			int nlocals;
@@ -827,7 +821,7 @@
 			
 			v = NULL;
 
-                        /* XXX ignore long->int overflows for now */
+			/* XXX ignore long->int overflows for now */
 			argcount = (int)r_long(p);
 			kwonlyargcount = (int)r_long(p);
 			nlocals = (int)r_long(p);
@@ -880,8 +874,8 @@
 			Py_XDECREF(name);
 			Py_XDECREF(lnotab);
 
+			return v;
 		}
-		return v;
 
 	default:
 		/* Bogus data got written, which isn't ideal.

Modified: python/branches/p3yk/Python/structmember.c
==============================================================================
--- python/branches/p3yk/Python/structmember.c	(original)
+++ python/branches/p3yk/Python/structmember.c	Mon May 14 02:38:05 2007
@@ -54,11 +54,7 @@
 PyMember_GetOne(const char *addr, PyMemberDef *l)
 {
 	PyObject *v;
-	if ((l->flags & READ_RESTRICTED) &&
-	    PyEval_GetRestricted()) {
-		PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
-		return NULL;
-	}
+
 	addr += l->offset;
 	switch (l->type) {
 	case T_BYTE:
@@ -167,10 +163,6 @@
 		PyErr_SetString(PyExc_AttributeError, "readonly attribute");
 		return -1;
 	}
-	if ((l->flags & WRITE_RESTRICTED) && PyEval_GetRestricted()) {
-		PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
-		return -1;
-	}
 	if (v == NULL && l->type != T_OBJECT_EX && l->type != T_OBJECT) {
 		PyErr_SetString(PyExc_TypeError,
 				"can't delete numeric/char attribute");


More information about the Python-3000-checkins mailing list