summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/rexec.py4
-rw-r--r--Lib/test/test_descr.py42
-rw-r--r--Objects/fileobject.c8
3 files changed, 52 insertions, 2 deletions
diff --git a/Lib/rexec.py b/Lib/rexec.py
index d1dd4eb..cece544 100644
--- a/Lib/rexec.py
+++ b/Lib/rexec.py
@@ -132,7 +132,7 @@ class RExec(ihooks._Verbose):
ok_sys_names = ('ps1', 'ps2', 'copyright', 'version',
'platform', 'exit', 'maxint')
- nok_builtin_names = ('open', 'reload', '__import__')
+ nok_builtin_names = ('open', 'file', 'reload', '__import__')
def __init__(self, hooks = None, verbose = 0):
ihooks._Verbose.__init__(self, verbose)
@@ -186,7 +186,7 @@ class RExec(ihooks._Verbose):
m = self.copy_except(__builtin__, self.nok_builtin_names)
m.__import__ = self.r_import
m.reload = self.r_reload
- m.open = self.r_open
+ m.open = m.file = self.r_open
def make_main(self):
m = self.add_module('__main__')
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 02ef0ef..f1af5b9 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1717,6 +1717,47 @@ def keywords():
raise TestFailed("expected TypeError from bogus keyword "
"argument to %r" % constructor)
+def restricted():
+ import rexec
+ if verbose:
+ print "Testing interaction with restricted execution ..."
+
+ sandbox = rexec.RExec()
+
+ code1 = """f = open(%r, 'w')""" % TESTFN
+ code2 = """f = file(%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, 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 all():
lists()
dicts()
@@ -1752,6 +1793,7 @@ def all():
supers()
inherits()
keywords()
+ restricted()
all()
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index 3cadff5..b373024 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -92,6 +92,14 @@ open_the_file(PyFileObject *f, char *name, char *mode)
assert(name != NULL);
assert(mode != NULL);
+ /* 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");
+ return NULL;
+ }
#ifdef HAVE_FOPENRF
if (*mode == '*') {
FILE *fopenRF();