[Python-checkins] r50730 - in python/branches/bcannon-sandboxing: Include/Python.h Include/objimpl.h Include/pyerrors.h Include/pymem.h Include/pystate.h Include/sandbox.h Lib/test/exception_hierarchy.txt Makefile.pre.in Modules/sandboxmodule.c Objects/exceptions.c Objects/object.c Python/pystate.c Python/pythonrun.c Python/sandbox.c configure configure.in pyconfig.h.in setup.py

brett.cannon python-checkins at python.org
Thu Jul 20 21:42:41 CEST 2006


Author: brett.cannon
Date: Thu Jul 20 21:42:38 2006
New Revision: 50730

Removed:
   python/branches/bcannon-sandboxing/Include/sandbox.h
   python/branches/bcannon-sandboxing/Modules/sandboxmodule.c
   python/branches/bcannon-sandboxing/Python/sandbox.c
Modified:
   python/branches/bcannon-sandboxing/Include/Python.h
   python/branches/bcannon-sandboxing/Include/objimpl.h
   python/branches/bcannon-sandboxing/Include/pyerrors.h
   python/branches/bcannon-sandboxing/Include/pymem.h
   python/branches/bcannon-sandboxing/Include/pystate.h
   python/branches/bcannon-sandboxing/Lib/test/exception_hierarchy.txt
   python/branches/bcannon-sandboxing/Makefile.pre.in
   python/branches/bcannon-sandboxing/Objects/exceptions.c
   python/branches/bcannon-sandboxing/Objects/object.c
   python/branches/bcannon-sandboxing/Python/pystate.c
   python/branches/bcannon-sandboxing/Python/pythonrun.c
   python/branches/bcannon-sandboxing/configure
   python/branches/bcannon-sandboxing/configure.in
   python/branches/bcannon-sandboxing/pyconfig.h.in
   python/branches/bcannon-sandboxing/setup.py
Log:
Initial stab at introducing a special build for capping memory usage in an
interpreter.  Build with Py_MEMORY_CAP defined (can be done with
--with-memory-cap) to activate features.

Have not tested actual memory cap usage; have only built, did not set a
memory cap, and then ran the testing suite (which all passes).  Still need to
figure out how to cap the memory usage.  Maybe put something in sys or gc?

Also still need to go through and change places that use a bare malloc()/free()
instead of PyMem_Malloc()/PyMem_Free().  Also catch places that inline
PyObject_New() and call PyObject_Malloc() directly.


Modified: python/branches/bcannon-sandboxing/Include/Python.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/Python.h	(original)
+++ python/branches/bcannon-sandboxing/Include/Python.h	Thu Jul 20 21:42:38 2006
@@ -114,7 +114,6 @@
 #include "pyerrors.h"
 
 #include "pystate.h"
-#include "sandbox.h"
 
 #include "pyarena.h"
 #include "modsupport.h"

Modified: python/branches/bcannon-sandboxing/Include/objimpl.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/objimpl.h	(original)
+++ python/branches/bcannon-sandboxing/Include/objimpl.h	Thu Jul 20 21:42:38 2006
@@ -128,11 +128,15 @@
 
 #endif	/* WITH_PYMALLOC */
 
+#ifndef Py_MEMORY_CAP
 #define PyObject_Del		PyObject_Free
-#define PyObject_DEL		PyObject_FREE
-
 /* for source compatibility with 2.2 */
 #define _PyObject_Del		PyObject_Free
+#else /* Py_MEMORY_CAP */
+PyAPI_FUNC(void) _PyObject_Del(void *);
+#define PyObject_Del            _PyObject_Del
+#endif /* !Py_MEMORY_CAP */
+#define PyObject_DEL		PyObject_FREE
 
 /*
  * Generic object allocator interface

Modified: python/branches/bcannon-sandboxing/Include/pyerrors.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/pyerrors.h	(original)
+++ python/branches/bcannon-sandboxing/Include/pyerrors.h	Thu Jul 20 21:42:38 2006
@@ -140,7 +140,6 @@
 PyAPI_DATA(PyObject *) PyExc_NameError;
 PyAPI_DATA(PyObject *) PyExc_OverflowError;
 PyAPI_DATA(PyObject *) PyExc_RuntimeError;
-PyAPI_DATA(PyObject *) PyExc_SandboxError;
 PyAPI_DATA(PyObject *) PyExc_NotImplementedError;
 PyAPI_DATA(PyObject *) PyExc_SyntaxError;
 PyAPI_DATA(PyObject *) PyExc_IndentationError;

Modified: python/branches/bcannon-sandboxing/Include/pymem.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/pymem.h	(original)
+++ python/branches/bcannon-sandboxing/Include/pymem.h	Thu Jul 20 21:42:38 2006
@@ -55,12 +55,18 @@
    no longer supported. They used to call PyErr_NoMemory() on failure. */
 
 /* Macros. */
