aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorBasil L. Contovounesios2018-04-29 15:37:45 +0100
committerNoam Postavsky2018-05-02 20:18:07 -0400
commitf2c74543edc7e8d07655b459ba8898eec9b6d4e8 (patch)
treeb6612a1370f9c20399e8fa32ff50be643a0ecabd /lisp
parent05e9477ab5d5dba1b960415d60b9957caa90da48 (diff)
downloademacs-f2c74543edc7e8d07655b459ba8898eec9b6d4e8.tar.gz
emacs-f2c74543edc7e8d07655b459ba8898eec9b6d4e8.zip
Fix off-by-one history pruning (bug#31211)
* lisp/subr.el (add-to-history): Clarify docstring. Protect against negative history-length and unnecessary variable modification, as per read_minibuf. * lisp/ido.el (ido-record-command): * lisp/international/mule-cmds.el (deactivate-input-method): (set-language-environment-input-method): * lisp/isearch.el (isearch-done): * lisp/minibuffer.el (read-file-name-default): * lisp/net/eww.el (eww-save-history): * lisp/simple.el (edit-and-eval-command, repeat-complex-command): (command-execute, kill-new, push-mark): * src/callint.c (Fcall_interactively): * src/minibuf.c (read_minibuf): Delegate to add-to-history. * test/lisp/simple-tests.el (command-execute-prune-command-history): * test/src/callint-tests.el (call-interactively-prune-command-history): New tests.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ido.el7
-rw-r--r--lisp/international/mule-cmds.el13
-rw-r--r--lisp/isearch.el13
-rw-r--r--lisp/minibuffer.el14
-rw-r--r--lisp/net/eww.el10
-rw-r--r--lisp/simple.el49
-rw-r--r--lisp/subr.el8
7 files changed, 42 insertions, 72 deletions
diff --git a/lisp/ido.el b/lisp/ido.el
index 7ff3d6820b4..705e7dd6301 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -1793,11 +1793,8 @@ is enabled then some keybindings are changed in the keymap."
1793 1793
1794(defun ido-record-command (command arg) 1794(defun ido-record-command (command arg)
1795 "Add (COMMAND ARG) to `command-history' if `ido-record-commands' is non-nil." 1795 "Add (COMMAND ARG) to `command-history' if `ido-record-commands' is non-nil."
1796 (if ido-record-commands ; FIXME: use `when' instead of `if'? 1796 (when ido-record-commands
1797 (let ((cmd (list command arg))) 1797 (add-to-history 'command-history (list command arg))))
1798 (if (or (not command-history) ; FIXME: ditto
1799 (not (equal cmd (car command-history))))
1800 (setq command-history (cons cmd command-history))))))
1801 1798
1802(defun ido-make-prompt (item prompt) 1799(defun ido-make-prompt (item prompt)
1803 ;; Make the prompt for ido-read-internal 1800 ;; Make the prompt for ido-read-internal
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index 6c49b8fa6a0..c0b329bbaea 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -1464,12 +1464,7 @@ If INPUT-METHOD is nil, deactivate any current input method."
1464(defun deactivate-input-method () 1464(defun deactivate-input-method ()
1465 "Turn off the current input method." 1465 "Turn off the current input method."
1466 (when current-input-method 1466 (when current-input-method
1467 (if input-method-history 1467 (add-to-history 'input-method-history current-input-method)
1468 (unless (string= current-input-method (car input-method-history))
1469 (setq input-method-history
1470 (cons current-input-method
1471 (delete current-input-method input-method-history))))
1472 (setq input-method-history (list current-input-method)))
1473 (unwind-protect 1468 (unwind-protect
1474 (progn 1469 (progn
1475 (setq input-method-function nil 1470 (setq input-method-function nil
@@ -2022,10 +2017,8 @@ See `set-language-info-alist' for use in programs."
2022 (let ((input-method (get-language-info language-name 'input-method))) 2017 (let ((input-method (get-language-info language-name 'input-method)))
2023 (when input-method 2018 (when input-method
2024 (setq default-input-method input-method) 2019 (setq default-input-method input-method)
2025 (if input-method-history 2020 (when input-method-history
2026 (setq input-method-history 2021 (add-to-history 'input-method-history input-method)))))
2027 (cons input-method
2028 (delete input-method input-method-history)))))))
2029 2022
2030(defun set-language-environment-nonascii-translation (language-name) 2023(defun set-language-environment-nonascii-translation (language-name)
2031 "Do unibyte/multibyte translation setup for language environment LANGUAGE-NAME." 2024 "Do unibyte/multibyte translation setup for language environment LANGUAGE-NAME."
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 5cbb4c941a5..feadf10e8b7 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -1049,13 +1049,12 @@ For a failing search, NOPUSH is t.
1049For going to the minibuffer to edit the search string, 1049For going to the minibuffer to edit the search string,
1050NOPUSH is t and EDIT is t." 1050NOPUSH is t and EDIT is t."
1051 1051
1052 (if isearch-resume-in-command-history 1052 (when isearch-resume-in-command-history
1053 (let ((command `(isearch-resume ,isearch-string ,isearch-regexp 1053 (add-to-history 'command-history
1054 ,isearch-regexp-function ,isearch-forward 1054 `(isearch-resume ,isearch-string ,isearch-regexp
1055 ,isearch-message 1055 ,isearch-regexp-function ,isearch-forward
1056 ',isearch-case-fold-search))) 1056 ,isearch-message
1057 (unless (equal (car command-history) command) 1057 ',isearch-case-fold-search)))
1058 (setq command-history (cons command command-history)))))
1059 1058
1060 (remove-hook 'pre-command-hook 'isearch-pre-command-hook) 1059 (remove-hook 'pre-command-hook 'isearch-pre-command-hook)
1061 (remove-hook 'post-command-hook 'isearch-post-command-hook) 1060 (remove-hook 'post-command-hook 'isearch-post-command-hook)
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index f1cbdc0cc36..a7e6a8761ff 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2722,17 +2722,9 @@ See `read-file-name' for the meaning of the arguments."
2722 (if (string= val1 (cadr file-name-history)) 2722 (if (string= val1 (cadr file-name-history))
2723 (pop file-name-history) 2723 (pop file-name-history)
2724 (setcar file-name-history val1))) 2724 (setcar file-name-history val1)))
2725 (if add-to-history 2725 (when add-to-history
2726 ;; Add the value to the history--but not if it matches 2726 (add-to-history 'file-name-history
2727 ;; the last value already there. 2727 (minibuffer-maybe-quote-filename val))))
2728 (let ((val1 (minibuffer-maybe-quote-filename val)))
2729 (unless (and (consp file-name-history)
2730 (equal (car file-name-history) val1))
2731 (setq file-name-history
2732 (cons val1
2733 (if history-delete-duplicates
2734 (delete val1 file-name-history)
2735 file-name-history)))))))
2736 val)))) 2728 val))))
2737 2729
2738(defun internal-complete-buffer-except (&optional buffer) 2730(defun internal-complete-buffer-except (&optional buffer)
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index e74f661ac75..97fdabd72bd 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1813,13 +1813,9 @@ If CHARSET is nil then use UTF-8."
1813(defun eww-save-history () 1813(defun eww-save-history ()
1814 (plist-put eww-data :point (point)) 1814 (plist-put eww-data :point (point))
1815 (plist-put eww-data :text (buffer-string)) 1815 (plist-put eww-data :text (buffer-string))
1816 (push eww-data eww-history) 1816 (let ((history-delete-duplicates nil))
1817 (setq eww-data (list :title "")) 1817 (add-to-history 'eww-history eww-data eww-history-limit t))
1818 ;; Don't let the history grow infinitely. We store quite a lot of 1818 (setq eww-data (list :title "")))
1819 ;; data per page.
1820 (when-let* ((tail (and eww-history-limit
1821 (nthcdr eww-history-limit eww-history))))
1822 (setcdr tail nil)))
1823 1819
1824(defvar eww-current-buffer) 1820(defvar eww-current-buffer)
1825 1821
diff --git a/lisp/simple.el b/lisp/simple.el
index 5446159d319..9fde9a5c90a 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1646,13 +1646,10 @@ the minibuffer, then read and evaluate the result."
1646 'command-history) 1646 'command-history)
1647 ;; If command was added to command-history as a string, 1647 ;; If command was added to command-history as a string,
1648 ;; get rid of that. We want only evaluable expressions there. 1648 ;; get rid of that. We want only evaluable expressions there.
1649 (if (stringp (car command-history)) 1649 (when (stringp (car command-history))
1650 (setq command-history (cdr command-history))))))) 1650 (pop command-history))))))
1651 1651
1652 ;; If command to be redone does not match front of history, 1652 (add-to-history 'command-history command)
1653 ;; add it to the history.
1654 (or (equal command (car command-history))
1655 (setq command-history (cons command command-history)))
1656 (eval command))) 1653 (eval command)))
1657 1654
1658(defun repeat-complex-command (arg) 1655(defun repeat-complex-command (arg)
@@ -1682,13 +1679,10 @@ to get different commands to edit and resubmit."
1682 ;; If command was added to command-history as a 1679 ;; If command was added to command-history as a
1683 ;; string, get rid of that. We want only 1680 ;; string, get rid of that. We want only
1684 ;; evaluable expressions there. 1681 ;; evaluable expressions there.
1685 (if (stringp (car command-history)) 1682 (when (stringp (car command-history))
1686 (setq command-history (cdr command-history)))))) 1683 (pop command-history)))))
1687 1684
1688 ;; If command to be redone does not match front of history, 1685 (add-to-history 'command-history newcmd)
1689 ;; add it to the history.
1690 (or (equal newcmd (car command-history))
1691 (setq command-history (cons newcmd command-history)))
1692 (apply #'funcall-interactively 1686 (apply #'funcall-interactively
1693 (car newcmd) 1687 (car newcmd)
1694 (mapcar (lambda (e) (eval e t)) (cdr newcmd)))) 1688 (mapcar (lambda (e) (eval e t)) (cdr newcmd))))
@@ -1905,11 +1899,8 @@ a special event, so ignore the prefix argument and don't clear it."
1905 ;; If requested, place the macro in the command history. For 1899 ;; If requested, place the macro in the command history. For
1906 ;; other sorts of commands, call-interactively takes care of this. 1900 ;; other sorts of commands, call-interactively takes care of this.
1907 (when record-flag 1901 (when record-flag
1908 (push `(execute-kbd-macro ,final ,prefixarg) command-history) 1902 (add-to-history
1909 ;; Don't keep command history around forever. 1903 'command-history `(execute-kbd-macro ,final ,prefixarg) nil t))
1910 (when (and (numberp history-length) (> history-length 0))
1911 (let ((cell (nthcdr history-length command-history)))
1912 (if (consp cell) (setcdr cell nil)))))
1913 (execute-kbd-macro final prefixarg)) 1904 (execute-kbd-macro final prefixarg))
1914 (t 1905 (t
1915 ;; Pass `cmd' rather than `final', for the backtrace's sake. 1906 ;; Pass `cmd' rather than `final', for the backtrace's sake.
@@ -4408,9 +4399,8 @@ argument should still be a \"useful\" string for such uses."
4408 (equal-including-properties string (car kill-ring))) 4399 (equal-including-properties string (car kill-ring)))
4409 (if (and replace kill-ring) 4400 (if (and replace kill-ring)
4410 (setcar kill-ring string) 4401 (setcar kill-ring string)
4411 (push string kill-ring) 4402 (let ((history-delete-duplicates nil))
4412 (if (> (length kill-ring) kill-ring-max) 4403 (add-to-history 'kill-ring string kill-ring-max t))))
4413 (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))))
4414 (setq kill-ring-yank-pointer kill-ring) 4404 (setq kill-ring-yank-pointer kill-ring)
4415 (if interprogram-cut-function 4405 (if interprogram-cut-function
4416 (funcall interprogram-cut-function string))) 4406 (funcall interprogram-cut-function string)))
@@ -5724,10 +5714,11 @@ purposes. See the documentation of `set-mark' for more information.
5724 5714
5725In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil." 5715In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil."
5726 (unless (null (mark t)) 5716 (unless (null (mark t))
5727 (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring)) 5717 (let ((old (nth mark-ring-max mark-ring))
5728 (when (> (length mark-ring) mark-ring-max) 5718 (history-delete-duplicates nil))
5729 (move-marker (car (nthcdr mark-ring-max mark-ring)) nil) 5719 (add-to-history 'mark-ring (copy-marker (mark-marker)) mark-ring-max t)
5730 (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil))) 5720 (when old
5721 (set-marker old nil))))
5731 (set-marker (mark-marker) (or location (point)) (current-buffer)) 5722 (set-marker (mark-marker) (or location (point)) (current-buffer))
5732 ;; Now push the mark on the global mark ring. 5723 ;; Now push the mark on the global mark ring.
5733 (if (and global-mark-ring 5724 (if (and global-mark-ring
@@ -5735,10 +5726,12 @@ In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil."
5735 ;; The last global mark pushed was in this same buffer. 5726 ;; The last global mark pushed was in this same buffer.
5736 ;; Don't push another one. 5727 ;; Don't push another one.
5737 nil 5728 nil
5738 (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring)) 5729 (let ((old (nth global-mark-ring-max global-mark-ring))
5739 (when (> (length global-mark-ring) global-mark-ring-max) 5730 (history-delete-duplicates nil))
5740 (move-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil) 5731 (add-to-history
5741 (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil))) 5732 'global-mark-ring (copy-marker (mark-marker)) global-mark-ring-max t)
5733 (when old
5734 (set-marker old nil))))
5742 (or nomsg executing-kbd-macro (> (minibuffer-depth) 0) 5735 (or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
5743 (message "Mark set")) 5736 (message "Mark set"))
5744 (if (or activate (not transient-mark-mode)) 5737 (if (or activate (not transient-mark-mode))
diff --git a/lisp/subr.el b/lisp/subr.el
index 9f6cade0f71..35e220a10ee 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -1798,7 +1798,7 @@ variable. The possible values of maximum length have the same meaning as
1798the values of `history-length'. 1798the values of `history-length'.
1799Remove duplicates of NEWELT if `history-delete-duplicates' is non-nil. 1799Remove duplicates of NEWELT if `history-delete-duplicates' is non-nil.
1800If optional fourth arg KEEP-ALL is non-nil, add NEWELT to history even 1800If optional fourth arg KEEP-ALL is non-nil, add NEWELT to history even
1801if it is empty or a duplicate." 1801if it is empty or duplicates the most recent entry in the history."
1802 (unless maxelt 1802 (unless maxelt
1803 (setq maxelt (or (get history-var 'history-length) 1803 (setq maxelt (or (get history-var 'history-length)
1804 history-length))) 1804 history-length)))
@@ -1814,12 +1814,12 @@ if it is empty or a duplicate."
1814 (setq history (delete newelt history))) 1814 (setq history (delete newelt history)))
1815 (setq history (cons newelt history)) 1815 (setq history (cons newelt history))
1816 (when (integerp maxelt) 1816 (when (integerp maxelt)
1817 (if (= 0 maxelt) 1817 (if (>= 0 maxelt)
1818 (setq history nil) 1818 (setq history nil)
1819 (setq tail (nthcdr (1- maxelt) history)) 1819 (setq tail (nthcdr (1- maxelt) history))
1820 (when (consp tail) 1820 (when (consp tail)
1821 (setcdr tail nil))))) 1821 (setcdr tail nil))))
1822 (set history-var history))) 1822 (set history-var history))))
1823 1823
1824 1824
1825;;;; Mode hooks. 1825;;;; Mode hooks.