]> code.delx.au - gnu-emacs/commitdiff
[ChangeLog]
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 30 May 2011 16:47:35 +0000 (09:47 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 30 May 2011 16:47:35 +0000 (09:47 -0700)
Malloc failure behavior now depends on size of allocation.
* lib/allocator.h (struct allocator.die): New size arg.
* lib/careadlinkat.c (careadlinkat): Pass size to 'die' function.
If the actual problem is an ssize_t limitation, not a size_t or
malloc failure, fail with errno == ENAMETOOLONG instead of calling 'die'.
[src/ChangeLog]
Malloc failure behavior now depends on size of allocation.
* alloc.c (buffer_memory_full, memory_full): New arg NBYTES.
* lisp.h: Change signatures accordingly.
* alloc.c, buffer.c, editfns.c, menu.c, minibuf.c, xterm.c:
All callers changed.

ChangeLog
lib/allocator.h
lib/careadlinkat.c
src/ChangeLog
src/alloc.c
src/buffer.c
src/editfns.c
src/lisp.h
src/menu.c
src/minibuf.c
src/xterm.c

index 879ce2834e7f28c8bb995b1a233931cde308bf44..4ca48fa91c472497f8b968f4895e60552b69e1f5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-05-30  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Malloc failure behavior now depends on size of allocation.
+       * lib/allocator.h (struct allocator.die): New size arg.
+       * lib/careadlinkat.c (careadlinkat): Pass size to 'die' function.
+       If the actual problem is an ssize_t limitation, not a size_t or
+       malloc failure, fail with errno == ENAMETOOLONG instead of calling 'die'.
+
 2011-05-29  Paul Eggert  <eggert@cs.ucla.edu>
 
        Adjust to recent gnulib change for @GUARD_PREFIX@.
index 953117da83f55609da58fffef4c6b012909bfa89..b8de95c0f50c8d79dbb466ff0ea5e24a3e87b58e 100644 (file)
@@ -45,10 +45,11 @@ struct allocator
   /* Call FREE to free memory, like 'free'.  */
   void (*free) (void *);
 
-  /* If nonnull, call DIE if MALLOC or REALLOC fails.  DIE should not
-     return.  DIE can be used by code that detects memory overflow
-     while calculating sizes to be passed to MALLOC or REALLOC.  */
-  void (*die) (void);
+  /* If nonnull, call DIE (SIZE) if MALLOC (SIZE) or REALLOC (...,
+     SIZE) fails.  DIE should not return.  SIZE should equal SIZE_MAX
+     if size_t overflow was detected while calculating sizes to be
+     passed to MALLOC or REALLOC.  */
+  void (*die) (size_t);
 };
 
 /* An allocator using the stdlib functions and a null DIE function.  */
