]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix bug uncovered by changing alloca to auto buffer.
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 7 Sep 2014 22:27:59 +0000 (15:27 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 7 Sep 2014 22:27:59 +0000 (15:27 -0700)
* 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
src/ChangeLog
src/coding.c
src/keyboard.c

index 88ab1eedca8592dfe01e13d2092163266cbe3a58..2654abd32d46eaadb915f05678b29660eab72ea7 100644 (file)
@@ -1,5 +1,15 @@
 2014-09-07  Paul Eggert  <eggert@cs.ucla.edu>
 
+       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.
index 84b774b4355d57c93861dd23c61af1282619de55..ed107a297baf08e3b7fcc05149f5ae6f813216c7 100644 (file)
@@ -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)
index eef0770684e378021520d22a46c7bd9a3f695a66..c435ba74faa146fd26bb8d87dab35e148d439515 100644 (file)
@@ -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)