Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(39)

Unified Diff: Include/pymem.h

Issue 2599: python - fix buffer overflows in unicode processing and elsewhere SVN Base: http://svn.python.org/view/*checkout*/python/trunk/
Patch Set: Created 1 year, 4 months ago , Downloaded from: http://bugs.python.org/file10825/issue2620-gps02-patch.txt
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side by-side-diff with in-line comments
Download patch
Index: Include/pymem.h
===================================================================
--- Include/pymem.h (revision 64754)
+++ Include/pymem.h (working copy)
@@ -69,8 +69,12 @@
for malloc(0), which would be treated as an error. Some platforms
would return a pointer with no memory behind it, which would break
pymalloc. To solve these problems, allocate an extra byte. */
-#define PyMem_MALLOC(n) malloc((n) ? (n) : 1)
-#define PyMem_REALLOC(p, n) realloc((p), (n) ? (n) : 1)
+/* Returns NULL to indicate error if a negative size or size larger than
+ Py_ssize_t can represent is supplied. Helps prevents security holes. */
+#define PyMem_MALLOC(n) (((n) < 0 || (n) > PY_SSIZE_T_MAX) ? NULL \
+ : malloc((n) ? (n) : 1))
+#define PyMem_REALLOC(p, n) (((n) < 0 || (n) > PY_SSIZE_T_MAX) ? NULL \
+ : realloc((p), (n) ? (n) : 1))
#define PyMem_FREE free
#endif /* PYMALLOC_DEBUG */
@@ -79,24 +83,31 @@
* Type-oriented memory interface
* ==============================
*
- * These are carried along for historical reasons. There's rarely a good
- * reason to use them anymore (you can just as easily do the multiply and
- * cast yourself).
+ * Allocate memory for n objects of the given type. Returns a new pointer
+ * or NULL if the request was too large or memory allocation failed. Use
+ * these macros rather than doing the multiplication yourself so that proper
+ * overflow checking is always done.
*/
#define PyMem_New(type, n) \
- ( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
+ ( ((n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \
( (type *) PyMem_Malloc((n) * sizeof(type)) ) )
#define PyMem_NEW(type, n) \
- ( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
+ ( ((n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \
( (type *) PyMem_MALLOC((n) * sizeof(type)) ) )
+/*
+ * The value of (p) is always clobbered by this macro regardless of success.
+ * The caller MUST check if (p) is NULL afterwards and deal with the memory
+ * error if so. This means the original value of (p) MUST be saved for the
+ * caller's memory error handler to not lose track of it.
+ */
#define PyMem_Resize(p, type, n) \
- ( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
- ( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) ) )
+ ( (p) = ((n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \
+ (type *) PyMem_Realloc((p), (n) * sizeof(type)) )
#define PyMem_RESIZE(p, type, n) \
- ( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
- ( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) ) )
+ ( (p) = ((n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \
+ (type *) PyMem_REALLOC((p), (n) * sizeof(type)) )
/* PyMem{Del,DEL} are left over from ancient days, and shouldn't be used
* anymore. They're just confusing aliases for PyMem_{Free,FREE} now.

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld r497