[Python-checkins] r50772 - in python/branches/bcannon-sandboxing: Include/Python.h Include/objimpl.h Include/pymem.h Include/pystate.h Lib/test/test_sys.py Modules/gcmodule.c Objects/bufferobject.c Objects/complexobject.c Objects/object.c Objects/stringobject.c Objects/typeobject.c Python/pystate.c Python/pythonrun.c securing_python.txt

brett.cannon python-checkins at python.org
Sat Jul 22 00:58:00 CEST 2006


Author: brett.cannon
Date: Sat Jul 22 00:57:57 2006
New Revision: 50772

Modified:
   python/branches/bcannon-sandboxing/Include/Python.h
   python/branches/bcannon-sandboxing/Include/objimpl.h
   python/branches/bcannon-sandboxing/Include/pymem.h
   python/branches/bcannon-sandboxing/Include/pystate.h
   python/branches/bcannon-sandboxing/Lib/test/test_sys.py
   python/branches/bcannon-sandboxing/Modules/gcmodule.c
   python/branches/bcannon-sandboxing/Objects/bufferobject.c
   python/branches/bcannon-sandboxing/Objects/complexobject.c
   python/branches/bcannon-sandboxing/Objects/object.c
   python/branches/bcannon-sandboxing/Objects/stringobject.c
   python/branches/bcannon-sandboxing/Objects/typeobject.c
   python/branches/bcannon-sandboxing/Python/pystate.c
   python/branches/bcannon-sandboxing/Python/pythonrun.c
   python/branches/bcannon-sandboxing/securing_python.txt
Log:
New try from scratch of keeping track of memory.  Doing it at the object level
and requiring specification of what memory is for.

Some debugging output is turned on.

Would be nice if even low-level calls included what the memory was for.


Modified: python/branches/bcannon-sandboxing/Include/Python.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/Python.h	(original)
+++ python/branches/bcannon-sandboxing/Include/Python.h	Sat Jul 22 00:57:57 2006
@@ -67,7 +67,7 @@
 /* Debug-mode build with pymalloc implies PYMALLOC_DEBUG.
  *  PYMALLOC_DEBUG is in error if pymalloc is not in use.
  */
-#if defined(Py_DEBUG) && defined(WITH_PYMALLOC) && !defined(PYMALLOC_DEBUG)
+#if defined(Py_DEBUG) && defined(WITH_PYMALLOC) && !defined(PYMALLOC_DEBUG) && !defined(Py_MEMORY_CAP)
 #define PYMALLOC_DEBUG
 #endif
 #if defined(PYMALLOC_DEBUG) && !defined(WITH_PYMALLOC)

Modified: python/branches/bcannon-sandboxing/Include/objimpl.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/objimpl.h	(original)
+++ python/branches/bcannon-sandboxing/Include/objimpl.h	Sat Jul 22 00:57:57 2006
@@ -101,7 +101,7 @@
 
 /* Macros */
 #ifdef WITH_PYMALLOC
-#ifdef PYMALLOC_DEBUG	/* WITH_PYMALLOC && PYMALLOC_DEBUG */
+#if defined(PYMALLOC_DEBUG)	/* WITH_PYMALLOC && PYMALLOC_DEBUG */
 PyAPI_FUNC(void *) _PyObject_DebugMalloc(size_t nbytes);
 PyAPI_FUNC(void *) _PyObject_DebugRealloc(void *p, size_t nbytes);
 PyAPI_FUNC(void) _PyObject_DebugFree(void *p);
@@ -119,7 +119,7 @@
 #define PyObject_MALLOC		PyObject_Malloc
 #define PyObject_REALLOC	PyObject_Realloc
 #define PyObject_FREE		PyObject_Free
-#endif
+#endif /* PYMALLOC_DEBUG */
 
 #else	/* ! WITH_PYMALLOC */
 #define PyObject_MALLOC		PyMem_MALLOC
