A user reports: I know this code is wrong but it shouldn't cause the shell to exit: echo text >&9999 This instead cause the creation of a file: echo text >&9999999999
I think it would be better if they report Bad file descriptor The first case happens because save_fd_on_redirect() causes an exit when dup_CLOEXEC() returns any error other than EBADF. Despite its name dup_CLOEXEC() actually uses fcntl(2) which returns EINVAL when the file descriptor is greater than the maximum allowed. The second case is due to any numeric string longer than nine digits being treated as a file name rather than a number. Bash doesn't do this. Treat a numeric string of any length as a number and limit the range of valid file descriptors to the maximum determined by calling getrlimit(2). function old new delta fixredir - 174 +174 readtoken1 3059 3069 +10 .rodata 99930 99916 -14 isdigit_str9 45 - -45 expredir 225 177 -48 parsefname 206 157 -49 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/3 up/down: 184/-156) Total: 28 bytes Signed-off-by: Ron Yorston <r...@pobox.com> --- shell/ash.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index ef4a47afe..31ad03e47 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -535,10 +535,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'); } @@ -9635,7 +9634,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"); @@ -11945,19 +11944,21 @@ static void fixredir(union node *n, const char *text, int err) { int fd; + struct rlimit limit; TRACE(("Fix redir %s %d\n", text, err)); if (!err) n->ndup.vname = NULL; + getrlimit(RLIMIT_NOFILE, &limit); fd = bb_strtou(text, NULL, 10); - if (!errno && fd >= 0) + if (!errno && fd >= 0 && fd < limit.rlim_cur - 1) n->ndup.dupfd = fd; else if (LONE_DASH(text)) n->ndup.dupfd = -1; else { if (err) - raise_error_syntax("bad fd number"); + raise_error_syntax(strerror(EBADF)); n->ndup.vname = makename(); } } @@ -12640,7 +12641,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; -- 2.35.1 _______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox