fix for cd when curent directory doesn't exist; fix wait -n in posix mode to delete any job that it returns; fix some variables where readonly can be circumvented; fix some overflows in printf

This commit is contained in:
Chet Ramey
2024-02-02 14:39:50 -05:00
parent 138f3cc359
commit 35465406cd
12 changed files with 263 additions and 89 deletions
+5 -2
View File
@@ -538,8 +538,11 @@ change_to_directory (char *newdir, int nolinks, int xattr)
/* TDIR is either the canonicalized absolute pathname of NEWDIR
(nolinks == 0) or the absolute physical pathname of NEWDIR
(nolinks != 0). */
tdir = nolinks ? sh_physpath (t, 0)
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
if (t && *t)
tdir = nolinks ? sh_physpath (t, 0)
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
else
tdir = NULL;
ndlen = strlen (newdir);
+66 -58
View File
@@ -1,7 +1,7 @@
This file is printf.def, from which is created printf.c.
It implements the builtin "printf" in Bash.
Copyright (C) 1997-2023 Free Software Foundation, Inc.
Copyright (C) 1997-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -105,6 +105,50 @@ $END
extern int errno;
#endif
/* We free the buffer used by mklong() if it's `too big'. */
#define PRETURN(value) \
do \
{ \
QUIT; \
retval = value; \
if (conv_bufsize > 4096 ) \
{ \
free (conv_buf); \
conv_bufsize = 0; \
conv_buf = 0; \
} \
if (vflag) \
{ \
SHELL_VAR *v; \
v = builtin_bind_variable (vname, vbuf, bindflags); \
stupidly_hack_special_variables (vname); \
if (v == 0 || readonly_p (v) || noassign_p (v)) \
retval = EXECUTION_FAILURE; \
if (vbsize > 4096) \
{ \
free (vbuf); \
vbsize = 0; \
vbuf = 0; \
} \
else if (vbuf) \
vbuf[0] = 0; \
} \
else \
{ \
if (ferror (stdout) == 0) \
fflush (stdout); \
QUIT; \
if (ferror (stdout)) \
{ \
sh_wrerror (); \
clearerr (stdout); \
retval = EXECUTION_FAILURE; \
} \
} \
return (retval); \
} \
while (0)
#define PC(c) \
do { \
char b[2]; \
@@ -120,7 +164,9 @@ extern int errno;
#define PF(f, func) \
do { \
int nw; \
clearerr (stdout); \
if (vflag == 0) \
clearerr (stdout); \
errno = 0; \
if (have_fieldwidth && have_precision) \
nw = vflag ? vbprintf (f, fieldwidth, precision, func) : printf (f, fieldwidth, precision, func); \
else if (have_fieldwidth) \
@@ -129,56 +175,17 @@ extern int errno;
nw = vflag ? vbprintf (f, precision, func) : printf (f, precision, func); \
else \
nw = vflag ? vbprintf (f, func) : printf (f, func); \
if (nw < 0 || ferror (stdout)) \
{ \
QUIT; \
if (vflag) \
builtin_error ("%s", strerror (errno)); \
PRETURN (EXECUTION_FAILURE); \
} \
tw += nw; \
QUIT; \
if (ferror (stdout)) \
{ \
sh_wrerror (); \
clearerr (stdout); \
return (EXECUTION_FAILURE); \
} \
} while (0)
/* We free the buffer used by mklong() if it's `too big'. */
#define PRETURN(value) \
do \
{ \
QUIT; \
if (vflag) \
{ \
SHELL_VAR *v; \
v = builtin_bind_variable (vname, vbuf, bindflags); \
stupidly_hack_special_variables (vname); \
if (v == 0 || readonly_p (v) || noassign_p (v)) \
return (EXECUTION_FAILURE); \
} \
if (conv_bufsize > 4096 ) \
{ \
free (conv_buf); \
conv_bufsize = 0; \
conv_buf = 0; \
} \
if (vbsize > 4096) \
{ \
free (vbuf); \
vbsize = 0; \
vbuf = 0; \
} \
else if (vbuf) \
vbuf[0] = 0; \
if (ferror (stdout) == 0) \
fflush (stdout); \
QUIT; \
if (ferror (stdout)) \
{ \
sh_wrerror (); \
clearerr (stdout); \
return (EXECUTION_FAILURE); \
} \
return (value); \
} \
while (0)
#define SKIP1 "#'-+ 0"
#define LENMODS "hjlLtz"
@@ -242,7 +249,7 @@ static int vflag = 0;
static int bindflags = 0;
static char *vbuf, *vname;
static size_t vbsize;
static int vblen;
static size_t vblen;
static intmax_t tw;
@@ -329,6 +336,7 @@ printf_builtin (WORD_LIST *list)
return ((v == 0 || readonly_p (v) || noassign_p (v)) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
/* If the format string is empty after preprocessing, return immediately. */
if (list->word->word == 0 || list->word->word[0] == '\0')
return (EXECUTION_SUCCESS);
@@ -338,10 +346,6 @@ printf_builtin (WORD_LIST *list)
garglist = orig_arglist = list->next;
/* If the format string is empty after preprocessing, return immediately. */
if (format == 0 || *format == 0)
return (EXECUTION_SUCCESS);
mb_cur_max = MB_CUR_MAX;
/* Basic algorithm is to scan the format string for conversion
@@ -793,7 +797,7 @@ printf_builtin (WORD_LIST *list)
modstart[1] = nextch;
}
if (ferror (stdout))
if (vflag == 0 && ferror (stdout))
{
/* PRETURN will print error message. */
PRETURN (EXECUTION_FAILURE);
@@ -928,7 +932,7 @@ printstr (char *fmt, char *string, int len, int fieldwidth, int precision)
for (; padlen < 0; padlen++)
PC (' ');
return (ferror (stdout) ? -1 : 0);
return ((vflag == 0 && ferror (stdout)) ? -1 : 0);
}
#if defined (HANDLE_MULTIBYTE)
@@ -1035,7 +1039,7 @@ printwidestr (char *fmt, wchar_t *wstring, size_t len, int fieldwidth, int preci
PC (' ');
free (string);
return (ferror (stdout) ? -1 : 0);
return ((vflag == 0 && ferror (stdout)) ? -1 : 0);
}
#endif
@@ -1261,7 +1265,7 @@ vbadd (char *buf, int blen)
#ifdef DEBUG
if (strlen (vbuf) != vblen)
internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
internal_error ("printf:vbadd: vblen (%zu) != strlen (vbuf) (%zu)", vblen, strlen (vbuf));
#endif
return vbuf;
@@ -1277,6 +1281,8 @@ vbprintf (const char *format, ...)
va_start (args, format);
blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
va_end (args);
if (blen < 0)
return (blen);
nlen = vblen + blen + 1;
if (nlen >= vbsize)
@@ -1286,6 +1292,8 @@ vbprintf (const char *format, ...)
va_start (args, format);
blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
va_end (args);
if (blen < 0)
return (blen);
}
vblen += blen;
@@ -1293,7 +1301,7 @@ vbprintf (const char *format, ...)
#ifdef DEBUG
if (strlen (vbuf) != vblen)
internal_error ("printf:vbprintf: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
internal_error ("printf:vbprintf: vblen (%zu) != strlen (vbuf) (%zu)", vblen, strlen (vbuf));
#endif
return (blen);
+5 -10
View File
@@ -573,17 +573,12 @@ set_shellopts (void)
v = find_variable ("SHELLOPTS");
/* Turn off the read-only attribute so we can bind the new value, and
note whether or not the variable was exported. */
if (v)
{
VUNSETATTR (v, att_readonly);
exported = exported_p (v);
}
else
exported = 0;
/* Note whether or not the variable was exported so we can adjust after the
assignment. */
exported = v ? exported_p (v) : 0;
v = bind_variable ("SHELLOPTS", value, 0);
/* ASS_FORCE so we don't have to temporarily turn off readonly */
v = bind_variable ("SHELLOPTS", value, ASS_FORCE);
/* Turn the read-only attribute back on, and turn off the export attribute
if it was set implicitly by mark_modified_vars and SHELLOPTS was not
+5 -10
View File
@@ -849,17 +849,12 @@ set_bashopts (void)
v = find_variable ("BASHOPTS");
/* Turn off the read-only attribute so we can bind the new value, and
note whether or not the variable was exported. */
if (v)
{
VUNSETATTR (v, att_readonly);
exported = exported_p (v);
}
else
exported = 0;
/* Note whether or not the variable was exported so we can adjust after the
assignment. */
exported = v ? exported_p (v) : 0;
v = bind_variable ("BASHOPTS", value, 0);
/* ASS_FORCE so we don't have to temporarily turn off readonly */
v = bind_variable ("BASHOPTS", value, ASS_FORCE);
/* Turn the read-only attribute back on, and turn off the export attribute
if it was set implicitly by mark_modified_vars and SHELLOPTS was not
+54 -1
View File
@@ -92,6 +92,7 @@ int wait_intr_flag;
static int set_waitlist (WORD_LIST *);
static void unset_waitlist (void);
static int check_bgpids (WORD_LIST *, struct procstat *);
/* Wait for the pid in LIST to stop or die. If no arguments are given, then
wait for all of the active background processes of the shell and return
@@ -210,6 +211,21 @@ wait_builtin (WORD_LIST *list)
#if defined (JOB_CONTROL)
if (nflag)
{
#if 0 /* TAG:bash-5.3 stevenpelley@gmail.com 01/22/2024 */
/* First let's see if there are any requested pids that have already
been removed from the jobs list and saved on bgpids. */
if (list)
{
status = check_bgpids (list, &pstat);
if (status != -1)
{
if (vname)
builtin_bind_var_to_int (vname, pstat.pid, bindflags);
WAIT_RETURN (status);
}
}
#endif
if (list)
{
opt = set_waitlist (list);
@@ -342,7 +358,7 @@ set_waitlist (WORD_LIST *list)
for (l = list; l; l = l->next)
{
job = NO_JOB;
job = (l && valid_number (l->word->word, &pid) && pid == (pid_t) pid)
job = (l && l->word && valid_number (l->word->word, &pid) && pid == (pid_t) pid)
? get_job_by_pid ((pid_t) pid, 0, 0)
: get_job_spec (l);
if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
@@ -376,4 +392,41 @@ unset_waitlist (void)
jobs[i]->flags &= ~J_WAITING;
UNBLOCK_CHILD (oset);
}
#if 0 /* TAG:bash-5.3 */
static int
check_bgpids (WORD_LIST *list, struct procstat *pstat)
{
sigset_t set, oset;
pid_t pid;
intmax_t ipid;
WORD_LIST *l;
int r, s;
r = -1;
BLOCK_CHILD (set, oset);
for (l = list; l; l = l->next)
{
if (l && valid_number (l->word->word, &ipid) && ipid == (pid_t) ipid)
pid = ipid;
else
continue; /* skip job ids for now */
if ((s = retrieve_proc_status (pid, 0)) != -1)
{
pstat->pid = pid;
pstat->status = r = s;
/* If running in posix mode, `wait -n pid' deletes pid from bgpids,
just like `wait pid'. */
if (posixly_correct)
delete_proc_status (pid, 0);
break;
}
}
UNBLOCK_CHILD (oset);
return r;
}
#endif
#endif