@@ -128,15 +128,16 @@
 
 #endif	/* WITH_PYMALLOC */
 
-#ifndef Py_MEMORY_CAP
+#ifdef Py_MEMORY_CAP
+PyAPI_FUNC(void) _PyObject_Del(void *);
+#define PyObject_Del		_PyObject_Del
+#define PyObject_DEL		_PyObject_Del
+#else /* !Py_MEMORY_CAP */
 #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
+#endif  /* Py_MEMORY_CAP */
+/* for source compatibility with 2.2 */
 
 /*
  * Generic object allocator interface

Modified: python/branches/bcannon-sandboxing/Include/pymem.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/pymem.h	(original)
+++ python/branches/bcannon-sandboxing/Include/pymem.h	Sat Jul 22 00:57:57 2006
@@ -61,12 +61,6 @@
 #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	Sat Jul 22 00:57:57 2006
@@ -110,8 +110,11 @@
 #ifdef Py_MEMORY_CAP
 PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_SafeGet(void);
 PyAPI_FUNC(int) PyInterpreterState_SetMemoryCap(PyInterpreterState *, PY_LONG_LONG);
-PyAPI_FUNC(int) PyInterpreterState_RaiseMemoryUsage(PyInterpreterState *, size_t);
-PyAPI_FUNC(void) PyInterpreterState_LowerMemoryUsage(PyInterpreterState *, size_t);
+PyAPI_FUNC(int) PyInterpreterState_AddObjectMem(PyTypeObject *);
+PyAPI_FUNC(int) PyInterpreterState_AddVarObjectMem(PyTypeObject *, Py_ssize_t);
+PyAPI_FUNC(int) PyInterpreterState_AddRawMem(const char *, size_t);
+PyAPI_FUNC(void) PyInterpreterState_RemoveObjectMem(PyObject *);
+PyAPI_FUNC(void) PyInterpreterState_RemoveRawMem(const char *, size_t);
 #endif /* Py_MEMORY_CAP */
 
 PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *);

Modified: python/branches/bcannon-sandboxing/Lib/test/test_sys.py
==============================================================================
--- python/branches/bcannon-sandboxing/Lib/test/test_sys.py	(original)
+++ python/branches/bcannon-sandboxing/Lib/test/test_sys.py	Sat Jul 22 00:57:57 2006
@@ -272,13 +272,17 @@
             return
         original_cap = sys.getmemorycap()
         self.failUnless(isinstance(original_cap, (int, long)))
-        new_cap = int(original_cap + 10000)
+        new_cap = int(1000 * 1000 * 1000)
         assert isinstance(new_cap, int)
         sys.setmemorycap(new_cap)
-        try:  # Make sure don't mess up interpreter.
+        try:  # Make sure don't mess up interpreter memory cap.
             self.failUnlessEqual(new_cap, sys.getmemorycap())
             sys.setmemorycap(long(new_cap))
             self.failUnlessEqual(new_cap, sys.getmemorycap())
+            current_usage = sys.getmemoryused()
+            used_memory = chr(ord('A')) + chr(ord('B'))
+            next_current_usage = sys.getmemoryused()
+            self.failUnlessEqual(next_current_usage, current_usage)
         finally:
             try:  # setmemorycap() could be broken.
                 sys.setmemorycap(original_cap)