-#ifdef PYMALLOC_DEBUG
+#if defined (PYMALLOC_DEBUG)
 /* Redirect all memory operations to Python's debugging allocator. */
 #define PyMem_MALLOC		PyObject_MALLOC
 #define PyMem_REALLOC		PyObject_REALLOC
 #define PyMem_FREE		PyObject_FREE
 
+#elif defined (Py_MEMORY_CAP)
+/* Redirect all memory allocations through memory tracking functions. */
+#define PyMem_MALLOC		PyMem_Malloc
+#define PyMem_REALLOC		PyMem_Realloc
+#define PyMem_FREE		PyMem_Free
+
 #else	/* ! PYMALLOC_DEBUG */
 
 /* PyMem_MALLOC(0) means malloc(1). Some systems would return NULL

Modified: python/branches/bcannon-sandboxing/Include/pystate.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/pystate.h	(original)
+++ python/branches/bcannon-sandboxing/Include/pystate.h	Thu Jul 20 21:42:38 2006
@@ -32,8 +32,9 @@
 #ifdef WITH_TSC
     int tscdump;
 #endif
-#ifdef PySandbox_SUPPORTED
-    PySandboxState *sandbox_state;
+#ifdef Py_MEMORY_CAP
+    size_t mem_cap;
+    size_t mem_usage;
 #endif
 
 } PyInterpreterState;
@@ -106,6 +107,13 @@
 PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *);
 PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *);
 
+#ifdef Py_MEMORY_CAP
+#define PyInterpreterState_SET_MEMORY_CAP(interp, cap) (interp->mem_cap = cap)
+PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_SafeGet(void);
+PyAPI_FUNC(int) PyInterpreterState_RaiseMemoryUsage(PyInterpreterState *, size_t);
+PyAPI_FUNC(void) PyInterpreterState_LowerMemoryUsage(PyInterpreterState *, size_t);
+#endif /* Py_MEMORY_CAP */
+
 PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *);
 PyAPI_FUNC(void) PyThreadState_Clear(PyThreadState *);
 PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *);

Deleted: /python/branches/bcannon-sandboxing/Include/sandbox.h
==============================================================================
--- /python/branches/bcannon-sandboxing/Include/sandbox.h	Thu Jul 20 21:42:38 2006
+++ (empty file)
@@ -1,56 +0,0 @@
-#ifdef PySandbox_SUPPORTED
-
-#ifndef Py_SANDBOX_H
-#define Py_SANDBOX_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct _sandbox_state;  /* Forward */
-
-typedef struct _sandbox_state {
-    /* The memory cap and current usage. */
-    size_t mem_cap;
-    size_t mem_usage;
-
-} PySandboxState;
-
-typedef struct {
-    PyObject_HEAD
-    PyThreadState *tstate;
-} PySandboxObject;
-
-PyAPI_DATA(PyTypeObject) PySandbox_Type;
-
-/* Return the sandbox state struct. */
-#define _PySandbox_GET() (PyThreadState_GET()->interp->sandbox_state)
-
-/* Return true if sandboxing is turn on for the current interpreter. */
-#define _PySandbox_Check() (_PySandbox_GET() != NULL)
-
-/* Return true if memory caps are to be used.
-   Assumes sandboxing is turned on. */
-#define _PySandbox_IsMemCapped() (_PySandbox_GET()->mem_cap > 0)
-
-
-/*
-   Memory
-*/
-
-PyAPI_FUNC(int) PySandbox_SetMemoryCap(PyThreadState *, size_t);
-
-PyAPI_FUNC(int) _PySandbox_AllowedMemoryAlloc(size_t);
-/* Return for caller if memory allocation would exceed memory cap. */
-#define PySandbox_AllowedMemoryAlloc(alloc, err_return) \
-    if (!_PySandbox_AllowedMemoryAlloc(alloc)) return err_return
-
-/* Lower memory usage. */
-PyAPI_FUNC(void) PySandbox_AllowedMemoryFree(size_t);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* Py_SANDBOX_H */
-#endif /* PySandbox_SUPPORTED */

Modified: python/branches/bcannon-sandboxing/Lib/test/exception_hierarchy.txt
==============================================================================
--- python/branches/bcannon-sandboxing/Lib/test/exception_hierarchy.txt	(original)
+++ python/branches/bcannon-sandboxing/Lib/test/exception_hierarchy.txt	Thu Jul 20 21:42:38 2006
@@ -27,7 +27,6 @@
       |    +-- ReferenceError
       |    +-- RuntimeError
       |    |    +-- NotImplementedError
-      |    +-- SandboxError
       |    +-- SyntaxError
       |    |    +-- IndentationError
       |    |         +-- TabError

Modified: python/branches/bcannon-sandboxing/Makefile.pre.in
==============================================================================
--- python/branches/bcannon-sandboxing/Makefile.pre.in	(original)
+++ python/branches/bcannon-sandboxing/Makefile.pre.in	Thu Jul 20 21:42:38 2006
@@ -262,7 +262,6 @@
 		Python/mysnprintf.o \
 		Python/pyarena.o \
 		Python/pyfpe.o \
-		Python/sandbox.o \
 		Python/pystate.o \
 		Python/pythonrun.o \
 		Python/structmember.o \
@@ -540,7 +539,6 @@
 		Include/pyfpe.h \
 		Include/pymem.h \
 		Include/pyport.h \
-		Include/sandbox.h \
 		Include/pystate.h \
 		Include/pythonrun.h \
 		Include/rangeobject.h \

