]> git.eshelyaron.com Git - emacs.git/commitdiff
; perl-mode, cperl-mode: Fix $\" in strings (Bug#69604)
authorHarald Jörg <haj@posteo.de>
Thu, 7 Mar 2024 23:37:36 +0000 (00:37 +0100)
committerEshel Yaron <me@eshelyaron.com>
Mon, 11 Mar 2024 09:15:33 +0000 (10:15 +0100)
* lisp/progmodes/perl-mode.el (perl-syntax-propertize-function):
Add to syntax-propertize-rules that $ is punctuation in strings.

* lisp/progmodes/cperl-mode.el (cperl-find-pods-heres): capture $\
to catch the edge case of "$\"".  Make $ a punctuation char in
strings and comments.

* test/lisp/progmodes/cperl-mode-tests.el (cperl-test-bug-69604):
New testcases with various combinations of $ " \

(cherry picked from commit 00f86833ac5423d57825213ef8b611978be0a3eb)

lisp/progmodes/cperl-mode.el
lisp/progmodes/perl-mode.el
test/lisp/progmodes/cperl-mode-tests.el

index 113eed64917f5354db871c883294759513d01a5e..10ac80dffd57d18c63538f4f22771c12499e3e84 100644 (file)
@@ -4014,7 +4014,10 @@ recursive calls in starting lines of here-documents."
                ;; 1+6+2+1+1+6+1+1+1=20 extra () before this:
                "\\|"
                 ;; -------- backslash-escaped stuff, don't interpret it
-               "\\\\\\(['`\"($]\\)")   ; BACKWACKED something-hairy
+               "\\\\\\(['`\"($]\\)"    ; BACKWACKED something-hairy
+                "\\|"
+                ;; -------- $\ is a variable in code, but not in a string
+                "\\(\\$\\\\\\)")
             "")))
          warning-message)
     (unwind-protect
@@ -4068,7 +4071,12 @@ recursive calls in starting lines of here-documents."
                  (cperl-modify-syntax-type bb cperl-st-punct)))
               ;; No processing in strings/comments beyond this point:
               ((or (nth 3 state) (nth 4 state))
-               t)                      ; Do nothing in comment/string
+                ;; Edge case: In a double-quoted string, $\ is not the
+                ;; punctuation variable, $ must not quote \ here.  We
+                ;; generally make $ a punctuation character in strings
+                ;; and comments (Bug#69604).
+                (when (match-beginning 22)
+                  (cperl-modify-syntax-type (match-beginning 22) cperl-st-punct)))
               ((match-beginning 1)     ; POD section
                ;;  "\\(\\`\n?\\|^\n\\)="
                (setq b (match-beginning 0)
index f74390841fed2f1c4d82e8eb9079301310982f5e..f6c4dbed1e2dfddd3947a59e511aba71339fffc8 100644 (file)
       ;; correctly the \() construct (Bug#11996) as well as references
       ;; to string values.
       ("\\(\\\\\\)['`\"($]" (1 (unless (nth 3 (syntax-ppss))
-                                       (string-to-syntax "."))))
+                                 (string-to-syntax "."))))
+      ;; A "$" in Perl code must escape the next char to protect against
+      ;; misinterpreting Perl's punctuation variables as unbalanced
+      ;; quotes or parens.  This is not needed in strings and broken in
+      ;; the special case of "$\"" (Bug#69604).  Make "$" a punctuation
+      ;; char in strings.
+      ("\\$" (0 (if (save-excursion
+                      (nth 3 (syntax-ppss (match-beginning 0))))
+                    (string-to-syntax ".")
+                  (string-to-syntax "/"))))
       ;; Handle funny names like $DB'stop.
       ("\\$ ?{?\\^?[_[:alpha:]][_[:alnum:]]*\\('\\)[_[:alpha:]]" (1 "_"))
       ;; format statements
index 62b7fdab7f778a8411a2bdca0498be7dc3430fb4..9d9718f719cc637e3551914436cb00c249ce1051 100644 (file)
@@ -1431,6 +1431,25 @@ cperl-mode fontifies text after the delimiter as Perl code."
     (should (equal (get-text-property (point) 'face)
                    font-lock-comment-face))))
 
+(ert-deftest cperl-test-bug-69604 ()
+  "Verify that $\" in a double-quoted string does not end the string.
+Both `perl-mode' and `cperl-mode' treat ?$ as a quoting/escaping char to
+avoid issues with punctuation variables.  In a string, however, this is
+not appropriate."
+  (let ((strings
+         '("\"$\\\"      in string ---\"; # \"" ; $ must not quote \
+           "$\"     . \" in string ---\"; # \"" ; $ must quote \
+           "\"\\$\" . \" in string ---\"; # \""))) ; \$ must not quote
+    (dolist (string strings)
+      (with-temp-buffer
+        (insert string)
+        (funcall cperl-test-mode)
+        (font-lock-ensure)
+        (goto-char (point-min))
+        (search-forward "in string")
+        (should (equal (get-text-property (point) 'face)
+                       font-lock-string-face))))))
+
 (ert-deftest test-indentation ()
   (ert-test-erts-file (ert-resource-file "cperl-indents.erts")))