ash: remove limitation on fd# length

"echo text >&0000000000002" works as you would expect,
"echo text >&9999999999" properly fails instead of creating a file
named "9999999999".

function                                             old     new   delta
expredir                                             219     232     +13
readtoken1                                          3045    3053      +8
parsefname                                           204     201      -3
isdigit_str9                                          45       -     -45
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 2/1 up/down: 21/-48)            Total: -27 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
master
Denys Vlasenko 2024-07-12 22:28:25 +02:00
parent 0829fce079
commit 08fb86726b
1 changed files with 13 additions and 7 deletions

View File

@ -557,10 +557,9 @@ static void trace_vprintf(const char *fmt, va_list va);
#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
static int
isdigit_str9(const char *str)
isdigit_str(const char *str)
{
int maxlen = 9 + 1; /* max 9 digits: 999999999 */
while (--maxlen && isdigit(*str))
while (isdigit(*str))
str++;
return (*str == '\0');
}
@ -9661,7 +9660,7 @@ expredir(union node *n)
if (fn.list == NULL)
ash_msg_and_raise_error("redir error");
#if BASH_REDIR_OUTPUT
if (!isdigit_str9(fn.list->text)) {
if (!isdigit_str(fn.list->text)) {
/* >&file, not >&fd */
if (redir->nfile.fd != 1) /* 123>&file - BAD */
ash_msg_and_raise_error("redir error");
@ -12011,12 +12010,19 @@ fixredir(union node *n, const char *text, int err)
if (!err)
n->ndup.vname = NULL;
if (LONE_DASH(text)) {
n->ndup.dupfd = -1;
return;
}
fd = bb_strtou(text, NULL, 10);
if (!errno && fd >= 0)
n->ndup.dupfd = fd;
else if (LONE_DASH(text))
n->ndup.dupfd = -1;
else {
/* This also fails on very large numbers
* which overflow "int" - bb_strtou() does not
* silently truncate results to word width.
*/
if (err)
raise_error_syntax("bad fd number");
n->ndup.vname = makename();
@ -12702,7 +12708,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
&& quotef == 0
) {
if (isdigit_str9(out)) {
if (isdigit_str(out)) {
PARSEREDIR(); /* passed as params: out, c */
lasttoken = TREDIR;
return lasttoken;