Deleted: /python/branches/bcannon-sandboxing/Modules/sandboxmodule.c
==============================================================================
--- /python/branches/bcannon-sandboxing/Modules/sandboxmodule.c	Thu Jul 20 21:42:38 2006
+++ (empty file)
@@ -1,227 +0,0 @@
-#include "Python.h"
-#include "structmember.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-   Destroy the sandboxed interpreter and dealloc memory.
-*/
-static void
-sandbox_dealloc(PyObject *self)
-{
-    PyThreadState *sand_tstate = NULL;
-    PyThreadState *cur_tstate = NULL;
-
-    /* To destory an interpreter using Py_EndInterpreter() it must be the
-       currently running interpreter.  This means you must temporariy make the
-       sanboxed interpreter the running interpreter again, destroy it, and then
-       swap back to the interpreter that created the interpreter in the first
-       place. */
-    sand_tstate = ((PySandboxObject *)self)->tstate;
-    cur_tstate = PyThreadState_Swap(sand_tstate);
-
-    Py_EndInterpreter(sand_tstate);
-    PyEval_RestoreThread(cur_tstate);
-
-    /* XXX need to do any special memory dealloc for sandboxed interpreter? */
-    self->ob_type->tp_free(self);
-}
-
-/*
-   Create new sandboxed interpreter.
-   XXX Might be better to wait until actual execution occurs to create the interpreter.  Would make these objects one-offs, but could then change this to a function instead where you pass in the needed arguments to handle everything (which is fine since object-capabilities puts the security into __builtins__ and thus only need that)).
-   XXX Could also create thread/interpreter from scratch and avoid all of this swapping of thread states (would need to do initialization that Py_NewInterpreter() did, though). */
-static PyObject *
-sandbox_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    PySandboxObject *self;
-    PyThreadState *cur_tstate;
-
-    self = (PySandboxObject *)type->tp_alloc(type, 0);
-    if (self == NULL)
-	return NULL;
-
-    /* Creating a new interpreter swaps out the current one. */
-    cur_tstate = PyThreadState_GET();
-
-    /* XXX chang eto call PySandbox_NewInterpreter() */
-    if (Py_NewInterpreter() == NULL) {
-	Py_DECREF(self);
-	/* XXX SandboxError best exception to use here? */
-	PyErr_SetString(PyExc_SandboxError, "sub-interpreter creation failed");
-	return NULL;
-    }
-
-    self->tstate = PyThreadState_Swap(cur_tstate);
-    if (self->tstate == NULL) {
-	Py_DECREF(self);
-	PyErr_SetString(PyExc_SandboxError, "sub-interpreter swap failed");
-	return NULL;
-    }
-
-    return (PyObject *)self;
-}
-
-static PyObject *
-sandbox_run(PyObject *self, PyObject *arg)
-{
-    PySandboxObject *sandbox_self = (PySandboxObject *)self;
-    const char *str_arg = NULL;
-    PyThreadState* cur_tstate = NULL;
-    int result = 0;
-
-    if (!PyString_Check(arg)) {
-	PyErr_SetString(PyExc_TypeError, "argument must be a string");
-	return NULL;
-    }
-
-    str_arg = PyString_AsString(arg);
-    if (!str_arg)
-	return NULL;
-
-    cur_tstate = PyThreadState_Swap(sandbox_self->tstate);
-
-    result = PyRun_SimpleString(str_arg);
-    if (result < 0) {
-	PyErr_Clear();
-    }
-
-    PyThreadState_Swap(cur_tstate);
-
-    if (result < 0) {
-	PyErr_SetString(PyExc_SandboxError,
-			"exception during execution in sandbox");
-	return NULL;
-    }
-
-    Py_RETURN_NONE;
-}
-
-static PyMethodDef sandbox_methods[] = {
-    {"run", sandbox_run, METH_O,
-	"Run the passed-in string in the sandboxed interpreter"},
-    {NULL}
-};
-
-
-static PyObject *
-sandbox_run_fxn(PyObject *self, PyObject *arg)
-{
-    PyThreadState *sandbox_tstate = NULL;
-    PyThreadState *cur_tstate = NULL;
-    int result = 0;
-    const char *arg_str = NULL;
-
-    if (!PyString_Check(arg)) {
-	PyErr_SetString(PyExc_TypeError, "argument must be a string");
-	return NULL;
-    }
-
-    arg_str = PyString_AsString(arg);
-    if (!arg_str)
-	return NULL;
-
-    cur_tstate = PyThreadState_GET();
-
-    sandbox_tstate = Py_NewInterpreter();
-    if (sandbox_tstate == NULL) {
-	PyErr_SetString(PyExc_SandboxError,
-			"could not instantiate a new sandboxed interpreter");
-	return NULL;
-    }
-
-    result = PyRun_SimpleString(arg_str);
-
-    Py_EndInterpreter(sandbox_tstate);
-    PyEval_RestoreThread(cur_tstate);
-
-    if (result < 0) {
-	PyErr_SetString(PyExc_SandboxError,
-		"exception raised in sandboxed interpreter");
-	return NULL;
-    }
-
-    Py_RETURN_NONE;
-}
-
-static PyMethodDef sandbox_fxns[] = {
-    {"run", sandbox_run_fxn, METH_O,
-	"Run the passed-in string in a new sandboxed interpreter"},
-    {NULL}
-};
-
-
-PyDoc_STRVAR(sandbox_type_doc,
-"XXX\n\
-\n\
-XXX");
-
-PyTypeObject PySandbox_Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,					/* ob_size */
-	"sandbox.Sandbox",			/* tp_name */
-	sizeof(PySandboxObject),		/* tp_basicsize */
-	0,               			/* tp_itemsize */
-	sandbox_dealloc,                      	/* tp_dealloc */
-	0,					/* tp_print */
-	0,			 		/* tp_getattr */
-	0,					/* tp_setattr */
-	0,       				/* tp_compare */
-	0,               			/* tp_repr */
-	0,					/* tp_as_number */
-	0,					/* tp_as_sequence */
-	0,					/* tp_as_mapping */
-	0,                      		/* tp_hash */
-	0,              			/* tp_call */
-	0,					/* tp_str */
-	0,                      		/* tp_getattro */
-	0,	                        	/* tp_setattro */
-	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT |
-	    Py_TPFLAGS_BASETYPE,     		/* tp_flags */
-	sandbox_type_doc,    			/* tp_doc */
-	0,                      		/* tp_traverse */
-	0,              			/* tp_clear */
-	0,					/* tp_richcompare */
-	0,                              	/* tp_weaklistoffset */
-	0,					/* tp_iter */
-	0,					/* tp_iternext */
-	sandbox_methods,      			/* tp_methods */
-	0,	         			/* tp_members */
-	0,		          		/* tp_getset */
-	0,					/* tp_base */
-	0,					/* tp_dict */
-	0,					/* tp_descr_get */
-	0,					/* tp_descr_set */
-	0,                              	/* tp_dictoffset */
-	0,					/* tp_init */
-	0,					/* tp_alloc */
-	sandbox_new,     			/* tp_new */
-	0,                      		/* tp_free */
-	0,              			/* tp_is_gc */
-};
-
-
-PyMODINIT_FUNC
-initsandbox(void)
-{
-    PyObject *module;
-
-    module = Py_InitModule3("sandbox", sandbox_fxns,
-	    "Provide a sandbox to safely execute Python code in.");
-    if (module == NULL)
-	return;
-
-    Py_INCREF(&PySandbox_Type);
-    if (PyType_Ready(&PySandbox_Type) < 0)
-	return;
-
-    if (PyModule_AddObject(module, "Sandbox", (PyObject *)&PySandbox_Type) < 0)
-	return;
-}
-
-#ifdef __cplusplus
-}
-#endif

