View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0000534 | tcsh | General | public | 2024-06-11 13:48 | 2024-06-11 13:48 |
| Reporter | MProG10 | Assigned To | |||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | new | Resolution | open | ||
| Summary | 0000534: Fix variable expansion on expressions. | ||||
| Description | It's known variables expand earlier than expression evaluations. The procedure if ( $?a && "$a" != ) echo "$a" would fail if a isn't set. The correct behavior is to evaluate $?a first, and, if expanded to zero, cancel further processing. This work remedies the issue by postponing variable expansions during expression evaluations. The function Dfix1 is used for I/O redirections, and fails if the expansion is, if not quoted, null or larger than one word/vector. I believe this behavior is fine. This work was also supposed to fix $< expansions on pipes and redirections. I had some success with a fix, but ends up blocking the shell, making it unusable and uninterruptible. | ||||
| Additional Information | https://github.com/tcsh-org/tcsh/pull/107 | ||||
| Tags | No tags attached. | ||||
|
|
sh.dol.c.diff (331 bytes)
--- a/sh.dol.c +++ b/sh.dol.c @@ -54,8 +54,6 @@ static Char *Dcp, *const *Dvp; /* Input vector for Dreadc */ #define unDgetC(c) Dpeekc = c -#define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */ - /* * The following variables give the information about the current * $ expansion, recording the current word position, the remaining sh.exp.c.diff (538 bytes)
--- a/sh.exp.c
+++ b/sh.exp.c
@@ -579,6 +579,19 @@ exp6(Char ***vp, int ignore)
etraci("exp6 {} status", getstatus(), vp);
return putn(getstatus() == 0);
}
+ for (cp = **vp; *cp; cp++)
+ if (cmap(*cp, _DOL | QUOTES)) {
+ Char *buf;
+
+ if (ignore & TEXP_IGNORE) {
+ (*vp)++;
+ return Strsave(STRNULL);
+ }
+ cleanup_push(cp = Dfix1(*(*vp)++), xfree);
+ buf = globone(cp, G_ERROR);
+ cleanup_until(cp);
+ return buf;
+ }
if (isa(**vp, ANYOP))
return (Strsave(STRNULL));
cp = *(*vp)++;
sh.h.diff (275 bytes)
--- a/sh.h +++ b/sh.h @@ -1305,5 +1305,6 @@ extern int filec; #define TEXP_IGNORE 1 /* in ignore, it means to ignore value, just parse */ #define TEXP_NOGLOB 2 /* in ignore, it means not to globone */ +#define QUOTES (_QB|_QF|_ESC) /* \ " ' ` */ #endif /* _h_sh */ sh.sem.c.diff (1,215 bytes)
--- a/sh.sem.c
+++ b/sh.sem.c
@@ -83,7 +83,7 @@ void
execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout,
int do_glob)
{
- int forked = 0;
+ int expr, forked = 0;
const struct biltins * volatile bifunc;
pid_t pid = 0;
int pv[2];
@@ -188,7 +188,11 @@ execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout,
if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
memmove(t->t_dcom[0], t->t_dcom[0] + 1,
(Strlen(t->t_dcom[0] + 1) + 1) * sizeof (*t->t_dcom[0]));
- if ((t->t_dflg & F_REPEAT) == 0)
+ if (!(expr = ((bifunc = isbfunc(t)) &&
+ (bifunc->bfunct == doexit ||
+ bifunc->bfunct == dolet ||
+ bifunc->bfunct == doif ||
+ bifunc->bfunct == dowhile))))
Dfix(t); /* $ " ' \ */
if (t->t_dcom[0] == 0) {
return;
@@ -290,10 +294,6 @@ execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout,
/* is it a command */
if (t->t_dtyp == NODE_COMMAND) {
- /*
- * Check if we have a builtin function and remember which one.
- */
- bifunc = isbfunc(t);
if (noexec) {
/*
* Continue for builtins that are part of the scripting language
|