[git commit] ash: remove limitation on fd# length

Denys Vlasenko vda.linux at googlemail.com
Fri Jul 12 20:28:25 UTC 2024


commit: https://git.busybox.net/busybox/commit/?id=08fb86726b508eb99502a6681da94395c4e4580c
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

"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 at googlemail.com>
---
 shell/ash.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index 39455c7c5..9da3e956a 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -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;


More information about the busybox-cvs mailing list