Modified: python/branches/bcannon-sandboxing/Objects/exceptions.c
==============================================================================
--- python/branches/bcannon-sandboxing/Objects/exceptions.c	(original)
+++ python/branches/bcannon-sandboxing/Objects/exceptions.c	Thu Jul 20 21:42:38 2006
@@ -944,12 +944,6 @@
                        "Unspecified run-time error.");
 
 /*
-   SandboxError extends StandardError
-*/
-SimpleExtendsException(PyExc_StandardError, SandboxError,
-			"Attempt to exceed privileges under sandboxing.");
-
-/*
  *    NotImplementedError extends RuntimeError
  */
 SimpleExtendsException(PyExc_RuntimeError, NotImplementedError,
@@ -2020,7 +2014,6 @@
 #endif
     PRE_INIT(EOFError)
     PRE_INIT(RuntimeError)
-    PRE_INIT(SandboxError)
     PRE_INIT(NotImplementedError)
     PRE_INIT(NameError)
     PRE_INIT(UnboundLocalError)
@@ -2086,7 +2079,6 @@
 #endif
     POST_INIT(EOFError)
     POST_INIT(RuntimeError)
-    POST_INIT(SandboxError)
     POST_INIT(NotImplementedError)
     POST_INIT(NameError)
     POST_INIT(UnboundLocalError)

Modified: python/branches/bcannon-sandboxing/Objects/object.c
==============================================================================
--- python/branches/bcannon-sandboxing/Objects/object.c	(original)
+++ python/branches/bcannon-sandboxing/Objects/object.c	Thu Jul 20 21:42:38 2006
@@ -234,6 +234,13 @@
 _PyObject_New(PyTypeObject *tp)
 {
 	PyObject *op;
+#ifdef Py_MEMORY_CAP
+	PyInterpreterState *interp = PyInterpreterState_SafeGet();
+	if (interp) {
+	    if (!PyInterpreterState_RaiseMemoryUsage(interp, _PyObject_SIZE(tp)))
+		return NULL;
+	}
+#endif
 	op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
 	if (op == NULL)
 		return PyErr_NoMemory();
@@ -245,19 +252,47 @@
 {
 	PyVarObject *op;
 	const size_t size = _PyObject_VAR_SIZE(tp, nitems);
+#ifdef Py_MEMORY_CAP
+	PyInterpreterState *interp = PyInterpreterState_SafeGet();
+	if (interp) {
+	    if (!PyInterpreterState_RaiseMemoryUsage(interp, size))
+		return NULL;
+	}
+#endif
 	op = (PyVarObject *) PyObject_MALLOC(size);
 	if (op == NULL)
 		return (PyVarObject *)PyErr_NoMemory();
 	return PyObject_INIT_VAR(op, tp, nitems);
 }
 
-/* for binary compatibility with 2.2 */
-#undef _PyObject_Del
+#ifdef Py_MEMORY_CAP
+void
+_PyObject_Del(void *op)
+{
+    PyObject *obj = (PyObject *)op;
+    size_t to_free = obj->ob_type->tp_basicsize;
+    PyInterpreterState *interp = PyInterpreterState_SafeGet();
+
+    if (obj->ob_type->tp_itemsize) {
+	Py_ssize_t obj_size = ((PyVarObject *)obj)->ob_size;
+
+	if (obj_size > 0)
+	    to_free += obj_size * obj->ob_type->tp_itemsize;
+    }
+
+    if (interp)
+	PyInterpreterState_LowerMemoryUsage(interp, to_free);
+
+    PyObject_Free(op);
+}
+#else /* !Py_MEMORY_CAP */
+/* for binary compatibility with 2.2 and sandboxing. */
 void
 _PyObject_Del(PyObject *op)
 {
 	PyObject_FREE(op);
 }
+#endif /* Py_MEMORY_CAP */
 
 /* Implementation of PyObject_Print with recursion checking */
 static int
@@ -2019,18 +2054,41 @@
 void *
 PyMem_Malloc(size_t nbytes)
 {
+#ifdef Py_MEMORY_CAP
+	PyInterpreterState *interp = PyInterpreterState_SafeGet();
+
+	if (interp) {
+	    if (!PyInterpreterState_RaiseMemoryUsage(interp, nbytes))
+		return NULL;
+	}
+#endif
 	return PyMem_MALLOC(nbytes);
 }
 
 void *
 PyMem_Realloc(void *p, size_t nbytes)
 {
+#ifdef Py_MEMORY_CAP
+	size_t mem_diff = (p ? nbytes - sizeof(p) : nbytes);
+	PyInterpreterState *interp = PyInterpreterState_SafeGet();
+
+	if (interp) {
+	    if (!PyInterpreterState_RaiseMemoryUsage(interp, mem_diff))
+		return NULL;
+	}
+#endif
 	return PyMem_REALLOC(p, nbytes);
 }
 
 void
 PyMem_Free(void *p)
 {
+#ifdef Py_MEMORY_CAP
+	PyInterpreterState *interp = PyInterpreterState_SafeGet();
+
+	if (interp)
+	    PyInterpreterState_LowerMemoryUsage(interp, sizeof(p));
+#endif
 	PyMem_FREE(p);
 }
 

Modified: python/branches/bcannon-sandboxing/Python/pystate.c
==============================================================================
--- python/branches/bcannon-sandboxing/Python/pystate.c	(original)
+++ python/branches/bcannon-sandboxing/Python/pystate.c	Thu Jul 20 21:42:38 2006
@@ -80,6 +80,10 @@
 #ifdef WITH_TSC
 		interp->tscdump = 0;
 #endif
+#ifdef Py_MEMORY_CAP
+		interp->mem_cap = 0;
+		interp->mem_usage = 0;
+#endif
 
 		HEAD_LOCK();
 		interp->next = interp_head;
@@ -140,6 +144,75 @@
 	free(interp);
 }
 
+#ifdef Py_MEMORY_CAP
+/*
+   Get the interpreter state from a PyThreadState after checking to make sure
+   it is safe to do so based on initialization of the interpreter.
+*/
+PyInterpreterState *
+PyInterpreterState_SafeGet(void)
+{
+    PyThreadState *tstate = NULL;
+
+    if (!Py_IsInitialized() || !PyEval_ThreadsInitialized())
+	return NULL;
+
+    tstate = PyThreadState_GET();
+    if (!tstate)
+	return NULL;
+
+    return tstate->interp;
+}
+
+/*
+   Raise the current allocation of memory on the interpreter by 'increase'.
+   If it the allocation pushes the total memory usage past the memory cap,
+   return a false value.
+*/
+int
+PyInterpreterState_RaiseMemoryUsage(PyInterpreterState *interp, size_t increase)
+{
+    size_t original_mem_usage = 0;
+
+    if (increase < 0)
+	Py_FatalError("can only increase memory usage by a positive value");
+
+    if (!interp->mem_cap)
+	return 1;
+
+    /* Watch out for integer overflow. */
+    original_mem_usage = interp->mem_usage;
+    interp->mem_usage += increase;
+    if (interp->mem_usage < original_mem_usage) {
+	interp->mem_usage = original_mem_usage;
+	PyErr_SetString(PyExc_MemoryError, "integer overflow in memory usage");
+	return 0;
+    }
+    
+    if (interp->mem_usage > interp->mem_cap) {
+	interp->mem_usage = original_mem_usage;
+	PyErr_SetString(PyExc_MemoryError, "exceeded memory usage");
+	return 0;
+    }
+
+    return 1;
+}
+
+/*
+   Lower the current memory allocation.
+   If lowered to below zero, push back up to zero.
+*/
+void
+PyInterpreterState_LowerMemoryUsage(PyInterpreterState *interp, size_t decrease)
+{
+    if (decrease < 0)
+	Py_FatalError("must specify memory usage reduction by a positive number");
+
+    interp->mem_usage -= decrease;
+    if (interp->mem_usage < 0)
+	interp->mem_usage = 0;
+}
+#endif /* Py_MEMORY_CAP */
 
 /* Default implementation for _PyThreadState_GetFrame */
 static struct _frame *

Modified: python/branches/bcannon-sandboxing/Python/pythonrun.c
==============================================================================
--- python/branches/bcannon-sandboxing/Python/pythonrun.c	(original)
+++ python/branches/bcannon-sandboxing/Python/pythonrun.c	Thu Jul 20 21:42:38 2006
@@ -512,13 +512,6 @@
 	if (interp == NULL)
 		return NULL;
 
-#ifdef PySandbox_SUPPORTED
-	/* Must set sandbox_state to NULL to flag that the interpreter is
-	   unprotected.  It if is to be protected, the field is set by
-	   PySandbox_NewInterpreter(). */
-	interp->sandbox_state = NULL;
-#endif
-
 	tstate = PyThreadState_New(interp);
 	if (tstate == NULL) {
 		PyInterpreterState_Delete(interp);

Deleted: /python/branches/bcannon-sandboxing/Python/sandbox.c
==============================================================================
--- /python/branches/bcannon-sandboxing/Python/sandbox.c	Thu Jul 20 21:42:38 2006
+++ (empty file)
@@ -1,79 +0,0 @@
-#include "Python.h" /* Must be defined before PySandbox_SUPPORTED check */
-
-#ifdef PySandbox_SUPPORTED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-   Set the memory cap for a sandboxed interpreter.
-*/
-int
-PySandbox_SetMemoryCap(PyThreadState *s_tstate, size_t mem_cap)
-{
-    PySandboxState *sandbox_state = s_tstate->interp->sandbox_state;
-
-    if (!sandbox_state)
-	return 0;
-
-    sandbox_state->mem_cap = mem_cap;
-
-    return 1;
-}
-
-/*
-   Verify that memory allocation is allowed.
-*/
-int
-_PySandbox_AllowedMemoryAlloc(size_t allocate)
-{
-    PySandboxState *sandbox_state = NULL;
-
-    /* If can't track yet, just assume it worked. */
-if (!(Py_IsInitialized() && PyEval_ThreadsInitialized()))
-	return 1;
-    
-    sandbox_state = _PySandbox_GET();
-
-    if (_PySandbox_Check() && _PySandbox_IsMemCapped()) {
-	size_t orig_mem_usage = sandbox_state->mem_usage;
-
-	sandbox_state->mem_usage += allocate;
-	/* Watch out for integer overflow. */
-	if ((sandbox_state->mem_cap < sandbox_state->mem_usage) ||
-		(orig_mem_usage > sandbox_state->mem_usage)) {
-	    sandbox_state -= allocate;
-	    PyErr_SetString(PyExc_SandboxError, "memory allocation exceeded");
-	    return 0;
-	}
-    }
-
-    return 1;
-}
-
-/*
-   Verify that freeing memory does not go past what was already used.
-*/
-void
-PySandbox_AllowedMemoryFree(size_t deallocate)
-{
-    PySandboxState *sandbox_state = NULL;
-
-    /* If interpreter not up yet, then don't worry about memory. */
-    if (!(Py_IsInitialized() && PyEval_ThreadsInitialized()))
-	return;
-
-    sandbox_state = _PySandbox_GET();
-    if (_PySandbox_Check() && _PySandbox_IsMemCapped()) {
-	sandbox_state->mem_usage -= deallocate;
-	if (sandbox_state->mem_usage < 0)
-	    sandbox_state->mem_usage = 0;
-    }
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* PySandbox_SUPPORTED */

Modified: python/branches/bcannon-sandboxing/configure
==============================================================================
--- python/branches/bcannon-sandboxing/configure	(original)
+++ python/branches/bcannon-sandboxing/configure	Thu Jul 20 21:42:38 2006
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 47023 .
+# From configure.in Revision: 50540 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59 for python 2.5.
 #
@@ -866,7 +866,7 @@
                           compiler
   --with-suffix=.exe      set executable suffix
   --with-pydebug          build with Py_DEBUG defined
-  --with-sandboxing       build with PySandbox_SUPPORTED defined
+  --with-memory-cap       build with Py_MEMORY_CAP defined
   --with-libs='lib1 ...'  link against additional libs
   --with-system-ffi       build _ctypes module using an installed ffi library
   --with-signal-module    disable/enable signal module
@@ -3765,26 +3765,26 @@
 echo "${ECHO_T}no" >&6
 fi;
 
-# Check for --with-sandboxing
-echo "$as_me:$LINENO: checking for --with-sandboxing" >&5
-echo $ECHO_N "checking for --with-sandboxing... $ECHO_C" >&6
-
-# Check whether --with-sandboxing or --without-sandboxing was given.
-if test "${with_sandboxing+set}" = set; then
-  withval="$with_sandboxing"
+# Check for --with-memory-cap
+echo "$as_me:$LINENO: checking for --with-memory-cap" >&5
+echo $ECHO_N "checking for --with-memory-cap... $ECHO_C" >&6
+
+# Check whether --with-memory-cap or --without-memory-cap was given.
+if test "${with_memory_cap+set}" = set; then
+  withval="$with_memory_cap"
 
 if test "$withval" != no
 then
 
 cat >>confdefs.h <<\_ACEOF
-#define PySandbox_SUPPORTED 1
+#define Py_MEMORY_CAP 1
 _ACEOF
 
   echo "$as_me:$LINENO: result: yes" >&5
 echo "${ECHO_T}yes" >&6;
-  PySandbox_SUPPORTED='true'
+  Py_MEMORY_CAP='true'
 else echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; PySandbox_SUPPORTED='false'
+echo "${ECHO_T}no" >&6; Py_MEMORY_CAP='false'
 fi
 else
   echo "$as_me:$LINENO: result: no" >&5

Modified: python/branches/bcannon-sandboxing/configure.in
==============================================================================
--- python/branches/bcannon-sandboxing/configure.in	(original)
+++ python/branches/bcannon-sandboxing/configure.in	Thu Jul 20 21:42:38 2006
@@ -725,18 +725,18 @@
 fi],
 [AC_MSG_RESULT(no)])
 
-# Check for --with-sandboxing
-AC_MSG_CHECKING(for --with-sandboxing)
-AC_ARG_WITH(sandboxing, 
-            AC_HELP_STRING(--with-sandboxing, build with PySandbox_SUPPORTED defined),
+# Check for --with-memory-cap
+AC_MSG_CHECKING(for --with-memory-cap)
+AC_ARG_WITH(memory-cap, 
+            AC_HELP_STRING(--with-memory-cap, build with Py_MEMORY_CAP defined),
 [
 if test "$withval" != no
 then 
-  AC_DEFINE(PySandbox_SUPPORTED, 1, 
-  [Define if you want to build an interpreter with sandboxing support.]) 
+  AC_DEFINE(Py_MEMORY_CAP, 1, 
+  [Define if you want to build an interpreter that can cap memory usage.]) 
   AC_MSG_RESULT(yes); 
-  PySandbox_SUPPORTED='true'
-else AC_MSG_RESULT(no); PySandbox_SUPPORTED='false'
+  Py_MEMORY_CAP='true'
+else AC_MSG_RESULT(no); Py_MEMORY_CAP='false'
 fi],
 [AC_MSG_RESULT(no)])
 

Modified: python/branches/bcannon-sandboxing/pyconfig.h.in
==============================================================================
--- python/branches/bcannon-sandboxing/pyconfig.h.in	(original)
+++ python/branches/bcannon-sandboxing/pyconfig.h.in	Thu Jul 20 21:42:38 2006
@@ -766,15 +766,15 @@
 /* Define as the integral type used for Unicode representation. */
 #undef PY_UNICODE_TYPE
 
-/* Define if you want to build an interpreter with sandboxing support. */
-#undef PySandbox_SUPPORTED
-
 /* Define if you want to build an interpreter with many run-time checks. */
 #undef Py_DEBUG
 
 /* Defined if Python is built as a shared library. */
 #undef Py_ENABLE_SHARED
 
+/* Define if you want to build an interpreter that can cap memory usage. */
+#undef Py_MEMORY_CAP
+
 /* Define as the size of the unicode type. */
 #undef Py_UNICODE_SIZE
 

Modified: python/branches/bcannon-sandboxing/setup.py
==============================================================================
--- python/branches/bcannon-sandboxing/setup.py	(original)
+++ python/branches/bcannon-sandboxing/setup.py	Thu Jul 20 21:42:38 2006
@@ -515,10 +515,6 @@
         # CSV files
         exts.append( Extension('_csv', ['_csv.c']) )
 
-        # Sandboxing
-        if config_h_vars.get("PySandbox_SUPPORTED", False):
-            exts.append(Extension('sandbox', ['sandboxmodule.c']) )
-
         # socket(2)
         exts.append( Extension('_socket', ['socketmodule.c'],
                                depends = ['socketmodule.h']) )


More information about the Python-checkins mailing list