bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

hash -l with empty hash table prints to stdout


From: beluro
Subject: hash -l with empty hash table prints to stdout
Date: Mon, 15 Jun 2020 22:47:17 +0200
User-agent: Mutt/1.10.1 (2018-07-13)

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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]