changes for PATH being the empty string; more minor asan fixes

This commit is contained in:
Chet Ramey
2023-03-17 16:03:11 -04:00
parent 437b73931c
commit deedd41cf4
10 changed files with 131 additions and 41 deletions
+46
View File
@@ -5661,3 +5661,49 @@ doc/{bash.1,bashref.texi}
doc/bash.1,lib/readline/doc/rluser.texi
- shell-expand-line: enumerate the specific expansions performed.
From a request by Alex Bochannek <alex@bochannek.com>
findcmd.c
- path_value: new function, returns normalized version of $PATH. Takes
a single argument saying whether or not to look in the temporary
environment first. Normalizes null $PATH (PATH=) into ".". From a
bug-bash discussion started by Moshe Looks <moshe.looks@gmail.com>
- _find_user_command_in_path: use path_value()
- user_command_matches: use path_value()
- search_for_command: if PATH[0] == 0, set PATH = "." like path_value().
This has the side effect of calling command_not_found_handle when
PATH is the empty string and the command isn't in the current
directory
- search_for_command: if path == 0, but we found an executable in the
current directory, make sure to set dot_found_in_search before adding
it to the command hash table
findcmd.h
- path_value: extern declaration
bashline.c
- command_word_completion_function: use path_value()
builtins/enable.def
- dyn_load_builtin: use path_value for BASH_LOADABLES_PATH; it's cleaner
though it doesn't change the behavior
3/17
----
bashline.c
- bashline_reset: reset rl_filename_quoting_function, since there is a
SIGINT code path where it could remain reset by glob completion.
Reported by Grisha Levit <grishalevit@gmail.com>
- command_word_completion_function,command_subst_completion_function,
glob_complete_word: set some static variables to NULL
after freeing them so they don't potentially get freed twice after
a SIGINT during completion
Reported by Grisha Levit <grishalevit@gmail.com>
parse.y
- read_token_word: when deciding how to quote translated strings, don't
free ttok before comparing it to ttrans
Reported by Grisha Levit <grishalevit@gmail.com>
- parse_matched_pair: same thing for freeing nestret
- read_token: if we return a newline, make sure we call set_word_top()
if necessary.
Fixes underflow reported by Grisha Levit <grishalevit@gmail.com>
+12 -6
View File
@@ -686,6 +686,8 @@ bashline_reset (void)
rl_filename_quote_characters = default_filename_quote_characters;
set_filename_bstab (rl_filename_quote_characters);
rl_filename_quoting_function = bash_quote_filename;
set_directory_hook ();
rl_filename_stat_hook = bash_filename_stat_hook;
@@ -1922,12 +1924,8 @@ executable_completion (const char *filename, int searching_path)
/* This gets an unquoted filename, so we need to quote special characters
in the filename before the completion hook gets it. */
#if 0
f = savestring (filename);
#else
c = 0;
f = bash_quote_filename ((char *)filename, SINGLE_MATCH, &c);
#endif
bash_directory_completion_hook (&f);
r = searching_path ? executable_file (f) : executable_or_directory (f);
@@ -1970,6 +1968,7 @@ command_word_completion_function (const char *hint_text, int state)
free (dequoted_hint);
if (hint)
free (hint);
dequoted_hint = hint = (char *)NULL;
mapping_over = searching_path = 0;
hint_is_dir = CMD_IS_DIR (hint_text);
@@ -2064,7 +2063,7 @@ command_word_completion_function (const char *hint_text, int state)
if (rl_completion_found_quote && rl_completion_quote_character == 0)
dequoted_hint = bash_dequote_filename (hint, 0);
path = get_string_value ("PATH");
path = path_value ("PATH", 0);
path_index = dot_in_path = 0;
/* Initialize the variables for each type of command word. */
@@ -2252,6 +2251,7 @@ globword:
free (fnhint);
if (filename_hint)
free (filename_hint);
fnhint = filename_hint = (char *)NULL;
filename_hint = sh_makepath (current_path, hint, 0);
/* Need a quoted version (though it doesn't matter much in most
@@ -2347,6 +2347,7 @@ globword:
t1 = make_absolute (val, t);
free (t);
cval = sh_canonpath (t1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
free (t1);
}
else
#endif
@@ -2397,7 +2398,10 @@ command_subst_completion_function (const char *text, int state)
start_len = text - orig_start;
filename_text = savestring (text);
if (matches)
free (matches);
{
free (matches);
matches = (char **)NULL;
}
/*
* At this point we can entertain the idea of re-parsing
@@ -3873,9 +3877,11 @@ glob_complete_word (const char *text, int state)
{
rl_filename_completion_desired = 1;
FREE (matches);
matches = (char **)NULL;
if (globorig != globtext)
FREE (globorig);
FREE (globtext);
globorig = globtext = (char *)NULL;
ttext = bash_tilde_expand (text, 0);
+1 -15
View File
@@ -1,7 +1,7 @@
This file is cd.def, from which is created cd.c. It implements the
builtins "cd" and "pwd" in Bash.
Copyright (C) 1987-2022 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -390,20 +390,6 @@ cd_builtin (WORD_LIST *list)
else
free (temp);
}
#if 0
/* changed for bash-4.2 Posix cd description steps 5-6 */
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
try the current directory, so we just punt now with an error
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
is so we don't mistakenly treat a CDPATH value of "" as not
specifying the current directory. */
if (posixly_correct && cdpath[0])
{
builtin_error ("%s: %s", dirname, strerror (ENOENT));
return (EXECUTION_FAILURE);
}
#endif
}
else
dirname = list->word->word;
+1 -1
View File
@@ -336,7 +336,7 @@ dyn_load_builtin (WORD_LIST *list, int flags, char *filename)
handle = 0;
if (absolute_program (filename) == 0)
{
loadables_path = get_string_value ("BASH_LOADABLES_PATH");
loadables_path = path_value ("BASH_LOADABLES_PATH", 1);
if (loadables_path)
{
load_path = find_in_path (filename, loadables_path, FS_NODIRS|FS_EXEC_PREFERRED);
+1
View File
@@ -139,6 +139,7 @@
/* Define as 1 if you want to enable code that implements multiple coprocs
executing simultaneously */
/* TAG: bash-5.3 */
#ifndef MULTIPLE_COPROCS
# define MULTIPLE_COPROCS 0
#endif
+34 -9
View File
@@ -248,6 +248,23 @@ find_path_file (const char *name)
return (find_user_command_internal (name, FS_READABLE));
}
/* Get $PATH and normalize it. USE_TEMPENV, if non-zero, says to look in the
temporary environment first. Normalizing means converting PATH= into ".". */
char *
path_value (const char *pathvar, int use_tempenv)
{
SHELL_VAR *var;
char *path;
var = use_tempenv ? find_variable_tempenv (pathvar) : find_variable (pathvar);
path = var ? value_cell (var) : (char *)NULL;
if (path == 0 || *path)
return (path);
else /* *path == '\0' */
return ".";
}
static char *
_find_user_command_internal (const char *name, int flags)
{
@@ -256,12 +273,9 @@ _find_user_command_internal (const char *name, int flags)
/* Search for the value of PATH in both the temporary environments and
in the regular list of variables. */
if (var = find_variable_tempenv ("PATH")) /* XXX could be array? */
path_list = value_cell (var);
else
path_list = (char *)NULL;
path_list = path_value ("PATH", 1);
if (path_list == 0 || *path_list == '\0')
if (path_list == 0)
return (savestring (name));
cmd = find_user_command_in_path (name, path_list, flags, (int *)0);
@@ -364,7 +378,11 @@ search_for_command (const char *pathname, int flags)
if (flags & CMDSRCH_STDPATH)
path_list = conf_standard_path ();
else if (temp_path || path)
path_list = value_cell (path);
{
path_list = value_cell (path);
if (path_list && *path_list == '\0')
path_list = ".";
}
else
path_list = 0;
@@ -377,6 +395,11 @@ search_for_command (const char *pathname, int flags)
table unless it's an executable file in the current directory. */
if (STREQ (command, pathname))
{
if (path_list == 0)
{
dot_found_in_search = 1;
st = file_status (pathname);
}
if (st & FS_EXECABLE)
phash_insert ((char *)pathname, command, dot_found_in_search, 1);
}
@@ -439,8 +462,8 @@ user_command_matches (const char *name, int flags, int state)
dot_found_in_search = 0;
if (stat (".", &dotinfo) < 0)
dotinfo.st_dev = dotinfo.st_ino = 0; /* so same_file won't match */
path_list = get_string_value ("PATH");
path_index = 0;
path_list = path_value ("PATH", 0);
path_index = 0;
}
while (path_list && path_list[path_index])
@@ -573,7 +596,9 @@ find_in_path_element (const char *name, char *path, int flags, size_t name_len,
/* This does the dirty work for find_user_command_internal () and
user_command_matches ().
NAME is the name of the file to search for.
PATH_LIST is a colon separated list of directories to search.
PATH_LIST is a colon separated list of directories to search. It is the
caller's responsibility to pass a non-empty path if they want an empty
path to be treated specially.
FLAGS contains bit fields which control the files which are eligible.
Some values are:
FS_EXEC_ONLY: The file must be an executable to be found.
+1
View File
@@ -35,6 +35,7 @@ extern int executable_or_directory (const char *);
extern char *find_user_command (const char *);
extern char *find_in_path (const char *, char *, int);
extern char *find_path_file (const char *);
extern char *path_value (const char *, int);
extern char *search_for_command (const char *, int);
extern char *user_command_matches (const char *, int, int);
extern void setup_exec_ignore (const char *);
+16 -5
View File
@@ -3470,6 +3470,9 @@ read_token (int command)
parser_state &= ~PST_ASSIGNOK;
parser_state &= ~PST_CMDBLTIN;
if (last_read_token == IF || last_read_token == WHILE || last_read_token == UNTIL)
set_word_top (last_read_token);
return (character);
}
@@ -3906,7 +3909,6 @@ parse_matched_pair (int qc, int open, int close, size_t *lenp, int flags)
/* Locale expand $"..." here. */
/* PST_NOEXPAND */
ttrans = locale_expand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
free (nestret);
/* If we're supposed to single-quote translated strings,
check whether the translated result is different from
@@ -3914,6 +3916,7 @@ parse_matched_pair (int qc, int open, int close, size_t *lenp, int flags)
if (singlequote_translations &&
((nestlen - 1) != ttranslen || STREQN (nestret, ttrans, ttranslen) == 0))
{
free (nestret);
if ((rflags & P_DQUOTE) == 0)
nestret = sh_single_quote (ttrans);
else if ((rflags & P_DQUOTE) && (dolbrace_state == DOLBRACE_QUOTE2) && (flags & P_DOLBRACE))
@@ -3923,7 +3926,10 @@ parse_matched_pair (int qc, int open, int close, size_t *lenp, int flags)
nestret = sh_backslash_quote_for_double_quotes (ttrans, 0);
}
else
nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
{
free (nestret);
nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
}
free (ttrans);
nestlen = strlen (nestret);
retind -= 2; /* back up before the $" */
@@ -5228,15 +5234,20 @@ read_token_word (int character)
/* PST_NOEXPAND */
/* Try to locale-expand the converted string. */
ttrans = locale_expand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
free (ttok);
/* Add the double quotes back (or single quotes if the user
has set that option). */
if (singlequote_translations &&
((ttoklen - 1) != ttranslen || STREQN (ttok, ttrans, ttranslen) == 0))
ttok = sh_single_quote (ttrans);
{
free (ttok);
ttok = sh_single_quote (ttrans);
}
else
ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
{
free (ttok);
ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
}
free (ttrans);
ttrans = ttok;
+9 -3
View File
@@ -31,11 +31,17 @@ trap -- '' SIGTERM
trap -- 'echo USR1' SIGUSR1
USR1
EXIT
./execscript: line 71: notthere: No such file or directory
./execscript: line 71: notthere: command not found
127
./execscript: line 74: notthere: No such file or directory
./execscript: line 73: notthere: command not found
127
./execscript: line 77: notthere: command not found
./execscript: line 75: notthere: command not found
127
./execscript: line 81: notthere: command not found
127
./execscript: line 83: notthere: command not found
127
./execscript: line 85: notthere: command not found
127
this is sh
this is sh
+10 -2
View File
@@ -65,15 +65,23 @@ ${THIS_SH} ./exec3.sub
rm -f $TMPDIR/bashenv
unset BASH_ENV
# these results should be the same as with an empty PATH
PATH=.
notthere
echo $?
command notthere
echo $?
command -p notthere
echo $?
# we're resetting the $PATH to empty, so this should be last
PATH=
notthere
echo $?
command notthere
echo $?
command -p notthere
echo $?