diff options
| author | Paul Eggert | 2019-10-30 14:24:29 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-10-30 14:43:14 -0700 |
| commit | 581601e650cc8bdcf3ed83c6ae36744601c12ce9 (patch) | |
| tree | 37cc3bd330820866ff9d3aa2bf37e2fd84725739 /src | |
| parent | 40ae02ff50a8f05660a7f9f234320875b6358c9d (diff) | |
| download | emacs-581601e650cc8bdcf3ed83c6ae36744601c12ce9.tar.gz emacs-581601e650cc8bdcf3ed83c6ae36744601c12ce9.zip | |
Fix keyboard.c infloops on circular lists
Fix infinite loops in keyboard.c when a circular list is
found in a hook, or in help-event-list, or in the argument
of event-convert-list, or in a keymap where a Lucid event
type list is expected, or in a menu or tab spec.
* src/keyboard.c (safe_run_hooks_error, menu_bar_items)
(parse_menu_item, parse_tab_bar_item, parse_tool_bar_item):
Use FOR_EACH_TAIL to avoid infloop on circular lists.
(help_char_p, Fevent_convert_list, lucid_event_type_list_p):
Use FOR_EACH_TAIL_SAFE to avoid infloop on circular lists,
when the action is idempotent so a circular list can be
treated as a noncircular one.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keyboard.c | 85 |
1 files changed, 39 insertions, 46 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index 0eab8fdfae1..7d3b0244b20 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -1784,10 +1784,10 @@ safe_run_hooks_error (Lisp_Object error, ptrdiff_t nargs, Lisp_Object *args) | |||
| 1784 | 1784 | ||
| 1785 | if (SYMBOLP (hook)) | 1785 | if (SYMBOLP (hook)) |
| 1786 | { | 1786 | { |
| 1787 | Lisp_Object val; | ||
| 1788 | bool found = false; | 1787 | bool found = false; |
| 1789 | Lisp_Object newval = Qnil; | 1788 | Lisp_Object newval = Qnil; |
| 1790 | for (val = find_symbol_value (hook); CONSP (val); val = XCDR (val)) | 1789 | Lisp_Object val = find_symbol_value (hook); |
| 1790 | FOR_EACH_TAIL (val) | ||
| 1791 | if (EQ (fun, XCAR (val))) | 1791 | if (EQ (fun, XCAR (val))) |
| 1792 | found = true; | 1792 | found = true; |
| 1793 | else | 1793 | else |
| @@ -1797,9 +1797,8 @@ safe_run_hooks_error (Lisp_Object error, ptrdiff_t nargs, Lisp_Object *args) | |||
| 1797 | /* Not found in the local part of the hook. Let's look at the global | 1797 | /* Not found in the local part of the hook. Let's look at the global |
| 1798 | part. */ | 1798 | part. */ |
| 1799 | newval = Qnil; | 1799 | newval = Qnil; |
| 1800 | for (val = (NILP (Fdefault_boundp (hook)) ? Qnil | 1800 | val = NILP (Fdefault_boundp (hook)) ? Qnil : Fdefault_value (hook); |
| 1801 | : Fdefault_value (hook)); | 1801 | FOR_EACH_TAIL (val) |
| 1802 | CONSP (val); val = XCDR (val)) | ||
| 1803 | if (EQ (fun, XCAR (val))) | 1802 | if (EQ (fun, XCAR (val))) |
| 1804 | found = true; | 1803 | found = true; |
| 1805 | else | 1804 | else |
| @@ -3196,14 +3195,13 @@ record_menu_key (Lisp_Object c) | |||
| 3196 | static bool | 3195 | static bool |
| 3197 | help_char_p (Lisp_Object c) | 3196 | help_char_p (Lisp_Object c) |
| 3198 | { | 3197 | { |
| 3199 | Lisp_Object tail; | ||
| 3200 | |||
| 3201 | if (EQ (c, Vhelp_char)) | 3198 | if (EQ (c, Vhelp_char)) |
| 3202 | return 1; | 3199 | return true; |
| 3203 | for (tail = Vhelp_event_list; CONSP (tail); tail = XCDR (tail)) | 3200 | Lisp_Object tail = Vhelp_event_list; |
| 3201 | FOR_EACH_TAIL_SAFE (tail) | ||
| 3204 | if (EQ (c, XCAR (tail))) | 3202 | if (EQ (c, XCAR (tail))) |
| 3205 | return 1; | 3203 | return true; |
| 3206 | return 0; | 3204 | return false; |
| 3207 | } | 3205 | } |
| 3208 | 3206 | ||
| 3209 | /* Record the input event C in various ways. */ | 3207 | /* Record the input event C in various ways. */ |
| @@ -6581,22 +6579,16 @@ The return value is an event type (a character or symbol) which | |||
| 6581 | has the same base event type and all the specified modifiers. */) | 6579 | has the same base event type and all the specified modifiers. */) |
| 6582 | (Lisp_Object event_desc) | 6580 | (Lisp_Object event_desc) |
| 6583 | { | 6581 | { |
| 6584 | Lisp_Object base; | 6582 | Lisp_Object base = Qnil; |
| 6585 | int modifiers = 0; | 6583 | int modifiers = 0; |
| 6586 | Lisp_Object rest; | ||
| 6587 | 6584 | ||
| 6588 | base = Qnil; | 6585 | FOR_EACH_TAIL_SAFE (event_desc) |
| 6589 | rest = event_desc; | ||
| 6590 | while (CONSP (rest)) | ||
| 6591 | { | 6586 | { |
| 6592 | Lisp_Object elt; | 6587 | Lisp_Object elt = XCAR (event_desc); |
| 6593 | int this = 0; | 6588 | int this = 0; |
| 6594 | 6589 | ||
| 6595 | elt = XCAR (rest); | ||
| 6596 | rest = XCDR (rest); | ||
| 6597 | |||
| 6598 | /* Given a symbol, see if it is a modifier name. */ | 6590 | /* Given a symbol, see if it is a modifier name. */ |
| 6599 | if (SYMBOLP (elt) && CONSP (rest)) | 6591 | if (SYMBOLP (elt) && CONSP (XCDR (event_desc))) |
| 6600 | this = parse_solitary_modifier (elt); | 6592 | this = parse_solitary_modifier (elt); |
| 6601 | 6593 | ||
| 6602 | if (this != 0) | 6594 | if (this != 0) |
| @@ -6605,7 +6597,6 @@ has the same base event type and all the specified modifiers. */) | |||
| 6605 | error ("Two bases given in one event"); | 6597 | error ("Two bases given in one event"); |
| 6606 | else | 6598 | else |
| 6607 | base = elt; | 6599 | base = elt; |
| 6608 | |||
| 6609 | } | 6600 | } |
| 6610 | 6601 | ||
| 6611 | /* Let the symbol A refer to the character A. */ | 6602 | /* Let the symbol A refer to the character A. */ |
| @@ -6755,24 +6746,23 @@ parse_solitary_modifier (Lisp_Object symbol) | |||
| 6755 | bool | 6746 | bool |
| 6756 | lucid_event_type_list_p (Lisp_Object object) | 6747 | lucid_event_type_list_p (Lisp_Object object) |
| 6757 | { | 6748 | { |
| 6758 | Lisp_Object tail; | ||
| 6759 | |||
| 6760 | if (! CONSP (object)) | 6749 | if (! CONSP (object)) |
| 6761 | return 0; | 6750 | return false; |
| 6762 | 6751 | ||
| 6763 | if (EQ (XCAR (object), Qhelp_echo) | 6752 | if (EQ (XCAR (object), Qhelp_echo) |
| 6764 | || EQ (XCAR (object), Qvertical_line) | 6753 | || EQ (XCAR (object), Qvertical_line) |
| 6765 | || EQ (XCAR (object), Qmode_line) | 6754 | || EQ (XCAR (object), Qmode_line) |
| 6766 | || EQ (XCAR (object), Qtab_line) | 6755 | || EQ (XCAR (object), Qtab_line) |
| 6767 | || EQ (XCAR (object), Qheader_line)) | 6756 | || EQ (XCAR (object), Qheader_line)) |
| 6768 | return 0; | 6757 | return false; |
| 6769 | 6758 | ||
| 6770 | for (tail = object; CONSP (tail); tail = XCDR (tail)) | 6759 | Lisp_Object tail = object; |
| 6760 | FOR_EACH_TAIL_SAFE (object) | ||
| 6771 | { | 6761 | { |
| 6772 | Lisp_Object elt; | 6762 | Lisp_Object elt = XCAR (object); |
| 6773 | elt = XCAR (tail); | ||
| 6774 | if (! (FIXNUMP (elt) || SYMBOLP (elt))) | 6763 | if (! (FIXNUMP (elt) || SYMBOLP (elt))) |
| 6775 | return 0; | 6764 | return false; |
| 6765 | tail = XCDR (object); | ||
| 6776 | } | 6766 | } |
| 6777 | 6767 | ||
| 6778 | return NILP (tail); | 6768 | return NILP (tail); |
| @@ -7401,7 +7391,7 @@ menu_bar_items (Lisp_Object old) | |||
| 7401 | Lisp_Object *maps; | 7391 | Lisp_Object *maps; |
| 7402 | 7392 | ||
| 7403 | Lisp_Object mapsbuf[3]; | 7393 | Lisp_Object mapsbuf[3]; |
| 7404 | Lisp_Object def, tail; | 7394 | Lisp_Object def; |
| 7405 | 7395 | ||
| 7406 | ptrdiff_t mapno; | 7396 | ptrdiff_t mapno; |
| 7407 | Lisp_Object oquit; | 7397 | Lisp_Object oquit; |
| @@ -7484,12 +7474,12 @@ menu_bar_items (Lisp_Object old) | |||
| 7484 | 7474 | ||
| 7485 | /* Move to the end those items that should be at the end. */ | 7475 | /* Move to the end those items that should be at the end. */ |
| 7486 | 7476 | ||
| 7487 | for (tail = Vmenu_bar_final_items; CONSP (tail); tail = XCDR (tail)) | 7477 | Lisp_Object tail = Vmenu_bar_final_items; |
| 7478 | FOR_EACH_TAIL (tail) | ||
| 7488 | { | 7479 | { |
| 7489 | int i; | ||
| 7490 | int end = menu_bar_items_index; | 7480 | int end = menu_bar_items_index; |
| 7491 | 7481 | ||
| 7492 | for (i = 0; i < end; i += 4) | 7482 | for (int i = 0; i < end; i += 4) |
| 7493 | if (EQ (XCAR (tail), AREF (menu_bar_items_vector, i))) | 7483 | if (EQ (XCAR (tail), AREF (menu_bar_items_vector, i))) |
| 7494 | { | 7484 | { |
| 7495 | Lisp_Object tem0, tem1, tem2, tem3; | 7485 | Lisp_Object tem0, tem1, tem2, tem3; |
| @@ -7726,10 +7716,12 @@ parse_menu_item (Lisp_Object item, int inmenubar) | |||
| 7726 | item = XCDR (item); | 7716 | item = XCDR (item); |
| 7727 | 7717 | ||
| 7728 | /* Parse properties. */ | 7718 | /* Parse properties. */ |
| 7729 | while (CONSP (item) && CONSP (XCDR (item))) | 7719 | FOR_EACH_TAIL (item) |
| 7730 | { | 7720 | { |
| 7731 | tem = XCAR (item); | 7721 | tem = XCAR (item); |
| 7732 | item = XCDR (item); | 7722 | item = XCDR (item); |
| 7723 | if (!CONSP (item)) | ||
| 7724 | break; | ||
| 7733 | 7725 | ||
| 7734 | if (EQ (tem, QCenable)) | 7726 | if (EQ (tem, QCenable)) |
| 7735 | { | 7727 | { |
| @@ -7780,7 +7772,6 @@ parse_menu_item (Lisp_Object item, int inmenubar) | |||
| 7780 | ASET (item_properties, ITEM_PROPERTY_TYPE, type); | 7772 | ASET (item_properties, ITEM_PROPERTY_TYPE, type); |
| 7781 | } | 7773 | } |
| 7782 | } | 7774 | } |
| 7783 | item = XCDR (item); | ||
| 7784 | } | 7775 | } |
| 7785 | } | 7776 | } |
| 7786 | else if (inmenubar || !NILP (start)) | 7777 | else if (inmenubar || !NILP (start)) |
| @@ -8198,12 +8189,13 @@ parse_tab_bar_item (Lisp_Object key, Lisp_Object item) | |||
| 8198 | item = XCDR (item); | 8189 | item = XCDR (item); |
| 8199 | 8190 | ||
| 8200 | /* Process the rest of the properties. */ | 8191 | /* Process the rest of the properties. */ |
| 8201 | for (; CONSP (item) && CONSP (XCDR (item)); item = XCDR (XCDR (item))) | 8192 | FOR_EACH_TAIL (item) |
| 8202 | { | 8193 | { |
| 8203 | Lisp_Object ikey, value; | 8194 | Lisp_Object ikey = XCAR (item); |
| 8204 | 8195 | item = XCDR (item); | |
| 8205 | ikey = XCAR (item); | 8196 | if (!CONSP (item)) |
| 8206 | value = XCAR (XCDR (item)); | 8197 | break; |
| 8198 | Lisp_Object value = XCAR (item); | ||
| 8207 | 8199 | ||
| 8208 | if (EQ (ikey, QCenable)) | 8200 | if (EQ (ikey, QCenable)) |
| 8209 | { | 8201 | { |
| @@ -8590,12 +8582,13 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item) | |||
| 8590 | item = XCDR (item); | 8582 | item = XCDR (item); |
| 8591 | 8583 | ||
| 8592 | /* Process the rest of the properties. */ | 8584 | /* Process the rest of the properties. */ |
| 8593 | for (; CONSP (item) && CONSP (XCDR (item)); item = XCDR (XCDR (item))) | 8585 | FOR_EACH_TAIL (item) |
| 8594 | { | 8586 | { |
| 8595 | Lisp_Object ikey, value; | 8587 | Lisp_Object ikey = XCAR (item); |
| 8596 | 8588 | item = XCDR (item); | |
| 8597 | ikey = XCAR (item); | 8589 | if (!CONSP (item)) |
| 8598 | value = XCAR (XCDR (item)); | 8590 | break; |
| 8591 | Lisp_Object value = XCAR (item); | ||
| 8599 | 8592 | ||
| 8600 | if (EQ (ikey, QCenable)) | 8593 | if (EQ (ikey, QCenable)) |
| 8601 | { | 8594 | { |