index e2909c766d5f1969d42b415499f90139e8d9f7aa..6e4aa1395ff06057f4352865248b688d65dc6ccf 100644 (file)
@@ -135,6 +135,7 @@ careadlinkat (int fd, char const *filename,
           if (buf == stack_buf)
             {
               char *b = (char *) alloc->allocate (link_size);
+              buf_size = link_size;
               if (! b)
                 break;
               memcpy (b, buf, link_size);
@@ -158,6 +159,11 @@ careadlinkat (int fd, char const *filename,
         buf_size *= 2;
       else if (buf_size < buf_size_max)
         buf_size = buf_size_max;
+      else if (buf_size_max < SIZE_MAX)
+        {
+          errno = ENAMETOOLONG;
+          return NULL;
+        }
       else
         break;
       buf = (char *) alloc->allocate (buf_size);
@@ -165,7 +171,7 @@ careadlinkat (int fd, char const *filename,
   while (buf);
 
   if (alloc->die)
-    alloc->die ();
+    alloc->die (buf_size);
   errno = ENOMEM;
   return NULL;
 }
index 7b0c73adbc914df020b50c240c7ac8a326abf326..aa034b3493f81492e7580cb52535799a8f73ef3b 100644 (file)
@@ -1,5 +1,11 @@
 2011-05-30  Paul Eggert  <eggert@cs.ucla.edu>
 
+       Malloc failure behavior now depends on size of allocation.
+       * alloc.c (buffer_memory_full, memory_full): New arg NBYTES.
+       * lisp.h: Change signatures accordingly.
+       * alloc.c, buffer.c, editfns.c, menu.c, minibuf.c, xterm.c:
+       All callers changed.
+
        * gnutls.c: Use Emacs's memory allocators.
        Without this change, the gnutls library would invoke malloc etc.
        directly, which causes problems on non-SYNC_INPUT hosts, and which
index 8215cc53cd31659951b644987eb5505e0f5a73e7..be045be2ab42fca3acfe61f9119a619855c37c0f 100644 (file)
@@ -471,7 +471,7 @@ display_malloc_warning (void)
 /* Called if we can't allocate relocatable space for a buffer.  */
 
 void
-buffer_memory_full (void)
+buffer_memory_full (EMACS_INT nbytes)
 {
   /* If buffers use the relocating allocator, no need to free
      spare_memory, because we may have plenty of malloc space left
@@ -481,7 +481,7 @@ buffer_memory_full (void)
      malloc.  */
 
 #ifndef REL_ALLOC
-  memory_full ();
+  memory_full (nbytes);
 #endif
 
   /* This used to call error, but if we've run out of memory, we could
@@ -677,7 +677,7 @@ xmalloc (size_t size)
   MALLOC_UNBLOCK_INPUT;
 
   if (!val && size)
-    memory_full ();
+    memory_full (size);
   return val;
 }
 
@@ -698,7 +698,8 @@ xrealloc (POINTER_TYPE *block, size_t size)
     val = (POINTER_TYPE *) realloc (block, size);
   MALLOC_UNBLOCK_INPUT;
 
-  if (!val && size) memory_full ();
+  if (!val && size)
+    memory_full (size);
   return val;
 }
 
@@ -791,7 +792,7 @@ lisp_malloc (size_t nbytes, enum mem_type type)
 
   MALLOC_UNBLOCK_INPUT;
   if (!val && nbytes)
-    memory_full ();
+    memory_full (nbytes);
   return val;
 }
 
@@ -938,7 +939,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
       if (base == 0)
        {
          MALLOC_UNBLOCK_INPUT;
-         memory_full ();
+         memory_full (ABLOCKS_BYTES);
        }
 
       aligned = (base == abase);
@@ -964,7 +965,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
              lisp_malloc_loser = base;
              free (base);
              MALLOC_UNBLOCK_INPUT;
-             memory_full ();
+             memory_full (SIZE_MAX);
            }
        }
 #endif
@@ -3270,35 +3271,58 @@ make_event_array (register int nargs, Lisp_Object *args)
  ************************************************************************/
 
 
-/* Called if malloc returns zero.  */
+/* Called if malloc (NBYTES) returns zero.  If NBYTES == SIZE_MAX,
+   there may have been size_t overflow so that malloc was never
+   called, or perhaps malloc was invoked successfully but the
+   resulting pointer had problems fitting into a tagged EMACS_INT.  In
+   either case this counts as memory being full even though malloc did
+   not fail.  */
 
 void
-memory_full (void)
+memory_full (size_t nbytes)
 {
-  int i;
+  /* Do not go into hysterics merely because a large request failed.  */
+  int enough_free_memory = 0;
+  if (SPARE_MEMORY < nbytes)
+    {
+      void *p = malloc (SPARE_MEMORY);
+      if (p)
+       {
+         if (spare_memory[0])
+           free (p);
+         else
+           spare_memory[0] = p;
+         enough_free_memory = 1;
+       }
+    }
 
-  Vmemory_full = Qt;
+  if (! enough_free_memory)
+    {
+      int i;
 
-  memory_full_cons_threshold = sizeof (struct cons_block);
+      Vmemory_full = Qt;
 
-  /* The first time we get here, free the spare memory.  */
-  for (i = 0; i < sizeof (spare_memory) / sizeof (char *); i++)
-    if (spare_memory[i])
-      {
-       if (i == 0)
-         free (spare_memory[i]);
-       else if (i >= 1 && i <= 4)
-         lisp_align_free (spare_memory[i]);
-       else
-         lisp_free (spare_memory[i]);
-       spare_memory[i] = 0;
-      }
+      memory_full_cons_threshold = sizeof (struct cons_block);
+
+      /* The first time we get here, free the spare memory.  */
+      for (i = 0; i < sizeof (spare_memory) / sizeof (char *); i++)
+       if (spare_memory[i])
+         {
+           if (i == 0)
+             free (spare_memory[i]);
+           else if (i >= 1 && i <= 4)
+             lisp_align_free (spare_memory[i]);
+           else
+             lisp_free (spare_memory[i]);
+           spare_memory[i] = 0;
+         }
 
-  /* Record the space now used.  When it decreases substantially,
-     we can refill the memory reserve.  */
+      /* Record the space now used.  When it decreases substantially,
+        we can refill the memory reserve.  */
 #if !defined SYSTEM_MALLOC && !defined SYNC_INPUT
-  bytes_used_when_full = BYTES_USED;
+      bytes_used_when_full = BYTES_USED;
 #endif
+    }
 
   /* This used to call error, but if we've run out of memory, we could
      get infinite recursion trying to build the string.  */
index 05bd129976fd905e33a4fb29cf40c72fe66879f6..e9ff8f492bacaa490375ded4d226d27cff7e419f 100644 (file)
@@ -328,7 +328,7 @@ even if it is dead.  The return value is never nil.  */)
   alloc_buffer_text (b, BUF_GAP_SIZE (b) + 1);
   UNBLOCK_INPUT;
   if (! BUF_BEG_ADDR (b))
-    buffer_memory_full ();
+    buffer_memory_full (BUF_GAP_SIZE (b) + 1);
 
   b->pt = BEG;
   b->begv = BEG;
@@ -4892,7 +4892,7 @@ alloc_buffer_text (struct buffer *b, size_t nbytes)
   if (p == NULL)
     {
       UNBLOCK_INPUT;
-      memory_full ();
+      memory_full (nbytes);
     }
 
   b->text->beg = (unsigned char *) p;
@@ -4920,7 +4920,7 @@ enlarge_buffer_text (struct buffer *b, EMACS_INT delta)
   if (p == NULL)
     {
       UNBLOCK_INPUT;
-      memory_full ();
+      memory_full (nbytes);
     }
 
   BUF_BEG_ADDR (b) = (unsigned char *) p;
index 8b48355fbfae80ca22c2976b93e762f6f735efd8..0e40fde9ca4cb21707502ac03ed12f9d606f2a66 100644 (file)
@@ -3636,7 +3636,7 @@ usage: (format STRING &rest OBJECTS)  */)
   {
     EMACS_INT i;
     if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs)
-      memory_full ();
+      memory_full (SIZE_MAX);
     SAFE_ALLOCA (info, struct info *, (nargs + 1) * sizeof *info + formatlen);
     discarded = (char *) &info[nargs + 1];
     for (i = 0; i < nargs + 1; i++)
index 26d09c6d555057da3832341c3a71c4662be1e41f..ceaf7f49eb2c564065a608bfb95c7c9178edd77e 100644 (file)
@@ -2685,8 +2685,8 @@ extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
 extern void reset_malloc_hooks (void);
 extern void uninterrupt_malloc (void);
 extern void malloc_warning (const char *);
-extern void memory_full (void) NO_RETURN;
-extern void buffer_memory_full (void) NO_RETURN;
+extern void memory_full (size_t) NO_RETURN;
+extern void buffer_memory_full (EMACS_INT) NO_RETURN;
 extern int survives_gc_p (Lisp_Object);
 extern void mark_object (Lisp_Object);
 #if defined REL_ALLOC && !defined SYSTEM_MALLOC
index e4338f349f6cb094000f7f36349cf50bce7de34e..7eda4c6ebb5aad78ba4ce108d9818a9f08708a28 100644 (file)
@@ -178,7 +178,7 @@ static void
 grow_menu_items (void)
 {
   if ((INT_MAX - MENU_ITEMS_PANE_LENGTH) / 2 < menu_items_allocated)
-    memory_full ();
+    memory_full (SIZE_MAX);
   menu_items_allocated *= 2;
   menu_items = larger_vector (menu_items, menu_items_allocated, Qnil);
 }
index 3f8bd8352111e63439f50854338d5797852e700c..fd51b0a23587c7113fd0d6f3d98b5fd820d2abc3 100644 (file)
@@ -245,7 +245,7 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial,
             len == size - 1 && line[len - 1] != '\n'))
     {
       if ((size_t) -1 / 2 < size)
-       memory_full ();
+       memory_full (SIZE_MAX);
       size *= 2;
       line = (char *) xrealloc (line, size);
     }
index 3b8112d972be6d0dea12e54e0defc2bca6e0d6d1..56d2ce0e9e51489feceb069bfb4f72140c1d83f9 100644 (file)
@@ -4225,7 +4225,7 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
       size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
 
       if ((size_t) -1 / sizeof *scroll_bar_windows < new_size)
-       memory_full ();
+       memory_full (SIZE_MAX);
       scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
                                                        nbytes);
       memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes);