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 |