z icon indicating copy to clipboard operation
z copied to clipboard

Crashes when trying to cd to a directory whose name contains "["

Open fictionic opened this issue 7 years ago • 7 comments

I have my albums in directories labeled "[<date>]

", where <date> is in YYYY-MM-DD form. When trying to use z to go to them, it crashes: <pre><code>awk: cmd. line:37: (FILENAME=- FNR=268) fatal: Invalid range end: //home/<rest of file path> </code></pre> <p>This is reproducible by simply creating a directory like <code>ooooo[a-</code>, cding into it, then typing <code>z oooo</code>. It should crash with a different error:</p> <pre><code>awk: cmd. line:37: (FILENAME=- FNR=269) fatal: Unmatched [, [^, [:, [., or [=: </code></pre> <p>Or with just `ooooo['</p> <pre><code>awk: cmd. line:37: (FILENAME=- FNR=269) fatal: Invalid regular expression: </code></pre> <p>Probably a simple fix.</p>

fictionic avatar Jun 06 '17 01:06 fictionic

Found the issue. It's a simple regex bug on line 173:

gsub(/\[\(\)\[\]\|\]/, "\\\\&", clean_short) should be gsub(/[\(\)\[\]\|]/, "\\\\&", clean_short). Basically the regex was escaping the [] for no reason, making it useless. This is such a tiny change it's not even worth a pull request, is it? I'd have to make a fork and all that. It's so simple.

fictionic avatar Oct 23 '17 17:10 fictionic

thanks - definitely a gross regex to begin with. When I wrote it there was definitely some edge cases I was sweating but they're lost in the mists of time :( I'm gonna run with this change for a bit before I push it. seems fine so far.

rupa avatar Oct 25 '17 16:10 rupa

I mean the only difference it makes is that it actually has a decent chance of matching something, since the old regex would only match strings containing [()[]|] as a substring (and then prefixes the entire thing with a single backslash). The fix just makes your original idea work. Definitely let me know when you push it! :)

fictionic avatar Oct 27 '17 23:10 fictionic

My suggested changes at #214 fix this. I'm replacing the gsub by an index call.

ericbn avatar Oct 29 '17 14:10 ericbn

Ok this is weird. The bug was introduced in https://github.com/rupa/z/commit/eda8015880106a2aef69c77a52f85b32599d4257, and it was the only change in the commit. @rupa can you give some detail on why this commit fixes a supposed problem with mawk? Or @somasis if he's around

fictionic avatar Dec 17 '17 01:12 fictionic

@fictionic, @rupa, this

gsub(/[\(\)\[\]\|]/, "\\\\&", clean_short)

is escaping special characters, so the escaped string can be used with a regular expression matching at

if( matches[x] && x !~ clean_short )

Example:

$ print '() []' | awk '{ if( $1 !~ $2 ) print "Hi" }'
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: Unmatched [, [^, [:, [., or [=: /[]/
$ print '() []' | awk '{ gsub(/[\(\)\[\]\|]/, "\\\\&", $2); if( $1 !~ $2 ) print "Hi" }'
Hi
$

This is not a good idea in many ways. First, the change done in eda8015 also broke it for GNU awk (version 4.2.0, API 2.0), so it looks like there's no universal idiom when it comes to regular expressions in awk, at least for bracket expressions like [A-Z] vs. \[A-Z\]. Second, the code is trying to do a direct string comparison, so it's much more efficient and easy to use index(s, t), which is the function awk provides to do exactly that:

index(s, t)
       the position in s where the string t occurs, or 0 if it does not.

Example:

$ print '() []' | awk '{ if( index($1, $2) == 0 ) print "Hi" }'
Hi
$

Hence my suggestion at #214. I'm introducing there another change too, which is checking if short matches only at the beginning of x, since the code is trying to check if there's a common root among the matches...

ericbn avatar Dec 18 '17 12:12 ericbn

Ok yeah I'm fully on board with your suggestion. @rupa?

fictionic avatar Dec 18 '17 18:12 fictionic