From: Paul Eggert Date: Sun, 7 Sep 2014 22:27:59 +0000 (-0700) Subject: Fix bug uncovered by changing alloca to auto buffer. X-Git-Tag: emacs-25.0.90~2635^2~679^2~333 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=4612d1eab721a1010312382d1048c8b3a67b18fa;p=emacs.git Fix bug uncovered by changing alloca to auto buffer. * coding.c (growable_destination): New function. (produce_chars): Use it for sanity checks. Do not fiddle with dst_end if the source and destination are both nil, as it's the caller's responsibility to avoid overlap. * keyboard.c (read_decoded_event_from_main_queue): The destination must be MAX_MULTIBYTE_LENGTH times the max source length, not 4 times, to prevent decode_coding_c_string from trying to reallocate a destination. This removes the need for the FIXME. Fixes: debbugs:18410 --- diff --git a/src/ChangeLog b/src/ChangeLog index 88ab1eedca8..2654abd32d4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,15 @@ 2014-09-07 Paul Eggert + Fix bug uncovered by changing alloca to auto buffer (Bug#18410). + * coding.c (growable_destination): New function. + (produce_chars): Use it for sanity checks. Do not fiddle with + dst_end if the source and destination are both nil, as it's + the caller's responsibility to avoid overlap. + * keyboard.c (read_decoded_event_from_main_queue): + The destination must be MAX_MULTIBYTE_LENGTH times the max source + length, not 4 times, to prevent decode_coding_c_string from trying + to reallocate a destination. This removes the need for the FIXME. + * callproc.c (exec_failed) [DOS_NT]: Define a dummy. All callers simplified. Add a comment about exec_failed, vfork, and alloca. diff --git a/src/coding.c b/src/coding.c index 84b774b4355..ed107a297ba 100644 --- a/src/coding.c +++ b/src/coding.c @@ -690,6 +690,14 @@ CHECK_NATNUM_CDR (Lisp_Object x) XSETCDR (x, tmp); } +/* True if CODING's destination can be grown. */ + +static bool +growable_destination (struct coding_system *coding) +{ + return STRINGP (coding->dst_object) || BUFFERP (coding->dst_object); +} + /* Safely get one byte from the source text pointed by SRC which ends at SRC_END, and set C to that byte. If there are not enough bytes @@ -7019,8 +7027,10 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, int *buf = coding->charbuf; int *buf_end = buf + coding->charbuf_used; - if (EQ (coding->src_object, coding->dst_object)) + if (EQ (coding->src_object, coding->dst_object) + && ! NILP (coding->dst_object)) { + eassert (growable_destination (coding)); coding_set_source (coding); dst_end = ((unsigned char *) coding->source) + coding->consumed; } @@ -7059,6 +7069,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, if ((dst_end - dst) / MAX_MULTIBYTE_LENGTH < to_nchars) { + eassert (growable_destination (coding)); if (((min (PTRDIFF_MAX, SIZE_MAX) - (buf_end - buf)) / MAX_MULTIBYTE_LENGTH) < to_nchars) @@ -7103,7 +7114,10 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, const unsigned char *src_end = src + coding->consumed; if (EQ (coding->dst_object, coding->src_object)) - dst_end = (unsigned char *) src; + { + eassert (growable_destination (coding)); + dst_end = (unsigned char *) src; + } if (coding->src_multibyte != coding->dst_multibyte) { if (coding->src_multibyte) @@ -7119,6 +7133,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, ONE_MORE_BYTE (c); if (dst == dst_end) { + eassert (growable_destination (coding)); if (EQ (coding->src_object, coding->dst_object)) dst_end = (unsigned char *) src; if (dst == dst_end) @@ -7149,6 +7164,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, if (dst >= dst_end - 1) { + eassert (growable_destination (coding)); if (EQ (coding->src_object, coding->dst_object)) dst_end = (unsigned char *) src; if (dst >= dst_end - 1) diff --git a/src/keyboard.c b/src/keyboard.c index eef0770684e..c435ba74faa 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -2355,22 +2355,15 @@ read_decoded_event_from_main_queue (struct timespec *end_time, struct coding_system *coding = TERMINAL_KEYBOARD_CODING (terminal); unsigned char src[MAX_ENCODED_BYTES]; - unsigned char dest[4 * sizeof src]; + unsigned char dest[MAX_ENCODED_BYTES * MAX_MULTIBYTE_LENGTH]; int i; for (i = 0; i < n; i++) src[i] = XINT (events[i]); if (meta_key != 2) for (i = 0; i < n; i++) src[i] &= ~0x80; - - /* FIXME: For some reason decode_coding_c_string requires a - fresh output buffer each time, and reusing the old buffer can - make Emacs dump core. Avoid triggering the problem for now - by allocating a new buffer each time through the loop. */ - bool please_fixme = true; - coding->destination = please_fixme ? alloca (n * 4) : dest; - - coding->dst_bytes = n * 4; + coding->destination = dest; + coding->dst_bytes = sizeof dest; decode_coding_c_string (coding, src, n, Qnil); eassert (coding->produced_char <= n); if (coding->produced_char == 0)