aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Ingebrigtsen2019-10-13 03:12:11 +0200
committerLars Ingebrigtsen2019-10-13 03:12:11 +0200
commitdb9ba7ca014a3437fc571b0890fa9ab16c08cfe0 (patch)
treebb8a0a038651314475f98877bd989f6d7ff2fdd0 /src
parent297f333a13b1f126e3f9c378ab856b970ee80283 (diff)
downloademacs-db9ba7ca014a3437fc571b0890fa9ab16c08cfe0.tar.gz
emacs-db9ba7ca014a3437fc571b0890fa9ab16c08cfe0.zip
Protect against segfaults in copy-keymap
* src/keymap.c (copy_keymap_1): Factor out and refuse to recurse infinitely (bug#7496). (Fcopy_keymap): ... from here. (copy_keymap_item): Pass on the depth parameter.
Diffstat (limited to 'src')
-rw-r--r--src/keymap.c70
1 files changed, 42 insertions, 28 deletions
diff --git a/src/keymap.c b/src/keymap.c
index da2786c8449..5aed4129bb7 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -912,8 +912,10 @@ store_in_keymap (Lisp_Object keymap, register Lisp_Object idx, Lisp_Object def)
912 return def; 912 return def;
913} 913}
914 914
915static Lisp_Object copy_keymap_1 (Lisp_Object keymap, int depth);
916
915static Lisp_Object 917static Lisp_Object
916copy_keymap_item (Lisp_Object elt) 918copy_keymap_item (Lisp_Object elt, int depth)
917{ 919{
918 Lisp_Object res, tem; 920 Lisp_Object res, tem;
919 921
@@ -943,7 +945,7 @@ copy_keymap_item (Lisp_Object elt)
943 elt = XCDR (elt); 945 elt = XCDR (elt);
944 tem = XCAR (elt); 946 tem = XCAR (elt);
945 if (CONSP (tem) && EQ (XCAR (tem), Qkeymap)) 947 if (CONSP (tem) && EQ (XCAR (tem), Qkeymap))
946 XSETCAR (elt, Fcopy_keymap (tem)); 948 XSETCAR (elt, copy_keymap_1 (tem, depth));
947 tem = XCDR (elt); 949 tem = XCDR (elt);
948 } 950 }
949 } 951 }
@@ -964,40 +966,29 @@ copy_keymap_item (Lisp_Object elt)
964 tem = XCDR (elt); 966 tem = XCDR (elt);
965 } 967 }
966 if (CONSP (tem) && EQ (XCAR (tem), Qkeymap)) 968 if (CONSP (tem) && EQ (XCAR (tem), Qkeymap))
967 XSETCDR (elt, Fcopy_keymap (tem)); 969 XSETCDR (elt, copy_keymap_1 (tem, depth));
968 } 970 }
969 else if (EQ (XCAR (tem), Qkeymap)) 971 else if (EQ (XCAR (tem), Qkeymap))
970 res = Fcopy_keymap (elt); 972 res = copy_keymap_1 (elt, depth);
971 } 973 }
972 return res; 974 return res;
973} 975}
974 976
975static void 977static void
976copy_keymap_1 (Lisp_Object chartable, Lisp_Object idx, Lisp_Object elt) 978copy_keymap_set_char_table (Lisp_Object chartable, Lisp_Object idx,
979 Lisp_Object elt)
977{ 980{
978 Fset_char_table_range (chartable, idx, copy_keymap_item (elt)); 981 Fset_char_table_range (chartable, idx, copy_keymap_item (elt, 0));
979} 982}
980 983
981DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0, 984static Lisp_Object
982 doc: /* Return a copy of the keymap KEYMAP. 985copy_keymap_1 (Lisp_Object keymap, int depth)
983
984Note that this is almost never needed. If you want a keymap that's like
985another yet with a few changes, you should use map inheritance rather
986than copying. I.e. something like:
987
988 (let ((map (make-sparse-keymap)))
989 (set-keymap-parent map <theirmap>)
990 (define-key map ...)
991 ...)
992
993After performing `copy-keymap', the copy starts out with the same definitions
994of KEYMAP, but changing either the copy or KEYMAP does not affect the other.
995Any key definitions that are subkeymaps are recursively copied.
996However, a key definition which is a symbol whose definition is a keymap
997is not copied. */)
998 (Lisp_Object keymap)
999{ 986{
1000 Lisp_Object copy, tail; 987 Lisp_Object copy, tail;
988
989 if (depth > 100)
990 error ("Possible infinite recursion when copying keymap");
991
1001 keymap = get_keymap (keymap, 1, 0); 992 keymap = get_keymap (keymap, 1, 0);
1002 copy = tail = list1 (Qkeymap); 993 copy = tail = list1 (Qkeymap);
1003 keymap = XCDR (keymap); /* Skip the `keymap' symbol. */ 994 keymap = XCDR (keymap); /* Skip the `keymap' symbol. */
@@ -1008,22 +999,22 @@ is not copied. */)
1008 if (CHAR_TABLE_P (elt)) 999 if (CHAR_TABLE_P (elt))
1009 { 1000 {
1010 elt = Fcopy_sequence (elt); 1001 elt = Fcopy_sequence (elt);
1011 map_char_table (copy_keymap_1, Qnil, elt, elt); 1002 map_char_table (copy_keymap_set_char_table, Qnil, elt, elt);
1012 } 1003 }
1013 else if (VECTORP (elt)) 1004 else if (VECTORP (elt))
1014 { 1005 {
1015 int i; 1006 int i;
1016 elt = Fcopy_sequence (elt); 1007 elt = Fcopy_sequence (elt);
1017 for (i = 0; i < ASIZE (elt); i++) 1008 for (i = 0; i < ASIZE (elt); i++)
1018 ASET (elt, i, copy_keymap_item (AREF (elt, i))); 1009 ASET (elt, i, copy_keymap_item (AREF (elt, i), depth + 1));
1019 } 1010 }
1020 else if (CONSP (elt)) 1011 else if (CONSP (elt))
1021 { 1012 {
1022 if (EQ (XCAR (elt), Qkeymap)) 1013 if (EQ (XCAR (elt), Qkeymap))
1023 /* This is a sub keymap. */ 1014 /* This is a sub keymap. */
1024 elt = Fcopy_keymap (elt); 1015 elt = copy_keymap_1 (elt, depth + 1);
1025 else 1016 else
1026 elt = Fcons (XCAR (elt), copy_keymap_item (XCDR (elt))); 1017 elt = Fcons (XCAR (elt), copy_keymap_item (XCDR (elt), depth + 1));
1027 } 1018 }
1028 XSETCDR (tail, list1 (elt)); 1019 XSETCDR (tail, list1 (elt));
1029 tail = XCDR (tail); 1020 tail = XCDR (tail);
@@ -1032,6 +1023,29 @@ is not copied. */)
1032 XSETCDR (tail, keymap); 1023 XSETCDR (tail, keymap);
1033 return copy; 1024 return copy;
1034} 1025}
1026
1027DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0,
1028 doc: /* Return a copy of the keymap KEYMAP.
1029
1030Note that this is almost never needed. If you want a keymap that's like
1031another yet with a few changes, you should use map inheritance rather
1032than copying. I.e. something like:
1033
1034 (let ((map (make-sparse-keymap)))
1035 (set-keymap-parent map <theirmap>)
1036 (define-key map ...)
1037 ...)
1038
1039After performing `copy-keymap', the copy starts out with the same definitions
1040of KEYMAP, but changing either the copy or KEYMAP does not affect the other.
1041Any key definitions that are subkeymaps are recursively copied.
1042However, a key definition which is a symbol whose definition is a keymap
1043is not copied. */)
1044 (Lisp_Object keymap)
1045{
1046 return copy_keymap_1 (keymap, 0);
1047}
1048
1035 1049
1036/* Simple Keymap mutators and accessors. */ 1050/* Simple Keymap mutators and accessors. */
1037 1051