aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2011-05-30 09:47:35 -0700
committerPaul Eggert2011-05-30 09:47:35 -0700
commit531b01656f89e093b9fa35959fa41e534b025320 (patch)
tree190b5a279e0e8e0130b6ba070fa217ce1282e2f3
parentde677ace77fa48962be80b668662a7009498e5d6 (diff)
downloademacs-531b01656f89e093b9fa35959fa41e534b025320.tar.gz
emacs-531b01656f89e093b9fa35959fa41e534b025320.zip
[ChangeLog]
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.
-rw-r--r--ChangeLog8
-rw-r--r--lib/allocator.h9
-rw-r--r--lib/careadlinkat.c8
-rw-r--r--src/ChangeLog6
-rw-r--r--src/alloc.c78
-rw-r--r--src/buffer.c6
-rw-r--r--src/editfns.c2
-rw-r--r--src/lisp.h4
-rw-r--r--src/menu.c2
-rw-r--r--src/minibuf.c2
-rw-r--r--src/xterm.c2
11 files changed, 86 insertions, 41 deletions
diff --git a/ChangeLog b/ChangeLog
index 879ce2834e7..4ca48fa91c4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
12011-05-30 Paul Eggert <eggert@cs.ucla.edu>
2
3 Malloc failure behavior now depends on size of allocation.
4 * lib/allocator.h (struct allocator.die): New size arg.
5 * lib/careadlinkat.c (careadlinkat): Pass size to 'die' function.
6 If the actual problem is an ssize_t limitation, not a size_t or
7 malloc failure, fail with errno == ENAMETOOLONG instead of calling 'die'.
8
12011-05-29 Paul Eggert <eggert@cs.ucla.edu> 92011-05-29 Paul Eggert <eggert@cs.ucla.edu>
2 10
3 Adjust to recent gnulib change for @GUARD_PREFIX@. 11 Adjust to recent gnulib change for @GUARD_PREFIX@.
diff --git a/lib/allocator.h b/lib/allocator.h
index 953117da83f..b8de95c0f50 100644
--- a/lib/allocator.h
+++ b/lib/allocator.h
@@ -45,10 +45,11 @@ struct allocator
45 /* Call FREE to free memory, like 'free'. */ 45 /* Call FREE to free memory, like 'free'. */
46 void (*free) (void *); 46 void (*free) (void *);
47 47
48 /* If nonnull, call DIE if MALLOC or REALLOC fails. DIE should not 48 /* If nonnull, call DIE (SIZE) if MALLOC (SIZE) or REALLOC (...,
49 return. DIE can be used by code that detects memory overflow 49 SIZE) fails. DIE should not return. SIZE should equal SIZE_MAX
50 while calculating sizes to be passed to MALLOC or REALLOC. */ 50 if size_t overflow was detected while calculating sizes to be
51 void (*die) (void); 51 passed to MALLOC or REALLOC. */
52 void (*die) (size_t);
52}; 53};
53 54
54/* An allocator using the stdlib functions and a null DIE function. */ 55/* An allocator using the stdlib functions and a null DIE function. */
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c
index e2909c766d5..6e4aa1395ff 100644
--- a/lib/careadlinkat.c
+++ b/lib/careadlinkat.c
@@ -135,6 +135,7 @@ careadlinkat (int fd, char const *filename,
135 if (buf == stack_buf) 135 if (buf == stack_buf)
136 { 136 {
137 char *b = (char *) alloc->allocate (link_size); 137 char *b = (char *) alloc->allocate (link_size);
138 buf_size = link_size;
138 if (! b) 139 if (! b)
139 break; 140 break;
140 memcpy (b, buf, link_size); 141 memcpy (b, buf, link_size);
@@ -158,6 +159,11 @@ careadlinkat (int fd, char const *filename,
158 buf_size *= 2; 159 buf_size *= 2;
159 else if (buf_size < buf_size_max) 160 else if (buf_size < buf_size_max)
160 buf_size = buf_size_max; 161 buf_size = buf_size_max;
162 else if (buf_size_max < SIZE_MAX)
163 {
164 errno = ENAMETOOLONG;
165 return NULL;
166 }
161 else 167 else
162 break; 168 break;
163 buf = (char *) alloc->allocate (buf_size); 169 buf = (char *) alloc->allocate (buf_size);
@@ -165,7 +171,7 @@ careadlinkat (int fd, char const *filename,
165 while (buf); 171 while (buf);
166 172
167 if (alloc->die) 173 if (alloc->die)
168 alloc->die (); 174 alloc->die (buf_size);
169 errno = ENOMEM; 175 errno = ENOMEM;
170 return NULL; 176 return NULL;
171} 177}
diff --git a/src/ChangeLog b/src/ChangeLog
index 7b0c73adbc9..aa034b3493f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,11 @@
12011-05-30 Paul Eggert <eggert@cs.ucla.edu> 12011-05-30 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Malloc failure behavior now depends on size of allocation.
4 * alloc.c (buffer_memory_full, memory_full): New arg NBYTES.
5 * lisp.h: Change signatures accordingly.
6 * alloc.c, buffer.c, editfns.c, menu.c, minibuf.c, xterm.c:
7 All callers changed.
8
3 * gnutls.c: Use Emacs's memory allocators. 9 * gnutls.c: Use Emacs's memory allocators.
4 Without this change, the gnutls library would invoke malloc etc. 10 Without this change, the gnutls library would invoke malloc etc.
5 directly, which causes problems on non-SYNC_INPUT hosts, and which 11 directly, which causes problems on non-SYNC_INPUT hosts, and which
diff --git a/src/alloc.c b/src/alloc.c
index 8215cc53cd3..be045be2ab4 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -471,7 +471,7 @@ display_malloc_warning (void)
471/* Called if we can't allocate relocatable space for a buffer. */ 471/* Called if we can't allocate relocatable space for a buffer. */
472 472
473void 473void
474buffer_memory_full (void) 474buffer_memory_full (EMACS_INT nbytes)
475{ 475{
476 /* If buffers use the relocating allocator, no need to free 476 /* If buffers use the relocating allocator, no need to free
477 spare_memory, because we may have plenty of malloc space left 477 spare_memory, because we may have plenty of malloc space left
@@ -481,7 +481,7 @@ buffer_memory_full (void)
481 malloc. */ 481 malloc. */
482 482
483#ifndef REL_ALLOC 483#ifndef REL_ALLOC
484 memory_full (); 484 memory_full (nbytes);
485#endif 485#endif
486 486
487 /* This used to call error, but if we've run out of memory, we could 487 /* This used to call error, but if we've run out of memory, we could
@@ -677,7 +677,7 @@ xmalloc (size_t size)
677 MALLOC_UNBLOCK_INPUT; 677 MALLOC_UNBLOCK_INPUT;
678 678
679 if (!val && size) 679 if (!val && size)
680 memory_full (); 680 memory_full (size);
681 return val; 681 return val;
682} 682}
683 683
@@ -698,7 +698,8 @@ xrealloc (POINTER_TYPE *block, size_t size)
698 val = (POINTER_TYPE *) realloc (block, size); 698 val = (POINTER_TYPE *) realloc (block, size);
699 MALLOC_UNBLOCK_INPUT; 699 MALLOC_UNBLOCK_INPUT;
700 700
701 if (!val && size) memory_full (); 701 if (!val && size)
702 memory_full (size);
702 return val; 703 return val;
703} 704}
704 705
@@ -791,7 +792,7 @@ lisp_malloc (size_t nbytes, enum mem_type type)
791 792
792 MALLOC_UNBLOCK_INPUT; 793 MALLOC_UNBLOCK_INPUT;
793 if (!val && nbytes) 794 if (!val && nbytes)
794 memory_full (); 795 memory_full (nbytes);
795 return val; 796 return val;
796} 797}
797 798
@@ -938,7 +939,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
938 if (base == 0) 939 if (base == 0)
939 { 940 {
940 MALLOC_UNBLOCK_INPUT; 941 MALLOC_UNBLOCK_INPUT;
941 memory_full (); 942 memory_full (ABLOCKS_BYTES);
942 } 943 }
943 944
944 aligned = (base == abase); 945 aligned = (base == abase);
@@ -964,7 +965,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
964 lisp_malloc_loser = base; 965 lisp_malloc_loser = base;
965 free (base); 966 free (base);
966 MALLOC_UNBLOCK_INPUT; 967 MALLOC_UNBLOCK_INPUT;
967 memory_full (); 968 memory_full (SIZE_MAX);
968 } 969 }
969 } 970 }
970#endif 971#endif
@@ -3270,35 +3271,58 @@ make_event_array (register int nargs, Lisp_Object *args)
3270 ************************************************************************/ 3271 ************************************************************************/
3271 3272
3272 3273
3273/* Called if malloc returns zero. */ 3274/* Called if malloc (NBYTES) returns zero. If NBYTES == SIZE_MAX,
3275 there may have been size_t overflow so that malloc was never
3276 called, or perhaps malloc was invoked successfully but the
3277 resulting pointer had problems fitting into a tagged EMACS_INT. In
3278 either case this counts as memory being full even though malloc did
3279 not fail. */
3274 3280
3275void 3281void
3276memory_full (void) 3282memory_full (size_t nbytes)
3277{ 3283{
3278 int i; 3284 /* Do not go into hysterics merely because a large request failed. */
3285 int enough_free_memory = 0;
3286 if (SPARE_MEMORY < nbytes)
3287 {
3288 void *p = malloc (SPARE_MEMORY);
3289 if (p)
3290 {
3291 if (spare_memory[0])
3292 free (p);
3293 else
3294 spare_memory[0] = p;
3295 enough_free_memory = 1;
3296 }
3297 }
3279 3298
3280 Vmemory_full = Qt; 3299 if (! enough_free_memory)
3300 {
3301 int i;
3281 3302
3282 memory_full_cons_threshold = sizeof (struct cons_block); 3303 Vmemory_full = Qt;
3283 3304
3284 /* The first time we get here, free the spare memory. */ 3305 memory_full_cons_threshold = sizeof (struct cons_block);
3285 for (i = 0; i < sizeof (spare_memory) / sizeof (char *); i++) 3306
3286 if (spare_memory[i]) 3307 /* The first time we get here, free the spare memory. */
3287 { 3308 for (i = 0; i < sizeof (spare_memory) / sizeof (char *); i++)
3288 if (i == 0) 3309 if (spare_memory[i])
3289 free (spare_memory[i]); 3310 {
3290 else if (i >= 1 && i <= 4) 3311 if (i == 0)
3291 lisp_align_free (spare_memory[i]); 3312 free (spare_memory[i]);
3292 else 3313 else if (i >= 1 && i <= 4)
3293 lisp_free (spare_memory[i]); 3314 lisp_align_free (spare_memory[i]);
3294 spare_memory[i] = 0; 3315 else
3295 } 3316 lisp_free (spare_memory[i]);
3317 spare_memory[i] = 0;
3318 }
3296 3319
3297 /* Record the space now used. When it decreases substantially, 3320 /* Record the space now used. When it decreases substantially,
3298 we can refill the memory reserve. */ 3321 we can refill the memory reserve. */
3299#if !defined SYSTEM_MALLOC && !defined SYNC_INPUT 3322#if !defined SYSTEM_MALLOC && !defined SYNC_INPUT
3300 bytes_used_when_full = BYTES_USED; 3323 bytes_used_when_full = BYTES_USED;
3301#endif 3324#endif
3325 }
3302 3326
3303 /* This used to call error, but if we've run out of memory, we could 3327 /* This used to call error, but if we've run out of memory, we could
3304 get infinite recursion trying to build the string. */ 3328 get infinite recursion trying to build the string. */
diff --git a/src/buffer.c b/src/buffer.c
index 05bd129976f..e9ff8f492ba 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -328,7 +328,7 @@ even if it is dead. The return value is never nil. */)
328 alloc_buffer_text (b, BUF_GAP_SIZE (b) + 1); 328 alloc_buffer_text (b, BUF_GAP_SIZE (b) + 1);
329 UNBLOCK_INPUT; 329 UNBLOCK_INPUT;
330 if (! BUF_BEG_ADDR (b)) 330 if (! BUF_BEG_ADDR (b))
331 buffer_memory_full (); 331 buffer_memory_full (BUF_GAP_SIZE (b) + 1);
332 332
333 b->pt = BEG; 333 b->pt = BEG;
334 b->begv = BEG; 334 b->begv = BEG;
@@ -4892,7 +4892,7 @@ alloc_buffer_text (struct buffer *b, size_t nbytes)
4892 if (p == NULL) 4892 if (p == NULL)
4893 { 4893 {
4894 UNBLOCK_INPUT; 4894 UNBLOCK_INPUT;
4895 memory_full (); 4895 memory_full (nbytes);
4896 } 4896 }
4897 4897
4898 b->text->beg = (unsigned char *) p; 4898 b->text->beg = (unsigned char *) p;
@@ -4920,7 +4920,7 @@ enlarge_buffer_text (struct buffer *b, EMACS_INT delta)
4920 if (p == NULL) 4920 if (p == NULL)
4921 { 4921 {
4922 UNBLOCK_INPUT; 4922 UNBLOCK_INPUT;
4923 memory_full (); 4923 memory_full (nbytes);
4924 } 4924 }
4925 4925
4926 BUF_BEG_ADDR (b) = (unsigned char *) p; 4926 BUF_BEG_ADDR (b) = (unsigned char *) p;
diff --git a/src/editfns.c b/src/editfns.c
index 8b48355fbfa..0e40fde9ca4 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3636,7 +3636,7 @@ usage: (format STRING &rest OBJECTS) */)
3636 { 3636 {
3637 EMACS_INT i; 3637 EMACS_INT i;
3638 if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs) 3638 if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs)
3639 memory_full (); 3639 memory_full (SIZE_MAX);
3640 SAFE_ALLOCA (info, struct info *, (nargs + 1) * sizeof *info + formatlen); 3640 SAFE_ALLOCA (info, struct info *, (nargs + 1) * sizeof *info + formatlen);
3641 discarded = (char *) &info[nargs + 1]; 3641 discarded = (char *) &info[nargs + 1];
3642 for (i = 0; i < nargs + 1; i++) 3642 for (i = 0; i < nargs + 1; i++)
diff --git a/src/lisp.h b/src/lisp.h
index 26d09c6d555..ceaf7f49eb2 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2685,8 +2685,8 @@ extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
2685extern void reset_malloc_hooks (void); 2685extern void reset_malloc_hooks (void);
2686extern void uninterrupt_malloc (void); 2686extern void uninterrupt_malloc (void);
2687extern void malloc_warning (const char *); 2687extern void malloc_warning (const char *);
2688extern void memory_full (void) NO_RETURN; 2688extern void memory_full (size_t) NO_RETURN;
2689extern void buffer_memory_full (void) NO_RETURN; 2689extern void buffer_memory_full (EMACS_INT) NO_RETURN;
2690extern int survives_gc_p (Lisp_Object); 2690extern int survives_gc_p (Lisp_Object);
2691extern void mark_object (Lisp_Object); 2691extern void mark_object (Lisp_Object);
2692#if defined REL_ALLOC && !defined SYSTEM_MALLOC 2692#if defined REL_ALLOC && !defined SYSTEM_MALLOC
diff --git a/src/menu.c b/src/menu.c
index e4338f349f6..7eda4c6ebb5 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -178,7 +178,7 @@ static void
178grow_menu_items (void) 178grow_menu_items (void)
179{ 179{
180 if ((INT_MAX - MENU_ITEMS_PANE_LENGTH) / 2 < menu_items_allocated) 180 if ((INT_MAX - MENU_ITEMS_PANE_LENGTH) / 2 < menu_items_allocated)
181 memory_full (); 181 memory_full (SIZE_MAX);
182 menu_items_allocated *= 2; 182 menu_items_allocated *= 2;
183 menu_items = larger_vector (menu_items, menu_items_allocated, Qnil); 183 menu_items = larger_vector (menu_items, menu_items_allocated, Qnil);
184} 184}
diff --git a/src/minibuf.c b/src/minibuf.c
index 3f8bd835211..fd51b0a2358 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -245,7 +245,7 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial,
245 len == size - 1 && line[len - 1] != '\n')) 245 len == size - 1 && line[len - 1] != '\n'))
246 { 246 {
247 if ((size_t) -1 / 2 < size) 247 if ((size_t) -1 / 2 < size)
248 memory_full (); 248 memory_full (SIZE_MAX);
249 size *= 2; 249 size *= 2;
250 line = (char *) xrealloc (line, size); 250 line = (char *) xrealloc (line, size);
251 } 251 }
diff --git a/src/xterm.c b/src/xterm.c
index 3b8112d972b..56d2ce0e9e5 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -4225,7 +4225,7 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
4225 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows; 4225 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
4226 4226
4227 if ((size_t) -1 / sizeof *scroll_bar_windows < new_size) 4227 if ((size_t) -1 / sizeof *scroll_bar_windows < new_size)
4228 memory_full (); 4228 memory_full (SIZE_MAX);
4229 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows, 4229 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
4230 nbytes); 4230 nbytes);
4231 memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes); 4231 memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes);