Don't send multiline commands as messages in ERC

* lisp/erc/erc.el (erc-command-regexp): Relocate from further down in
same file.
(erc--check-prompt-input-for-multiline-command): Reject slash commands
containing multiple lines during input validation and before running
additional hooks.
(erc--discard-trailing-multiline-nulls): Don't mark input that begins
with a possible "slash command" as constituting a plain message just
because it has a trailing newline.  It's relatively easy to add a
newline by accident, which can result in the unintended sharing of a
command line.  Also, ERC already has a /SAY command that allows a user
to send a message starting a literal command.
* test/lisp/erc/erc-tests.el (erc-send-whitespace-lines): Fix test to
expect validation error when non-blank lines follow a slash command.
(Bug#62947)
This commit is contained in:
F. Jason Park 2023-04-17 23:09:49 -07:00
parent b0d761be0f
commit 1630656770
2 changed files with 27 additions and 12 deletions

View file

@ -6082,6 +6082,9 @@ submitted line to be intentional."
(defvar erc--input-line-delim-regexp (rx (| (: (? ?\r) ?\n) ?\r)))
(defvar erc-command-regexp "^/\\([A-Za-z']+\\)\\(\\s-+.*\\|\\s-*\\)$"
"Regular expression used for matching commands in ERC.")
(defun erc--blank-in-multiline-input-p (lines)
"Detect whether LINES contains a blank line.
When `erc-send-whitespace-lines' is in effect, return nil if
@ -6131,11 +6134,19 @@ is empty or consists of one or more spaces, tabs, or form-feeds."
(erc-command-no-process-p string))
"ERC: No process running"))
(defun erc--check-prompt-input-for-multiline-command (line lines)
"Return non-nil when non-blank lines follow a command line."
(when (and (cdr lines)
(string-match erc-command-regexp line)
(seq-drop-while #'string-empty-p (reverse (cdr lines))))
"Excess input after command line"))
(defvar erc--check-prompt-input-functions
'(erc--check-prompt-input-for-point-in-bounds
erc--check-prompt-input-for-multiline-blanks
erc--check-prompt-input-for-running-process
erc--check-prompt-input-for-excess-lines)
erc--check-prompt-input-for-excess-lines
erc--check-prompt-input-for-multiline-command)
"Validators for user input typed at prompt.
Called with latest input string submitted by user and the list of
lines produced by splitting it. If any member function returns
@ -6190,19 +6201,15 @@ When the returned value is a string, pass it to `erc-error'.")
erc-input-marker
(erc-end-of-input-line)))
(defvar erc-command-regexp "^/\\([A-Za-z']+\\)\\(\\s-+.*\\|\\s-*\\)$"
"Regular expression used for matching commands in ERC.")
(defun erc--discard-trailing-multiline-nulls (state)
"Ensure last line of STATE's string is non-null.
But only when `erc-send-whitespace-lines' is non-nil. STATE is
an `erc--input-split' object."
(when (and erc-send-whitespace-lines (erc--input-split-lines state))
(let ((reversed (nreverse (erc--input-split-lines state))))
(when (string-empty-p (car reversed))
(pop reversed)
(setf (erc--input-split-cmdp state) nil))
(nreverse (seq-drop-while #'string-empty-p reversed)))))
(while (and reversed (string-empty-p (car reversed)))
(setq reversed (cdr reversed)))
(setf (erc--input-split-lines state) (nreverse reversed)))))
(defun erc-send-input (input &optional skip-ws-chk)
"Treat INPUT as typed in by the user.

View file

@ -1236,15 +1236,23 @@
(pcase-dolist (`(,p . ,q)
'(("/a b\r" "/a b\n") ("/a b\n" "/a b\n")
("/a b\n\n" "/a b\n") ("/a b\r\n" "/a b\n")
("a b\nc\n\n" "c\n" "a b\n")
("/a b\nc\n\n" "c\n" "/a b\n")
("/a b\n\nc\n\n" "c\n" "\n" "/a b\n")))
("/a b\n\n\n" "/a b\n")))
(insert p)
(erc-send-current-line)
(erc-bol)
(should (eq (point) (point-max)))
(while q
(should (equal (funcall next) (list (pop q) nil t))))
(should (pcase (funcall next)
(`(,cmd ,_ nil) (equal cmd (pop q))))))
(should-not (funcall next))))
(ert-info ("Multiline command with non-blanks errors")
(dolist (p '("/a b\nc\n\n" "/a b\n/c\n\n" "/a b\n\nc\n\n"
"/a\n c\n" "/a\nb\n" "/a\n/b\n" "/a \n \n"))
(insert p)
(should-error (erc-send-current-line))
(goto-char erc-input-marker)
(delete-region (point) (point-max))
(should-not (funcall next))))
(ert-info ("Multiline hunk with trailing whitespace not filtered")