mirror of https://github.com/python/cpython
Now that file objects are subclassable, you can get at the file constructor
just by doing type(f) where f is any file object. This left a hole in restricted execution mode that rexec.py can't plug by itself (although it can plug part of it; the rest is plugged in fileobject.c now).
This commit is contained in:
parent
561f899d19
commit
8fa45677c1
|
@ -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__')
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue