Subject: bug#31097: 27.0.50; Interprogram paste is destructively modified

From: "Basil L. Contovounesios" <[email-masked]>
Date: Fri, 13 Apr 2018 12:56:38 +0100

>From 5bde054f8c80f64c15e105e21aaddccff67d9e7a Mon Sep 17 00:00:00 2001
From: "Basil L. Contovounesios" <[email-masked]>
Date: Fri, 13 Apr 2018 12:47:30 +0100
Subject: [PATCH] Do not destructively modify interprogram paste

* simple.el (kill-new, current-kill): Non-destructively reverse list
returned by interprogram-paste-function. (bug#31097)
---
 lisp/simple.el | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lisp/simple.el b/lisp/simple.el
index efe5406bf7..19e41344d1 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -4369,7 +4369,8 @@ kill-new
                                    (funcall interprogram-paste-function))))
       (when interprogram-paste
         (dolist (s (if (listp interprogram-paste)
-		       (nreverse interprogram-paste)
+                       ;; Use `reverse' to avoid modifying external data
+                       (reverse interprogram-paste)
 		     (list interprogram-paste)))
 	  (unless (and kill-do-not-save-duplicates
 		       (equal-including-properties s (car kill-ring)))
@@ -4448,7 +4449,8 @@ current-kill
 	  ;; selection, with identical text.
 	  (let ((interprogram-cut-function nil))
 	    (if (listp interprogram-paste)
-	      (mapc 'kill-new (nreverse interprogram-paste))
+                ;; Use `reverse' to avoid modifying external data
+                (mapc #'kill-new (reverse interprogram-paste))
 	      (kill-new interprogram-paste)))
 	  (car kill-ring))
       (or kill-ring (error "Kill ring is empty"))
-- 
2.16.3

Noam Postavsky <[email-masked]> writes:

> "Basil L. Contovounesios" <[email-masked]> writes:
>
>> * simple.el (kill-new, current-kill): Non-destructively reverse list
>> returned by interprogram-paste-function. (bug#31097)
>
> Seems reasonable.  Perhaps add some comments in case someone tries to
> "optimize" it later?

Are the comments in the updated patch attached clear enough?

>>  If optional arg DO-NOT-MOVE is non-nil, then don't actually
>>  move the yanking point; just return the Nth kill forward."
>> -
>>   (let ((interprogram-paste (and (= n 0)
>
>> -      (let ((ARGth-kill-element
>> +      (let ((nth-kill-element
>>  	     (nthcdr (mod (- n (length kill-ring-yank-pointer))
>>  			  (length kill-ring))
>>  		     kill-ring)))
>>  	(unless do-not-move
>> -	  (setq kill-ring-yank-pointer ARGth-kill-element)
>> +          (setq kill-ring-yank-pointer nth-kill-element)
>>  	  (when (and yank-pop-change-selection
>>  		     (> n 0)
>>  		     interprogram-cut-function)
>> -	    (funcall interprogram-cut-function (car ARGth-kill-element))))
>> -	(car ARGth-kill-element)))))
>> +            (funcall interprogram-cut-function (car nth-kill-element))))
>> +        (car nth-kill-element)))))
>
> I don't think these hunks are needed.

Fair enough, I just thought it was strange having an ARGth element
without an ARG.

Thanks,

-- 
Basil