mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
changes for PATH being the empty string; more minor asan fixes
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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
@@ -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
@@ -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 $?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user