[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Error from substring-of-symlink in emms-source-file-directory-tree-inter

From: Mike Kazantsev
Subject: Error from substring-of-symlink in emms-source-file-directory-tree-internal
Date: Fri, 24 Jan 2020 11:32:01 +0500


Having trouble with (args-out-of-range "..." 0 23) error when adding
directory to playlist, with somewhat weird directories-through-symlinks

Tracked down this error to a line which causes it, but not entirely
sure if suggested fix would be appropriate.

How to reproduce it:

- Create this directory hierarchy:

    % mkdir -p /tmp/mp/mp-dir/mp-subdir/music-dir
    % ln -s ../mp/mp-dir /tmp/mp/mp-dir-link
    % cd /tmp/mp/mp-dir-link/mp-subdir/music-dir
    % mkdir ../music-dir-{A,B,C}
    % ln -s ../music-dir-{A,B,C} .

  I know it looks a bit convoluted, but a mock of actual configuration
  made here for convenience (with links to big mountpoint and "heap of
  unsorted stuff" dirs).

- (emms-source-directory-tree "/tmp/mp/mp-dir-link/mp-subdir/music-dir")

  Note that there should be one symlink in the middle of that
  source-dir (mp-dir-link), and symlinks to other dirs inside music-dir.

Result is this error:

  Debugger entered--Lisp error: (args-out-of-range "../music-dir-A" 0 39)
    eval((emms-source-directory-tree "/tmp/mp/mp-dir-link/mp-subdir/music-dir") 
    funcall-interactively(eval-last-sexp nil)
    call-interactively(eval-last-sexp nil nil)

I've snipped "long-file-ext-regexp" as it's very long and that's file
extension matching regexp, which afaict doesn't get used anyway -
there are no files in this mock-setup, only dirs.

Error happens in this part of emms-source-file-directory-tree-internal:

    (or (string-match "/\\.\\.?$" (car dirs))
      (let ((symlink (file-symlink-p (car dirs))))
        (and symlink
          (string-equal dir (substring symlink 0 (string-width dir))))))
    (setq dirs (cdr dirs))
    (setq dirs (condition-case nil ...)))

Specifically it's an error from (substring ...) where:

  (car dirs) = "/tmp/mp/mp-dir-link/mp-subdir/music-dir/music-dir-A"
  dir = "/tmp/mp/mp-dir-link/mp-subdir/music-dir"
  symlink = "../music-dir-A"
  (string-width dir) = 39
  (string-width symlink) = 14

So (string-width dir) goes beyond end of "symlink" string and produces
error above.

I believe purpose of that condition is to check for symlink referring
to directory itself and eliminate such loop, if that's the case.

One way to fix it can be to use:

  (substring symlink 0
    (min (string-width dir) (string-width symlink)))

But them what if it's a symlink to "music-dir-something-something" and
such (min ...) will cut it to "music-dir", resulting in t for
string-equal check, while symlink does not actually refer to same dir?

So this fix doesn't look right.

And I'm not entirely sure I'm understanding the problem correctly in
the first place, as it looks like there was a bug anyway, given that
any width can be longer than other, yet string was cut using only one
of them.

Given that it looks like something simple and maybe typical wrt
symlinks, thought I'd should ask for clarification on what this code
does and maybe what's the right way to fix it?

Also, I've seen this (args-out-of-range ...) error pop-up with
(substring ...) in other unexpected places for me, like completion
system suddenly stops working until emacs restart with no clear
backtrace (assuming it was optimized-out in .elc, same as here) and such.

So I suspect it's actually an upstream change in emacs that caused this
bug to surface - e.g. maybe (substring ...) didn't raise such error before.

But code looks bit strange to me anyway, due that
"music-dir-something-something cut to music-dir" case.

(emacs-version) gives:
  GNU Emacs 26.3 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.10) ...

I'm also a bit sleep-deprived and distracted atm, so maybe just can't
think right about the issue and it's actually a no-brainer (esp. if
it's indeed some kind of typical symlink check).

Thanks in advance for any info/clarification.

Mike Kazantsev // fraggod.net

reply via email to

[Prev in Thread] Current Thread [Next in Thread]