summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog7
-rw-r--r--src/alloc.c12
-rw-r--r--src/charset.c4
-rw-r--r--src/doprnt.c5
4 files changed, 22 insertions, 6 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 27453ab8a16..d5794b513e6 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,12 @@
2012-12-02 Paul Eggert <eggert@cs.ucla.edu>
+ 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 28c9b51dab4..e504b3d93ec 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 c9133c780e8..43be0e9c780 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 caa56d6ae88..8cab219aafa 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);
}
}