zsh-users / zsh-syntax-highlighting

Fish shell like syntax highlighting for Zsh.
github.com/zsh-users/zsh-syntax-highlighting
BSD 3-Clause "New" or "Revised" License
19.8k stars 1.32k forks source link

[PATCH] Hangs when zsh is started under non-existent PWD #819

Open danielshahaf opened 3 years ago

danielshahaf commented 3 years ago

To reproduce:

$ cd "$(mktemp -d)"
$ rm -rf -- "$(pwd)"
$ zsh -f
% source /path/to/zsh-syntax-highlighting.zsh
% [try to type]

When I do that, the typing doesn't echo; only the first letter shows, sometimes immediately, sometimes only after a ^C.

zsh-5.8-387-gdf899d3 (3½ months old), z-sy-h current master (dffe304567c8), Linux.

The only use of $PWD in our code, other than tests, is here:

https://github.com/zsh-users/zsh-syntax-highlighting/blob/dffe304567c86f06bf1be0fce200077504e79783/highlighters/main/main-highlighter.zsh#L1234-L1245

That looks like an infinite loop.

Proposed patch:

diff --git a/highlighters/main/main-highlighter.zsh b/highlighters/main/main-highlighter.zsh
index b251a3c..8da01fd 100644
--- a/highlighters/main/main-highlighter.zsh
+++ b/highlighters/main/main-highlighter.zsh
@@ -1239,7 +1239,11 @@ _zsh_highlight_main_highlighter_check_path()
   fi
   tmp_path=$tmp_path:a

-  while [[ $tmp_path != / ]]; do
+  # Check whether $tmp_path is blacklisted.
+  #
+  # The loop will terminate when $tmp_path is the root directory (equal to "/")
+  # or starts with a dot (which can happen if $PWD doesn't exist; issue #819).
+  while [[ ${tmp_path:0:2} = /? ]]; do
     [[ -n ${(M)ZSH_HIGHLIGHT_DIRS_BLACKLIST:#$tmp_path} ]] && return 1
     tmp_path=$tmp_path:h
   done
phy1729 commented 10 months ago

It'd be nice to have a test for this; however,

if [[ $PWD != ${TMPDIR:-/tmp}/?* ]]; then
  print -r >&2 "Potentially unsafe to remove pwd: $PWD"
  return 1
fi
rm -rf -- "$PWD"

BUFFER=': possible_file'

expected_region_highlight=(
  '1 1 builtin' # :
  '3 15 default' # possible_file
)

doesn't reproduce the error as zsh keeps the current directory path in the internal pwd variable which is used by $tmp_path:a even if one does PWD=. or tries cd .. Not sure how to update pwd to . without starting a new shell which doesn't particularly fit into the test harness.