From 2dd2e62273983693076360e1bc4e59a0f9184c68 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 2 Dec 2012 15:11:42 -0800 Subject: [PATCH] Fix xpalloc confusion after memory is exhausted. * alloc.c (xpalloc): Comment fix. * charset.c (Fdefine_charset_internal): If xpalloc exhausts memory and signals an error, do not clear charset_table_size, as charset_table is still valid. * doprnt.c (evxprintf): Clear *BUF after freeing it. --- src/ChangeLog | 7 +++++++ src/alloc.c | 12 ++++++++---- src/charset.c | 4 +++- src/doprnt.c | 5 ++++- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 27453ab8a1..d5794b513e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,12 @@ 2012-12-02 Paul Eggert + Fix xpalloc confusion after memory is exhausted. + * alloc.c (xpalloc): Comment fix. + * charset.c (Fdefine_charset_internal): If xpalloc exhausts memory + and signals an error, do not clear charset_table_size, as + charset_table is still valid. + * doprnt.c (evxprintf): Clear *BUF after freeing it. + Use execve to avoid need to munge environ (Bug#13054). * callproc.c (Fcall_process): * process.c (create_process): diff --git a/src/alloc.c b/src/alloc.c index 28c9b51dab..e504b3d93e 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -761,13 +761,17 @@ xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) infinity. If PA is null, then allocate a new array instead of reallocating - the old one. Thus, to grow an array A without saving its old - contents, invoke xfree (A) immediately followed by xgrowalloc (0, - &NITEMS, ...). + the old one. Block interrupt input as needed. If memory exhaustion occurs, set *NITEMS to zero if PA is null, and signal an error (i.e., do not - return). */ + return). + + Thus, to grow an array A without saving its old contents, do + { xfree (A); A = NULL; A = xpalloc (NULL, &AITEMS, ...); }. + The A = NULL avoids a dangling pointer if xpalloc exhausts memory + and signals an error, and later this code is reexecuted and + attempts to free A. */ void * xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, diff --git a/src/charset.c b/src/charset.c index c9133c780e..43be0e9c78 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1142,12 +1142,14 @@ usage: (define-charset-internal ...) */) example, the IDs are stuffed into struct coding_system.charbuf[i] entries, which are 'int'. */ int old_size = charset_table_size; + ptrdiff_t new_size = old_size; struct charset *new_table = - xpalloc (0, &charset_table_size, 1, + xpalloc (0, &new_size, 1, min (INT_MAX, MOST_POSITIVE_FIXNUM), sizeof *charset_table); memcpy (new_table, charset_table, old_size * sizeof *new_table); charset_table = new_table; + charset_table_size = new_size; /* FIXME: This leaks memory, as the old charset_table becomes unreachable. If the old charset table is charset_table_init then this leak is intentional; otherwise, it's unclear. diff --git a/src/doprnt.c b/src/doprnt.c index caa56d6ae8..8cab219aaf 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -521,7 +521,10 @@ evxprintf (char **buf, ptrdiff_t *bufsize, if (nbytes < *bufsize - 1) return nbytes; if (*buf != nonheapbuf) - xfree (*buf); + { + xfree (*buf); + *buf = NULL; + } *buf = xpalloc (NULL, bufsize, 1, bufsize_max, 1); } } -- 2.20.1