Modified: python/branches/bcannon-sandboxing/Modules/gcmodule.c
==============================================================================
--- python/branches/bcannon-sandboxing/Modules/gcmodule.c	(original)
+++ python/branches/bcannon-sandboxing/Modules/gcmodule.c	Sat Jul 22 00:57:57 2006
@@ -1317,8 +1317,9 @@
 _PyObject_GC_Malloc(size_t basicsize)
 {
 	PyObject *op;
-	PyGC_Head *g = (PyGC_Head *)PyObject_MALLOC(
-                sizeof(PyGC_Head) + basicsize);
+	PyGC_Head *g = NULL;
+
+	g  = (PyGC_Head *)PyObject_MALLOC(sizeof(PyGC_Head) + basicsize);
 	if (g == NULL)
 		return PyErr_NoMemory();
 	g->gc.gc_refs = GC_UNTRACKED;
@@ -1339,7 +1340,13 @@
 PyObject *
 _PyObject_GC_New(PyTypeObject *tp)
 {
-	PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp));
+	PyObject *op = NULL;
+
+#ifdef Py_MEMORY_CAP
+	if (!PyInterpreterState_AddObjectMem(tp))
+	    return NULL;
+#endif
+	op = _PyObject_GC_Malloc(_PyObject_SIZE(tp));
 	if (op != NULL)
 		op = PyObject_INIT(op, tp);
 	return op;
@@ -1349,7 +1356,13 @@
 _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
 {
 	const size_t size = _PyObject_VAR_SIZE(tp, nitems);
-	PyVarObject *op = (PyVarObject *) _PyObject_GC_Malloc(size);
+	PyVarObject *op = NULL;
+
+#ifdef Py_MEMORY_CAP
+	if (!PyInterpreterState_AddVarObjectMem(tp, nitems))
+	    return NULL;
+#endif
+	op = (PyVarObject *) _PyObject_GC_Malloc(size);
 	if (op != NULL)
 		op = PyObject_INIT_VAR(op, tp, nitems);
 	return op;
@@ -1377,6 +1390,9 @@
 	if (generations[0].count > 0) {
 		generations[0].count--;
 	}
+#ifdef Py_MEMORY_CAP
+	PyInterpreterState_RemoveObjectMem((PyObject *)op);
+#endif
 	PyObject_FREE(g);
 }
 

Modified: python/branches/bcannon-sandboxing/Objects/bufferobject.c
==============================================================================
--- python/branches/bcannon-sandboxing/Objects/bufferobject.c	(original)
+++ python/branches/bcannon-sandboxing/Objects/bufferobject.c	Sat Jul 22 00:57:57 2006
@@ -209,6 +209,11 @@
 	}
 	/* XXX: check for overflow in multiply */
 	/* Inline PyObject_New */
+#ifdef Py_MEMORY_CAP
+	if (!PyInterpreterState_AddRawMem("buffer",
+					    sizeof(*b) + size))
+	    return PyErr_NoMemory();
+#endif
 	o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
 	if ( o == NULL )
 		return PyErr_NoMemory();

Modified: python/branches/bcannon-sandboxing/Objects/complexobject.c
==============================================================================
--- python/branches/bcannon-sandboxing/Objects/complexobject.c	(original)
+++ python/branches/bcannon-sandboxing/Objects/complexobject.c	Sat Jul 22 00:57:57 2006
@@ -200,6 +200,10 @@
 	register PyComplexObject *op;
 
 	/* Inline PyObject_New */
+#ifdef Py_MEMORY_CAP
+	if (!PyInterpreterState_AddRawMem("complex number", sizeof(PyComplexObject)))
+		return PyErr_NoMemory();
+#endif
 	op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
 	if (op == NULL)
 		return PyErr_NoMemory();

Modified: python/branches/bcannon-sandboxing/Objects/object.c
==============================================================================
--- python/branches/bcannon-sandboxing/Objects/object.c	(original)
+++ python/branches/bcannon-sandboxing/Objects/object.c	Sat Jul 22 00:57:57 2006
@@ -234,14 +234,14 @@
 _PyObject_New(PyTypeObject *tp)
 {
 	PyObject *op;
+	size_t tp_size = _PyObject_SIZE(tp);
+
 #ifdef Py_MEMORY_CAP
-	PyInterpreterState *interp = PyInterpreterState_SafeGet();
-	if (interp) {
-	    if (!PyInterpreterState_RaiseMemoryUsage(interp, _PyObject_SIZE(tp)))
-		return NULL;
-	}
+	if (!PyInterpreterState_AddObjectMem(tp))
+	    return PyErr_NoMemory();
 #endif
-	op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
+
+	op = (PyObject *) PyObject_MALLOC(tp_size);
 	if (op == NULL)
 		return PyErr_NoMemory();
 	return PyObject_INIT(op, tp);
@@ -252,47 +252,28 @@
 {
 	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;
-	}
+	if (!PyInterpreterState_AddVarObjectMem(tp, nitems))
+	    return (PyVarObject *)PyErr_NoMemory();
 #endif
+
 	op = (PyVarObject *) PyObject_MALLOC(size);
 	if (op == NULL)
 		return (PyVarObject *)PyErr_NoMemory();
 	return PyObject_INIT_VAR(op, tp, nitems);
 }
 
-#ifdef Py_MEMORY_CAP
+/* for binary compatibility with 2.2. */
+#undef _PyObject_Del
 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)
-{
+#ifdef Py_MEMORY_CAP
+    PyInterpreterState_RemoveObjectMem((PyObject *)op);
+#endif
 	PyObject_FREE(op);
 }
-#endif /* Py_MEMORY_CAP */
 
 /* Implementation of PyObject_Print with recursion checking */
 static int
@@ -2054,41 +2035,18 @@
 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/Objects/stringobject.c
==============================================================================
--- python/branches/bcannon-sandboxing/Objects/stringobject.c	(original)
+++ python/branches/bcannon-sandboxing/Objects/stringobject.c	Sat Jul 22 00:57:57 2006
@@ -72,6 +72,10 @@
 	}
 
 	/* Inline PyObject_NewVar */
+#ifdef Py_MEMORY_CAP
+	if (!PyInterpreterState_AddRawMem("str", sizeof(PyStringObject) + size))
+	    return PyErr_NoMemory();
+#endif
 	op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
 	if (op == NULL)
 		return PyErr_NoMemory();
@@ -127,6 +131,10 @@
 	}
 
 	/* Inline PyObject_NewVar */
+#ifdef Py_MEMORY_CAP
+	 if (!PyInterpreterState_AddRawMem("str", sizeof(PyStringObject) + size))
+	     return PyErr_NoMemory();
+#endif
 	op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
 	if (op == NULL)
 		return PyErr_NoMemory();
@@ -960,6 +968,10 @@
 	}
 	  
 	/* Inline PyObject_NewVar */
+#ifdef Py_MEMORY_CAP
+	if (!PyInterpreterState_AddRawMem("str", sizeof(PyStringObject) + size))
+	    return PyErr_NoMemory();
+#endif
 	op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
 	if (op == NULL)
 		return PyErr_NoMemory();
@@ -1002,6 +1014,10 @@
 			"repeated string is too long");
 		return NULL;
 	}
+#ifdef Py_MEMORY_CAP
+	if (!PyInterpreterState_AddRawMem("str", sizeof(PyStringObject) + nbytes))
+	    return PyErr_NoMemory();
+#endif
 	op = (PyStringObject *)
 		PyObject_MALLOC(sizeof(PyStringObject) + nbytes);
 	if (op == NULL)

Modified: python/branches/bcannon-sandboxing/Objects/typeobject.c
==============================================================================
--- python/branches/bcannon-sandboxing/Objects/typeobject.c	(original)
+++ python/branches/bcannon-sandboxing/Objects/typeobject.c	Sat Jul 22 00:57:57 2006
@@ -450,6 +450,10 @@
 	const size_t size = _PyObject_VAR_SIZE(type, nitems+1);
 	/* note that we need to add one, for the sentinel */
 
+#ifdef Py_MEMORY_CAP
+	if (!PyInterpreterState_AddVarObjectMem(type, nitems))
+	    return PyErr_NoMemory();
+#endif
 	if (PyType_IS_GC(type))
 		obj = _PyObject_GC_Malloc(size);
 	else
@@ -1892,6 +1896,12 @@
 		PyObject *doc = PyDict_GetItemString(dict, "__doc__");
 		if (doc != NULL && PyString_Check(doc)) {
 			const size_t n = (size_t)PyString_GET_SIZE(doc);
+#ifdef Py_MEMORY_CAP
+			if (!PyInterpreterState_AddRawMem("str", n)) {
+			    Py_DECREF(type);
+			    return NULL;
+			}
+#endif
                         char *tp_doc = (char *)PyObject_MALLOC(n+1);
 			if (tp_doc == NULL) {
 				Py_DECREF(type);
@@ -2145,7 +2155,7 @@
         /* A type's tp_doc is heap allocated, unlike the tp_doc slots
          * of most other objects.  It's okay to cast it to char *.
          */
-	PyObject_Free((char *)type->tp_doc);
+	PyObject_FREE((char *)type->tp_doc);
 	Py_XDECREF(et->ht_name);
 	Py_XDECREF(et->ht_slots);
 	type->ob_type->tp_free((PyObject *)type);

Modified: python/branches/bcannon-sandboxing/Python/pystate.c
==============================================================================
--- python/branches/bcannon-sandboxing/Python/pystate.c	(original)
+++ python/branches/bcannon-sandboxing/Python/pystate.c	Sat Jul 22 00:57:57 2006
@@ -183,17 +183,33 @@
     return 1;
 }
 
-/*
-   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)
+PyInterpreterState_AddObjectMem(PyTypeObject *obj_type)
+{
+    size_t total_mem = _PyObject_SIZE(obj_type);
+
+    return PyInterpreterState_AddRawMem(obj_type->tp_name, total_mem);
+}
+
+int
+PyInterpreterState_AddVarObjectMem(PyTypeObject *obj_type, Py_ssize_t nitems)
 {
-    size_t original_mem_usage = 0;
+    size_t total_mem = _PyObject_VAR_SIZE(obj_type, nitems);
 
-    if (increase < 0)
+    return PyInterpreterState_AddRawMem(obj_type->tp_name, total_mem);
+}
+
+int
+PyInterpreterState_AddRawMem(const char *from, size_t new_mem)
+{
+    /* XXX SafeGet() needed if working right off of objects? */
+    PyInterpreterState *interp = PyInterpreterState_SafeGet();
+    PY_LONG_LONG original_mem_usage = 0;
+
+    if (!interp)
+	return 1;
+
+    if (new_mem < 0)
 	Py_FatalError("can only increase memory usage by a positive value");
 
     if (!interp->mem_cap)
@@ -201,35 +217,48 @@
 
     /* Watch out for integer overflow. */
     original_mem_usage = interp->mem_usage;
-    interp->mem_usage += (PY_LONG_LONG)increase;
+    interp->mem_usage += (PY_LONG_LONG)new_mem;
     if (interp->mem_usage < original_mem_usage) {
 	interp->mem_usage = original_mem_usage;
-	PyErr_NoMemory();
 	return 0;
     }
     
     if (interp->mem_usage > interp->mem_cap) {
 	interp->mem_usage = original_mem_usage;
-	PyErr_NoMemory();
 	return 0;
     }
 
+    printf("add: %d (%s)\n", new_mem, from ? from : "<unknown>");
     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)
