]> granicus.if.org Git - python/commitdiff
Issue #21951: Use attemptckalloc() instead of ckalloc() in Tkinter.
authorSerhiy Storchaka <storchaka@gmail.com>
Thu, 11 Sep 2014 07:38:08 +0000 (10:38 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Thu, 11 Sep 2014 07:38:08 +0000 (10:38 +0300)
ckalloc() causes the Tcl interpreter to panic, attemptckalloc() returns NULL
if the memory allocation fails.

Misc/NEWS
Modules/_tkinter.c

index 6e7ed3ab111e09d16cab2fc63603b30daf025bab..9e5e681a55133be0ae3bd368b017d0cefaa58738 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -22,6 +22,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #21951: Tkinter now most likely raises MemoryError instead of crash
+  if the memory allocation fails.
+
 - Issue #22226: First letter no longer is stripped from the "status" key in
   the result of Treeview.heading().
 
index fe35882a73d514401307c52ba892b3af91bbfa68..d0a4464716b838b9c9854ac06730ec9b90d60ce5 100644 (file)
@@ -408,8 +408,8 @@ Merge(PyObject *args)
                 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));
+            argv = (char **)attemptckalloc((size_t)argc * sizeof(char *));
+            fv = (int *)attemptckalloc((size_t)argc * sizeof(int));
             if (argv == NULL || fv == NULL) {
                 PyErr_NoMemory();
                 goto finally;
@@ -754,7 +754,7 @@ Tkapp_New(char *screenName, char *baseName, char *className,
         Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
 
     /* This is used to get the application class for Tk 4.1 and up */
-    argv0 = (char*)ckalloc(strlen(className) + 1);
+    argv0 = (char*)attemptckalloc(strlen(className) + 1);
     if (!argv0) {
         PyErr_NoMemory();
         Py_DECREF(v);
@@ -788,7 +788,7 @@ Tkapp_New(char *screenName, char *baseName, char *className,
         if (use)
             len += strlen(use) + sizeof "-use ";
 
-        args = (char*)ckalloc(len);
+        args = (char*)attemptckalloc(len);
         if (!args) {
             PyErr_NoMemory();
             Py_DECREF(v);
@@ -1056,7 +1056,7 @@ AsObj(PyObject *value)
             PyErr_SetString(PyExc_OverflowError, "tuple is too long");
             return NULL;
         }
-        argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
+        argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
         if(!argv)
           return 0;
         for (i = 0; i < size; i++)
@@ -1083,7 +1083,7 @@ AsObj(PyObject *value)
             return Tcl_NewUnicodeObj(inbuf, size);
         allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
         if (allocsize >= size)
-            outbuf = (Tcl_UniChar*)ckalloc(allocsize);
+            outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
         /* Else overflow occurred, and we take the next exit */
         if (!outbuf) {
             PyErr_NoMemory();
@@ -1272,7 +1272,7 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
                 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
                 return NULL;
             }
-            objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
+            objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
             if (objv == NULL) {
                 PyErr_NoMemory();
                 objc = 0;
@@ -1410,7 +1410,11 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
         PyObject *exc_type, *exc_value, *exc_tb;
         if (!WaitForMainloop(self))
             return NULL;
-        ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
+        ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
+        if (ev == NULL) {
+            PyErr_NoMemory();
+            return NULL;
+        }
         ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
         ev->self = self;
         ev->args = args;
@@ -1700,8 +1704,11 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
         if (!WaitForMainloop(self))
             return NULL;
 
-        ev = (VarEvent*)ckalloc(sizeof(VarEvent));
-
+        ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
+        if (ev == NULL) {
+            PyErr_NoMemory();
+            return NULL;
+        }
         ev->self = selfptr;
         ev->args = args;
         ev->flags = flags;
@@ -2312,7 +2319,12 @@ Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
 #ifdef WITH_THREAD
     if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
         Tcl_Condition cond = NULL;
-        CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
+        CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
+        if (ev == NULL) {
+            PyErr_NoMemory();
+            PyMem_DEL(data);
+            return NULL;
+        }
         ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
         ev->interp = self->interp;
         ev->create = 1;
@@ -2359,7 +2371,11 @@ Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
     if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
         Tcl_Condition cond = NULL;
         CommandEvent *ev;
-        ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
+        ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
+        if (ev == NULL) {
+            PyErr_NoMemory();
+            return NULL;
+        }
         ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
         ev->interp = self->interp;
         ev->create = 0;