Mercurial > cpython-lru_cache-weakref
diff Modules/_tkinter.c @ 85298:ee0bb673536c 2.7
Issue #17119: Fixed integer overflows when processing large Unicode strings
and tuples in the tkinter module.
| author | Serhiy Storchaka <storchaka@gmail.com> |
|---|---|
| date | Wed, 21 Aug 2013 21:46:12 +0300 |
| parents | f53cdd4e2689 |
| children | 2d96764a66fa |
line wrap: on
line diff
--- a/Modules/_tkinter.c Wed Aug 21 18:25:00 2013 +0200 +++ b/Modules/_tkinter.c Wed Aug 21 21:46:12 2013 +0300 @@ -47,6 +47,10 @@ #define PyBool_FromLong PyInt_FromLong #endif +#define CHECK_SIZE(size, elemsize) \ + ((size_t)(size) <= (size_t)INT_MAX && \ + (size_t)(size) <= UINT_MAX / (size_t)(elemsize)) + /* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately, making _tkinter correct for this API means to break earlier versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and @@ -378,7 +382,7 @@ char **argv = NULL; int fvStore[ARGSZ]; int *fv = NULL; - int argc = 0, fvc = 0, i; + Py_ssize_t argc = 0, fvc = 0, i; char *res = NULL; if (!(tmp = PyList_New(0))) @@ -400,8 +404,12 @@ argc = PyTuple_Size(args); if (argc > ARGSZ) { - argv = (char **)ckalloc(argc * sizeof(char *)); - fv = (int *)ckalloc(argc * sizeof(int)); + if (!CHECK_SIZE(argc, sizeof(char *))) { + PyErr_SetString(PyExc_OverflowError, "tuple is too long"); + goto finally; + } + argv = (char **)ckalloc((size_t)argc * sizeof(char *)); + fv = (int *)ckalloc((size_t)argc * sizeof(int)); if (argv == NULL || fv == NULL) { PyErr_NoMemory(); goto finally; @@ -983,12 +991,18 @@ else if (PyFloat_Check(value)) return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value)); else if (PyTuple_Check(value)) { - Tcl_Obj **argv = (Tcl_Obj**) - ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*)); - int i; + Tcl_Obj **argv; + Py_ssize_t size, i; + + size = PyTuple_Size(value); + if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) { + PyErr_SetString(PyExc_OverflowError, "tuple is too long"); + return NULL; + } + argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *)); if(!argv) return 0; - for(i=0;i<PyTuple_Size(value);i++) + for (i = 0; i < size; i++) argv[i] = AsObj(PyTuple_GetItem(value,i)); result = Tcl_NewListObj(PyTuple_Size(value), argv); ckfree(FREECAST argv); @@ -1003,7 +1017,12 @@ #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3 Tcl_UniChar *outbuf = NULL; Py_ssize_t i; - size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar); + size_t allocsize; + if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) { + PyErr_SetString(PyExc_OverflowError, "string is too long"); + return NULL; + } + allocsize = ((size_t)size) * sizeof(Tcl_UniChar); if (allocsize >= size) outbuf = (Tcl_UniChar*)ckalloc(allocsize); /* Else overflow occurred, and we take the next exit */ @@ -1198,7 +1217,7 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc) { Tcl_Obj **objv = objStore; - int objc = 0, i; + Py_ssize_t objc = 0, i; if (args == NULL) /* do nothing */; @@ -1213,7 +1232,11 @@ objc = PyTuple_Size(args); if (objc > ARGSZ) { - objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *)); + if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) { + PyErr_SetString(PyExc_OverflowError, "tuple is too long"); + return NULL; + } + objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *)); if (objv == NULL) { PyErr_NoMemory(); objc = 0;
