Hi all,

I found that the two functions `TeX-delete-dups-by-car' and
`TeX-delete-duplicate-strings' can fall into infinite loop under certain
contition.

I'm proposing a fix, so please tell me if someone finds any problems in
it.

[How to confirm]
1. Activate AUCTeX.
2. Evaluate (TeX-delete-duplicate-strings '("nil")) or
(TeX-delete-dups-by-car '(("nil" . 1))) .  Both examples fall into
infinite loops.

[Analysis]
Since (string= "nil" nil) returns t, the loop
      (while (string= elt (cadr new))
        (setcdr new (cddr new)))
in `TeX-delete-duplicate-strings' never finishes when the list given as
the argument to the function ends with a string "nil" after sort.
Essentially the same reason applies for `TeX-delete-dups-by-car', too.

I estimate that it is quite uncommon that this bug causes a problem in
practical cases considering the ways that these functions are used, but
I still think it should be fixed.

[Possible fix]
The attached patch fixes the problem.  Although it may seem complicated,
the essential part is just the two occurence of
-    (while new
+    (while (cdr new)
only.  The rest are just plain rewrite using utility functions to reduce
code duplication.  (The reason that I moved the position of defun of
`TeX-car-string-lessp' is that the defcustom of `TeX-engine' requires
`TeX-delete-dups-by-car' at load time.  Thus all the functions used in
`TeX-delete-dups-by-car' must be defined before the defcustom.)

Any comments and suggestions are welcome.

Regards,
Ikumi Keita

diff -r 29cedaaa8cbd tex.el
--- a/tex.el	Thu Aug 31 23:39:35 2017 +0900
+++ b/tex.el	Fri Sep 01 16:55:26 2017 +0900
@@ -914,12 +914,11 @@
   "Return a list of all elements in ALIST, but each car only once.
 Elements of KEEP-LIST are not removed even if duplicate."
   ;; Copy of `reftex-uniquify-by-car' (written by David Kastrup).
-  (setq keep-list (sort (copy-sequence keep-list) #'string<))
+  (setq keep-list (TeX-sort-strings keep-list))
   (setq alist (sort (copy-sequence alist)
-		    (lambda (a b)
-		      (string< (car a) (car b)))))
+		    #'TeX-car-string-lessp))
   (let ((new alist) elt)
-    (while new
+    (while (cdr new)
       (setq elt (caar new))
       (while (and keep-list (string< (car keep-list) elt))
 	(setq keep-list (cdr keep-list)))
@@ -933,7 +932,7 @@
   "Return a list of all strings in LIST, but each only once."
   (setq list (TeX-sort-strings list))
   (let ((new list) elt)
-    (while new
+    (while (cdr new)
       (setq elt (car new))
       (while (string= elt (cadr new))
 	(setcdr new (cddr new)))
@@ -944,6 +943,11 @@
   "Return sorted list of all strings in LIST."
   (sort (copy-sequence list) #'string<))
 
+(defun TeX-car-string-lessp (s1 s2)
+  "Compare the cars of S1 and S2 in lexicographic order.
+Return t if first is less than second in lexicographic order."
+  (string-lessp (car s1) (car s2)))
+
 ;;; Buffer
 
 (defgroup TeX-output nil
@@ -4737,11 +4741,6 @@
 ;; Some of these functions has little to do with TeX, but nonetheless we
 ;; should use the "TeX-" prefix to avoid name clashes.
 
-(defun TeX-car-string-lessp (s1 s2)
-  "Compare the cars of S1 and S2 in lexicographic order.
-Return t if first is less than second in lexicographic order."
-  (string-lessp (car s1) (car s2)))
-
 (defun TeX-listify (elt)
   "Return a newly created list with element ELT.
 If ELT already is a list, return ELT."
_______________________________________________
auctex-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/auctex-devel

Reply via email to