MacOS – Zsh moves texts when the prompt is too long

macoszsh

Steps to reproduce:

  1. Resize the terminal to width 80 or less, making it easier for prompt
    to wrap.

  2. Temporarily rename /etc/zshrc in case it affects outcome. (Remember
    to change it back afterwards!)

  3. Create a really deep folder, like

    mkdir -p /tmp/very-deep/directory/very-deep/directory/very-deep/directory/very-deep/directory/very-deep/directory
    
  4. Run a clean Zsh with

    /usr/bin/env -i ZDOTDIR=/tmp TERM=xterm-256color /bin/zsh
    
  5. Set prompt with PROMPT='%~ '.

  6. Change directory to that folder. The prompt should wrap.

  7. Try auto-complete. For example, type dir then hit Tab key.

On my machine, after the last step the dir was moved one character left. There was a space between prompt and command before I trigger the completion, which was eliminated by dir moving left. In other words, before I hit Tab the line ends with directory dir, but completion makes it directorydir. This behavior was similar to Bash not properly wrapping ANSI escape code with \[ and \], except that in this case there should be no ANSI escape code in prompt.

I tried eliminating all possible variables, including environment variable, configuration files, terminal emulator. What else can possibly go wrong?

In case it matters, I’m using Catalina.

Best Answer

On Catalina 10.15.3 zsh is version zsh 5.7.1 (x86_64-apple-darwin19.0).

Compiling version 5.7.1 from upstream source shows the same error while version 5.8 does not. As you can see below when setting PROMPT='%~X the X is deleted on pressing tab on dir in 5.7.1 but not 5.8.

Screenshot

The NEWS file supplied with 5.8 source says changes were made to completion functions which may explain this but in any case this bug appears to be fixed.

Several changes have been made to the way completion functions track
'precommands' (such as `command` and `env`) and determine whether the
command being completed for is a shell builtin. Developers of completion
functions may wish to familiarise themselves with `_normal -p` and
`_pick_variant -b`.

There is also this CVE included in version 5.8 so perhaps Apple will provide an update at some point if you don't wish to compile your own.

CVE-2019-20044: When unsetting the PRIVILEGED option, the shell sets its
effective user and group IDs to match their respective real IDs. On some
platforms (including Linux and macOS, but not FreeBSD), when the RUID and
EUID were both non-zero, it was possible to regain the shell's former
privileges