+PyInterpreterState_RemoveObjectMem(PyObject *py_obj)
 {
-    if (decrease < 0)
-	Py_FatalError("must specify memory usage reduction by a positive number");
+    size_t total_mem = _PyObject_SIZE(py_obj->ob_type);
+
+    if (py_obj->ob_type->tp_itemsize > 0)
+	total_mem += ((PyVarObject *)py_obj)->ob_size *
+			py_obj->ob_type->tp_itemsize;
 
-    interp->mem_usage -= (PY_LONG_LONG)decrease;
-    if (interp->mem_usage < 0)
-	interp->mem_usage = 0;
+    PyInterpreterState_RemoveRawMem(py_obj->ob_type->tp_name, total_mem);
+}
+
+void
+PyInterpreterState_RemoveRawMem(const char *from, size_t old_mem)
+{
+    PyInterpreterState *interp = PyInterpreterState_SafeGet();
+
+    if (!interp)
+	return;
+
+    if (old_mem < 0)
+	Py_FatalError("amount to decrease amount of memory must be >= 0");
+
+    if (interp->mem_cap) {
+	    printf("remove %d (%s)\n", old_mem, from ? from : "<unknown>");
+	    interp->mem_usage -= (PY_LONG_LONG)old_mem;
+	}
 }
 #endif /* Py_MEMORY_CAP */
 

Modified: python/branches/bcannon-sandboxing/Python/pythonrun.c
==============================================================================
--- python/branches/bcannon-sandboxing/Python/pythonrun.c	(original)
+++ python/branches/bcannon-sandboxing/Python/pythonrun.c	Sat Jul 22 00:57:57 2006
@@ -35,8 +35,8 @@
 #define PRINT_TOTAL_REFS()
 #else /* Py_REF_DEBUG */
 #define PRINT_TOTAL_REFS() fprintf(stderr,				\
-				   "[%" PY_FORMAT_SIZE_T "d refs]\n",	\
-				   _Py_GetRefTotal())
+				   "[%" PY_FORMAT_SIZE_T "d refs, %lld memory]\n",	\
+				   _Py_GetRefTotal(), PyThreadState_Get()->interp->mem_usage)
 #endif
 
 #ifdef __cplusplus

Modified: python/branches/bcannon-sandboxing/securing_python.txt
==============================================================================
--- python/branches/bcannon-sandboxing/securing_python.txt	(original)
+++ python/branches/bcannon-sandboxing/securing_python.txt	Sat Jul 22 00:57:57 2006
@@ -665,42 +665,21 @@
 
 Existing APIs to protect are:
 
-- _PyObject_New()
-    protected directly
-- _PyObject_NewVar()
-    protected directly
+- _PyObject_New() : PyObject_New()
+- _PyObject_NewVar() : PyObject_NewVar()
 - _PyObject_Del()
     remove macro that uses PyObject_Free() and protect directly
-- PyObject_New()
-    implicitly by macro using _PyObject_New()
-- PyObject_NewVar()
-    implicitly by macro using _PyObject_NewVar()
 - PyObject_Del()
     redefine macro to use _PyObject_Del() instead of PyObject_Free()
-- PyMem_Malloc()
-    protected directly
-- PyMem_Realloc()
-    protected directly
-- PyMem_Free()
-    protected directly
-- PyMem_New()
-    implicitly protected by macro using PyMem_Malloc()
-- PyMem_Resize()
-    implicitly protected by macro using PyMem_Realloc()
-- PyMem_Del()
-    implicitly protected by macro using PyMem_Free()
-- PyMem_MALLOC()
+- PyMem_Malloc() : PyMem_New()
+- PyMem_Realloc() : PyMem_Resize()
+- PyMem_Free() : PyMem_Del()
+- PyMem_MALLOC() : PyMem_NEW()
     redefine macro to use PyMem_Malloc()
-- PyMem_REALLOC()
+- PyMem_REALLOC() : PyMem_RESIZE()
     redefine macro to use PyMem_Realloc()
-- PyMem_FREE()
+- PyMem_FREE() : PyMem_DEL()
     redefine macro to use PyMem_Free()
-- PyMem_NEW()
-    implicitly protected by macro using PyMem_MALLOC()
-- PyMem_RESIZE()
-    implicitly protected by macro using PyMem_REALLOC()
-- PyMem_DEL()
-    implicitly protected by macro using PyMem_FREE()
 - PyObject_Malloc()
     XXX
 - PyObject_Realloc()


More information about the Python-checkins mailing list