mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
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
3 changed files with 52 additions and 2 deletions
|
@ -132,7 +132,7 @@ class RExec(ihooks._Verbose):
|
||||||
ok_sys_names = ('ps1', 'ps2', 'copyright', 'version',
|
ok_sys_names = ('ps1', 'ps2', 'copyright', 'version',
|
||||||
'platform', 'exit', 'maxint')
|
'platform', 'exit', 'maxint')
|
||||||
|
|
||||||
nok_builtin_names = ('open', 'reload', '__import__')
|
nok_builtin_names = ('open', 'file', 'reload', '__import__')
|
||||||
|
|
||||||
def __init__(self, hooks = None, verbose = 0):
|
def __init__(self, hooks = None, verbose = 0):
|
||||||
ihooks._Verbose.__init__(self, verbose)
|
ihooks._Verbose.__init__(self, verbose)
|
||||||
|
@ -186,7 +186,7 @@ class RExec(ihooks._Verbose):
|
||||||
m = self.copy_except(__builtin__, self.nok_builtin_names)
|
m = self.copy_except(__builtin__, self.nok_builtin_names)
|
||||||
m.__import__ = self.r_import
|
m.__import__ = self.r_import
|
||||||
m.reload = self.r_reload
|
m.reload = self.r_reload
|
||||||
m.open = self.r_open
|
m.open = m.file = self.r_open
|
||||||
|
|
||||||
def make_main(self):
|
def make_main(self):
|
||||||
m = self.add_module('__main__')
|
m = self.add_module('__main__')
|
||||||
|
|
|
@ -1717,6 +1717,47 @@ def keywords():
|
||||||
raise TestFailed("expected TypeError from bogus keyword "
|
raise TestFailed("expected TypeError from bogus keyword "
|
||||||
"argument to %r" % constructor)
|
"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():
|
def all():
|
||||||
lists()
|
lists()
|
||||||
dicts()
|
dicts()
|
||||||
|
@ -1752,6 +1793,7 @@ def all():
|
||||||
supers()
|
supers()
|
||||||
inherits()
|
inherits()
|
||||||
keywords()
|
keywords()
|
||||||
|
restricted()
|
||||||
|
|
||||||
all()
|
all()
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,14 @@ open_the_file(PyFileObject *f, char *name, char *mode)
|
||||||
assert(name != NULL);
|
assert(name != NULL);
|
||||||
assert(mode != 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
|
#ifdef HAVE_FOPENRF
|
||||||
if (*mode == '*') {
|
if (*mode == '*') {
|
||||||
FILE *fopenRF();
|
FILE *fopenRF();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue