Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -g -O2 -fdebug-prefix-map=/build/bash-2bxm7h/bash-5.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wall -Wno-parentheses -Wno-format-security uname output: Linux XXX 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2+deb10u1 (2020-06-07) x86_64 GNU/Linux Machine Type: x86_64-pc-linux-gnu
Bash Version: 5.0 Patch Level: 3 Release Status: release Description: (I used `bashbug' from my distributor's pre-compiled package, but, looking at the current bash source code, I strongly believe this bug still exists, and you can completely ignore the "Configuration Information" section above.) `hash -l' is supposed to generate output that is reusable as input (`help hash' says so, at least). In case the hash table is empty, a string not re-usable as input is output to stdout. The exit code indicates success in this case. The string being output is locale- dependant (and therefore is hard to filter out in a work-around). $ hash -r $ hash -l hash: hash table empty $ echo $? 0 $ hash -l > /dev/null # no output, the message is printed to stdout $ hash -l 2> /dev/null # the message is not printed to stderr hash: hash table empty A work-around bash function to save the current hash table (in a re- usable format) would need to do something along these lines: saved_hash_table() { local hash_table="$( LANG=C hash -l )" # Let's hope, the string for an empty hash table never changes... [[ "$hash_table" =~ "hash table empty"$ ]] && hash_table= printf %s "$hash_table" } Repeat-By: $ LANG=C bash $ hash -r $ $( hash -l ) # should always succeed, I think bash: hash:: command not found $ echo $? 127 Even weirder after creating an actual script named "hash:" (note trailing colon): $ cat /usr/local/bin/hash: #!/bin/sh echo do harm $ hash -r $ $( hash -l ) do harm Fix: I've never looked at the bash sources before, but the conundrum appears to be in line 138 in "bash-5.0/builtins/hash.def": printf (_("%s: hash table empty\n"), this_command_name); A bash script should be able to get a really re-usable output from `hash -l', at least if the return code of `hash' indicates success. So, either of the following changes should be applied: 1. (preferable, in my opinion) Output the message about the empty hash table to stderr instead of stdout, that is, change the afore-mentioned line to fprintf (stderr, _("%s: hash table empty\n"), this_command_name); Saving the hash table in a script would be something along saved_hash_table="$( hash -l 2> /dev/null )" || handle_error (not sure if any errors (needed to be handled in some cases) can happen at all here). 2. Don't output anything (or a single newline-character only) in case the hash table is empty. Saving the hash table would be simply: saved_hash_table="$( hash -l )" || handle_error with the draw-back of less informative output for interactive users. 3. Consider an empty hash table an error so at least something along the following would work: saved_hash_table="$( hash -l )" || saved_hash_table= This possibly makes other errors hard to detect, though `$saved_hash_table' would result in a loss of efficiency only, not in malfunctioning software (or a security risk, my "do harm"-example is a little lame, I confess, I currently don't quite see a real-life exploitable security bug here), so ignoring a possible error (whatever this should be) is probably a minor thing.