diff options
| author | Paul Eggert | 2014-09-07 15:27:59 -0700 |
|---|---|---|
| committer | Paul Eggert | 2014-09-07 15:27:59 -0700 |
| commit | 4612d1eab721a1010312382d1048c8b3a67b18fa (patch) | |
| tree | e0c89c15723fce2430853d3eddb9535ce0ad9e38 /src | |
| parent | d5e25ad17f871ed7837fcc5277efce762c112f2a (diff) | |
| download | emacs-4612d1eab721a1010312382d1048c8b3a67b18fa.tar.gz emacs-4612d1eab721a1010312382d1048c8b3a67b18fa.zip | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 10 | ||||
| -rw-r--r-- | src/coding.c | 20 | ||||
| -rw-r--r-- | src/keyboard.c | 13 |
3 files changed, 31 insertions, 12 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 88ab1eedca8..2654abd32d4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,15 @@ | |||
| 1 | 2014-09-07 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2014-09-07 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Fix bug uncovered by changing alloca to auto buffer (Bug#18410). | ||
| 4 | * coding.c (growable_destination): New function. | ||
| 5 | (produce_chars): Use it for sanity checks. Do not fiddle with | ||
| 6 | dst_end if the source and destination are both nil, as it's | ||
| 7 | the caller's responsibility to avoid overlap. | ||
| 8 | * keyboard.c (read_decoded_event_from_main_queue): | ||
| 9 | The destination must be MAX_MULTIBYTE_LENGTH times the max source | ||
| 10 | length, not 4 times, to prevent decode_coding_c_string from trying | ||
| 11 | to reallocate a destination. This removes the need for the FIXME. | ||
| 12 | |||
| 3 | * callproc.c (exec_failed) [DOS_NT]: Define a dummy. | 13 | * callproc.c (exec_failed) [DOS_NT]: Define a dummy. |
| 4 | All callers simplified. Add a comment about exec_failed, vfork, | 14 | All callers simplified. Add a comment about exec_failed, vfork, |
| 5 | and alloca. | 15 | 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) | |||
| 690 | XSETCDR (x, tmp); | 690 | XSETCDR (x, tmp); |
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | /* True if CODING's destination can be grown. */ | ||
| 694 | |||
| 695 | static bool | ||
| 696 | growable_destination (struct coding_system *coding) | ||
| 697 | { | ||
| 698 | return STRINGP (coding->dst_object) || BUFFERP (coding->dst_object); | ||
| 699 | } | ||
| 700 | |||
| 693 | 701 | ||
| 694 | /* Safely get one byte from the source text pointed by SRC which ends | 702 | /* Safely get one byte from the source text pointed by SRC which ends |
| 695 | at SRC_END, and set C to that byte. If there are not enough bytes | 703 | 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, | |||
| 7019 | int *buf = coding->charbuf; | 7027 | int *buf = coding->charbuf; |
| 7020 | int *buf_end = buf + coding->charbuf_used; | 7028 | int *buf_end = buf + coding->charbuf_used; |
| 7021 | 7029 | ||
| 7022 | if (EQ (coding->src_object, coding->dst_object)) | 7030 | if (EQ (coding->src_object, coding->dst_object) |
| 7031 | && ! NILP (coding->dst_object)) | ||
| 7023 | { | 7032 | { |
| 7033 | eassert (growable_destination (coding)); | ||
| 7024 | coding_set_source (coding); | 7034 | coding_set_source (coding); |
| 7025 | dst_end = ((unsigned char *) coding->source) + coding->consumed; | 7035 | dst_end = ((unsigned char *) coding->source) + coding->consumed; |
| 7026 | } | 7036 | } |
| @@ -7059,6 +7069,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, | |||
| 7059 | 7069 | ||
| 7060 | if ((dst_end - dst) / MAX_MULTIBYTE_LENGTH < to_nchars) | 7070 | if ((dst_end - dst) / MAX_MULTIBYTE_LENGTH < to_nchars) |
| 7061 | { | 7071 | { |
| 7072 | eassert (growable_destination (coding)); | ||
| 7062 | if (((min (PTRDIFF_MAX, SIZE_MAX) - (buf_end - buf)) | 7073 | if (((min (PTRDIFF_MAX, SIZE_MAX) - (buf_end - buf)) |
| 7063 | / MAX_MULTIBYTE_LENGTH) | 7074 | / MAX_MULTIBYTE_LENGTH) |
| 7064 | < to_nchars) | 7075 | < to_nchars) |
| @@ -7103,7 +7114,10 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, | |||
| 7103 | const unsigned char *src_end = src + coding->consumed; | 7114 | const unsigned char *src_end = src + coding->consumed; |
| 7104 | 7115 | ||
| 7105 | if (EQ (coding->dst_object, coding->src_object)) | 7116 | if (EQ (coding->dst_object, coding->src_object)) |
| 7106 | dst_end = (unsigned char *) src; | 7117 | { |
| 7118 | eassert (growable_destination (coding)); | ||
| 7119 | dst_end = (unsigned char *) src; | ||
| 7120 | } | ||
| 7107 | if (coding->src_multibyte != coding->dst_multibyte) | 7121 | if (coding->src_multibyte != coding->dst_multibyte) |
| 7108 | { | 7122 | { |
| 7109 | if (coding->src_multibyte) | 7123 | if (coding->src_multibyte) |
| @@ -7119,6 +7133,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, | |||
| 7119 | ONE_MORE_BYTE (c); | 7133 | ONE_MORE_BYTE (c); |
| 7120 | if (dst == dst_end) | 7134 | if (dst == dst_end) |
| 7121 | { | 7135 | { |
| 7136 | eassert (growable_destination (coding)); | ||
| 7122 | if (EQ (coding->src_object, coding->dst_object)) | 7137 | if (EQ (coding->src_object, coding->dst_object)) |
| 7123 | dst_end = (unsigned char *) src; | 7138 | dst_end = (unsigned char *) src; |
| 7124 | if (dst == dst_end) | 7139 | if (dst == dst_end) |
| @@ -7149,6 +7164,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, | |||
| 7149 | 7164 | ||
| 7150 | if (dst >= dst_end - 1) | 7165 | if (dst >= dst_end - 1) |
| 7151 | { | 7166 | { |
| 7167 | eassert (growable_destination (coding)); | ||
| 7152 | if (EQ (coding->src_object, coding->dst_object)) | 7168 | if (EQ (coding->src_object, coding->dst_object)) |
| 7153 | dst_end = (unsigned char *) src; | 7169 | dst_end = (unsigned char *) src; |
| 7154 | if (dst >= dst_end - 1) | 7170 | 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, | |||
| 2355 | struct coding_system *coding | 2355 | struct coding_system *coding |
| 2356 | = TERMINAL_KEYBOARD_CODING (terminal); | 2356 | = TERMINAL_KEYBOARD_CODING (terminal); |
| 2357 | unsigned char src[MAX_ENCODED_BYTES]; | 2357 | unsigned char src[MAX_ENCODED_BYTES]; |
| 2358 | unsigned char dest[4 * sizeof src]; | 2358 | unsigned char dest[MAX_ENCODED_BYTES * MAX_MULTIBYTE_LENGTH]; |
| 2359 | int i; | 2359 | int i; |
| 2360 | for (i = 0; i < n; i++) | 2360 | for (i = 0; i < n; i++) |
| 2361 | src[i] = XINT (events[i]); | 2361 | src[i] = XINT (events[i]); |
| 2362 | if (meta_key != 2) | 2362 | if (meta_key != 2) |
| 2363 | for (i = 0; i < n; i++) | 2363 | for (i = 0; i < n; i++) |
| 2364 | src[i] &= ~0x80; | 2364 | src[i] &= ~0x80; |
| 2365 | 2365 | coding->destination = dest; | |
| 2366 | /* FIXME: For some reason decode_coding_c_string requires a | 2366 | coding->dst_bytes = sizeof dest; |
| 2367 | fresh output buffer each time, and reusing the old buffer can | ||
| 2368 | make Emacs dump core. Avoid triggering the problem for now | ||
| 2369 | by allocating a new buffer each time through the loop. */ | ||
| 2370 | bool please_fixme = true; | ||
| 2371 | coding->destination = please_fixme ? alloca (n * 4) : dest; | ||
| 2372 | |||
| 2373 | coding->dst_bytes = n * 4; | ||
| 2374 | decode_coding_c_string (coding, src, n, Qnil); | 2367 | decode_coding_c_string (coding, src, n, Qnil); |
| 2375 | eassert (coding->produced_char <= n); | 2368 | eassert (coding->produced_char <= n); |
| 2376 | if (coding->produced_char == 0) | 2369 | if (coding->produced_char == 0) |