dcb175d4309a41723ebeb561a8089115d9e7126b

Author
leycec <leycec@gmail.com>
Committer
leycec <leycec@gmail.com>
Date

Message

Insecure completion handler added.

A new "lib/compfix.zsh" script defining a new handle_completion_insecurities()
function has been added, which handles insecure completion directories by
notifying users of said insecurities and moving away all existing completion
caches to a temporary directory. While intended to be called at startup, this
function is generally callable at any time (e.g., for testing).

Diff

 1diff --git a/lib/compfix.zsh b/lib/compfix.zsh
 2new file mode 100644
 3index 0000000000000000000000000000000000000000..208aaadb1ebad0e25ebdef29192da815be8136bd
 4--- /dev/null
 5+++ b/lib/compfix.zsh
 6@@ -0,0 +1,60 @@
 7+# Handle completions insecurities (i.e., completion-dependent directories with
 8+# insecure ownership or permissions) by:
 9+#
10+# * Human-readably notifying the user of these insecurities.
11+# * Moving away all existing completion caches to a temporary directory. Since
12+#   any of these caches may have been generated from insecure directories, they
13+#   are all suspect now. Failing to do so typically causes subsequent compinit()
14+#   calls to fail with "command not found: compdef" errors. (That's bad.)
15+function handle_completion_insecurities() {
16+  # List of the absolute paths of all unique insecure directories, split on
17+  # newline from compaudit()'s output resembling:
18+  #
19+  #     There are insecure directories:
20+  #     /usr/share/zsh/site-functions
21+  #     /usr/share/zsh/5.0.6/functions
22+  #     /usr/share/zsh
23+  #     /usr/share/zsh/5.0.6
24+  #
25+  # Since the ignorable first line is printed to stderr and thus not captured,
26+  # stderr is squelched to prevent this output from leaking to the user. 
27+  local -aU insecure_dirs
28+  insecure_dirs=( ${(f@):-"$(compaudit 2>/dev/null)"} )
29+
30+  # If no such directories exist, get us out of here.
31+  if (( ! ${#insecure_dirs} )); then
32+      print "[oh-my-zsh] No insecure completion-dependent directories detected."
33+      return
34+  fi
35+
36+  # List ownership and permissions of all insecure directories.
37+  print "[oh-my-zsh] Insecure completion-dependent directories detected:"
38+  ls -ld "${(@)insecure_dirs}"
39+  print "[oh-my-zsh] For safety, completions will be disabled until you manually fix all"
40+  print "[oh-my-zsh] insecure directory permissions and ownership and restart oh-my-zsh."
41+  print "[oh-my-zsh] See the above list for directories with group or other writability.\n"
42+
43+  # Locally enable the "NULL_GLOB" option, thus removing unmatched filename
44+  # globs from argument lists *AND* printing no warning when doing so. Failing
45+  # to do so prints an unreadable warning if no completion caches exist below.
46+  setopt local_options null_glob
47+
48+  # List of the absolute paths of all unique existing completion caches.
49+  local -aU zcompdump_files
50+  zcompdump_files=( "${ZSH_COMPDUMP}"(.) "${ZDOTDIR:-${HOME}}"/.zcompdump* )
51+
52+  # Move such caches to a temporary directory.
53+  if (( ${#zcompdump_files} )); then
54+    # Absolute path of the directory to which such files will be moved.
55+    local ZSH_ZCOMPDUMP_BAD_DIR="${ZSH_CACHE_DIR}/zcompdump-bad"
56+
57+    # List such files first.
58+    print "[oh-my-zsh] Insecure completion caches also detected:"
59+    ls -l "${(@)zcompdump_files}"
60+
61+    # For safety, move rather than permanently remove such files.
62+    print "[oh-my-zsh] Moving to \"${ZSH_ZCOMPDUMP_BAD_DIR}/\"...\n"
63+    mkdir -p "${ZSH_ZCOMPDUMP_BAD_DIR}"
64+    mv "${(@)zcompdump_files}" "${ZSH_ZCOMPDUMP_BAD_DIR}/"
65+  fi
66+}