[Python-checkins] r51912 - in python/branches/bcannon-objcap: Lib/test/test_interpreter.py Modules/interpretermodule.c securing_python.txt
brett.cannon
python-checkins at python.org
Mon Sep 18 23:27:52 CEST 2006
Author: brett.cannon
Date: Mon Sep 18 23:27:51 2006
New Revision: 51912
Modified:
python/branches/bcannon-objcap/Lib/test/test_interpreter.py
python/branches/bcannon-objcap/Modules/interpretermodule.c
python/branches/bcannon-objcap/securing_python.txt
Log:
Rework interface for getting the built-ins namespace dict. Since it is cached
the instant you create an interpreter by the initial execution frame, make it
so that you need a function call to return the dict. That way people realize
they cannot reassign the dict but it can be mutated.
Need to verify that the sys_dict and modules dicts don't have the same issue.
Modified: python/branches/bcannon-objcap/Lib/test/test_interpreter.py
==============================================================================
--- python/branches/bcannon-objcap/Lib/test/test_interpreter.py (original)
+++ python/branches/bcannon-objcap/Lib/test/test_interpreter.py Mon Sep 18 23:27:51 2006
@@ -1,12 +1,3 @@
-"""XXX Use case tests:
- * cannot open files
- - test removal of open() as well as change to bz2.
- * block imports
- - built-ins
- - .pyc/.pyo
- - extension modules
-
-"""
import interpreter
import unittest
@@ -28,6 +19,12 @@
to_return.append(False)
"""
+test_builtins_contains = """
+import __builtin__
+_return.append(__builtin__.__dict__.__contains__("%s"))
+"""
+
+
class BaseInterpTests(unittest.TestCase):
def setUp(self):
@@ -49,52 +46,45 @@
class BuiltinsTests(BaseInterpTests):
- """Test interpreter.Interpreter().builtins ."""
+ """Test interpreter.Interpreter().builtins() ."""
def test_get(self):
# Test the getting of 'builtins'.
- builtins = self.interp.builtins
+ builtins = self.interp.builtins()
self.failUnless(isinstance(builtins, dict))
self.failUnless('object' in builtins)
- def test_set(self):
- # Make sure setting 'builtins' can be done and has proper type
- # checking.
- self.interp.builtins = {}
- self.failUnlessRaises(TypeError, setattr, self.interp, 'builtins', [])
-
def test_remove(self):
# Make sure that something can be removed from built-ins.
- # XXX
- pass
+ builtins = self.interp.builtins()
+ del builtins['open']
+ _return = []
+ builtins['_return'] = _return
+ self.interp.execute(test_builtins_contains % 'open')
+ self.failUnless(not _return[-1])
def test_add_remove(self):
# Make sure you can add to the built-ins and then remove the same
# object.
- self.interp.builtins['test'] = 'test'
- self.interp.execute('test')
- del self.interp.builtins['test']
- # XXX self.failUnlessRaises(XXX, interp.execute, 'test')
-
-
- def test_empty_builtins(self):
- # Make sure that emptying the built-ins truly make them non-existent.
- self.interp.builtins = {}
- # XXX self.failUnlessRaises(XXX, interp.execute, 'object')
-
+ self.interp.builtins()['test'] = 'test'
+ _return = []
+ self.interp.builtins()['_return'] = _return
+ self.interp.execute(test_builtins_contains % 'test')
+ self.failUnless(_return[-1])
+ del self.interp.builtins()['test']
+ self.interp.execute(test_builtins_contains % 'test')
+ self.failUnless(not _return[-1])
+
def test_copied(self):
# Make sure built-ins are unique per interpreter.
- self.failUnless(self.interp.builtins is not __builtin__.__dict__)
-
- try:
- __builtin__.__dict__['test1'] = 'test1'
- self.failUnless('test1' not in self.interp.builtins)
- finally:
- del __builtin__.__dict__['test1']
- self.interp.builtins['test2'] = 'test2'
- self.failUnless('test2' not in __builtin__.__dict__)
-
-
+ master_id = id(__builtin__.__dict__)
+ _return = []
+ self.interp.builtins()['_return'] = _return
+ self.interp.execute('import __builtin__;'
+ '_return.append(id(__builtin__.__dict__))')
+ self.failUnless(_return[-1] != master_id)
+
+
class ModulesTests(BaseInterpTests):
"""Test interpreter.Interpreter().modules ."""
@@ -153,7 +143,7 @@
sys_dict = self.interp.sys_dict
sys_dict['version'] = 'test'
interp_return = []
- self.interp.builtins['to_return'] = interp_return
+ self.interp.builtins()['to_return'] = interp_return
self.interp.execute(test_sys_changed)
self.failUnless(interp_return[0])
@@ -183,7 +173,7 @@
def test_file_restrictions(self):
# You cannot open a file.
- del self.interp.builtins['open']
+ del self.interp.builtins()['open']
try:
self.interp.execute("open(%s, 'w')" % test_support.TESTFN)
finally:
Modified: python/branches/bcannon-objcap/Modules/interpretermodule.c
==============================================================================
--- python/branches/bcannon-objcap/Modules/interpretermodule.c (original)
+++ python/branches/bcannon-objcap/Modules/interpretermodule.c Mon Sep 18 23:27:51 2006
@@ -99,45 +99,29 @@
Py_RETURN_NONE;
}
-static PyMethodDef interpreter_methods[] = {
- {"execute", interpreter_exec, METH_O,
- "Execute the passed-in string in the interpreter"},
- {NULL}
-};
-
-
/*
- Getter for 'builtins'.
-*/
+ Getter for 'builtins'.
+
+ There is not setter because the creation of a new interpreter automatically
+ creates the initial execution frame which caches the built-in namespace.
+ */
static PyObject *
-interpreter_get_builtins(PyObject *self, void *optional)
+interpreter_builtins(PyObject *self)
{
- PyObject *builtins = PyInterpreter_GET_INTERP(self)->builtins;
-
- Py_INCREF(builtins);
- return builtins;
+ PyObject *builtins = PyInterpreter_GET_INTERP(self)->builtins;
+
+ Py_INCREF(builtins);
+ return builtins;
}
-/*
- Setter for 'builtins'.
-*/
-static int
-interpreter_set_builtins(PyObject *self, PyObject *arg, void *optional)
-{
- PyObject *old_builtins = PyInterpreter_GET_INTERP(self)->builtins;
-
- if (!PyDict_CheckExact(arg)) {
- PyErr_SetString(PyExc_TypeError,
- "'builtins' must be set to a dict");
- return -1;
- }
-
- Py_INCREF(arg);
- Py_DECREF(old_builtins);
- PyInterpreter_GET_INTERP(self)->builtins = arg;
+static PyMethodDef interpreter_methods[] = {
+ {"builtins", (PyCFunction)interpreter_builtins, METH_NOARGS,
+ "Return the built-in namespace dict"},
+ {"execute", interpreter_exec, METH_O,
+ "Execute the passed-in string in the interpreter"},
+ {NULL}
+};
- return 0;
-}
/*
Getter for 'modules'.
@@ -207,8 +191,6 @@
static PyGetSetDef interpreter_getset[] = {
- {"builtins", interpreter_get_builtins, interpreter_set_builtins,
- "The built-ins dict for the interpreter.", NULL},
{"sys_dict", interpreter_get_sys_dict, interpreter_set_sys_dict,
"The modules dict for 'sys'.", NULL},
{"modules", interpreter_get_modules, interpreter_set_modules,
Modified: python/branches/bcannon-objcap/securing_python.txt
==============================================================================
--- python/branches/bcannon-objcap/securing_python.txt (original)
+++ python/branches/bcannon-objcap/securing_python.txt Mon Sep 18 23:27:51 2006
@@ -43,11 +43,7 @@
interrupt_main() not per-interpreter, and stack_size() can be
dangerous)
+ Create sandboxed interpreter stdlib module <critical>
- - Be able to specify built-ins
- * XXX frames cache built-ins, so setting to a new dict does
- not get propagated; need to either change ability to assign
- to built-ins or add functions that allow to set and delete
- keys individually.
+ - Be able to specify built-ins [done]
- Set 'sys' module settings
- Set 'sys.modules'
- API
More information about the Python-checkins
mailing list