Skip to content

Bug in backup-walker-get-sorted-backups / backup-walker-get-version #4

@phil-s

Description

@phil-s

This library seems very nice (thanks!), but I immediately hit a bug testing it with Emacs default settings, in which backups are stored in the same directory as the original file.

This results in the call to (file-name-all-completions file dir) in backup-walker-get-sorted-backups including the original filename as well as the backup filenames, and consequently triggers an error in backup-walker-get-version due to the unhandled edge case whereby string-match doesn't return a match, and (match-end 0) then gives us something arbitrary from a previous match, which might be a larger number than the length of the filename, and therefore substring fails (or returns a bad value).

Code is:

(defsubst backup-walker-get-version (fn &optional start)
  "return version number given backup"
  (setq start (or start
                  (length (file-name-sans-versions fn))))
  (string-to-number
   (substring fn
              (string-match "[[:digit:]]+" fn start)
              (match-end 0))))

And:

(defun backup-walker-get-sorted-backups (filename)
  ;; [...]
  (let* ((filename (file-name-sans-versions
                    (make-backup-file-name (expand-file-name filename))))
         (file (file-name-nondirectory filename))
         (dir  (file-name-directory    filename))
         (comp (file-name-all-completions file dir))
         (prefix-len (length file)))
    (cons filename (mapcar
                    (lambda (f)
                      (substring (cdr f) prefix-len))
                    (sort (mapcar (lambda (f)
                                    (cons (backup-walker-get-version f prefix-len)
                                          f))
                                  comp)
                          (lambda (f1 f2)
                            (not (< (car f1) (car f2)))))))))

It seems like we can resolve this with the following change to that latter function:

-         (comp (file-name-all-completions file dir))
+         (comp (delete file (file-name-all-completions file dir)))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions