From af0432abc89763bcd1b204fa83506aacfb1e911c Mon Sep 17 00:00:00 2001
Message-Id: <af0432abc89763bcd1b204fa83506aacfb1e911c.1645978829.git.auerswal@unix-ag.uni-kl.de>
In-Reply-To: <cover.1645978829.git.auerswal@unix-ag.uni-kl.de>
References: <20220221180158.GA18107@unix-ag.uni-kl.de>
	<cover.1645978829.git.auerswal@unix-ag.uni-kl.de>
From: Erik Auerswald <auerswal@unix-ag.uni-kl.de>
Date: Sun, 27 Feb 2022 16:04:17 +0100
Subject: [PATCH 3/3] telnet: Avoid command evaluation crashes.
To: ams@gnu.org
Cc: bug-inetutils@gnu.org,
    jmayer@loplof.de

Avoid crashing when given unexpected or invalid commands.
Reported by Peter Kasza in
<https://lists.gnu.org/archive/html/bug-inetutils/2017-06/msg00000.html>,
AiDai in
<https://savannah.gnu.org/bugs/?61725> and
<https://savannah.gnu.org/bugs/?61726>,
and ZFeiXQ in
<https://lists.gnu.org/archive/html/bug-inetutils/2021-12/msg00017.html>.

* NEWS: Mention fixes.
* libtelnet/genget.c (genget): Don't accept a single space as
command name.  Return &ambiguous for duplicated command names.
* telnet/commands.c: Define TELNET_MAX_ARGS and use it for *margv[].
(makeargv): Ignore arguments that don't fit into *margv[].
(setcmd): Don't dereference null pointer.
(unsetcmd): Don't dereference null pointer.
(cmdtab2[]): Add help text for help command.
(help): Don't dereference null pointer.
---
 NEWS               |  9 +++++++++
 libtelnet/genget.c |  4 +---
 telnet/commands.c  | 24 +++++++++++++++++++++---
 3 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/NEWS b/NEWS
index 319bb2f9..c0333253 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,15 @@ variable has exactly 44 bytes.  This concerns the CVE-2019-0053 fixes.
 Reported by Erik Auerswald in
 <https://lists.gnu.org/archive/html/bug-inetutils/2022-02/msg00004.html>.
 
+Avoid crashing when given unexpected or invalid commands.  Reported by
+Peter Kasza in
+<https://lists.gnu.org/archive/html/bug-inetutils/2017-06/msg00000.html>,
+AiDai in
+<https://savannah.gnu.org/bugs/?61725>,
+<https://savannah.gnu.org/bugs/?61726>,
+and ZFeiXQ in
+<https://lists.gnu.org/archive/html/bug-inetutils/2021-12/msg00017.html>.
+
 ** Various bugs fixes, internal improvements and clean ups.
 
 Further cleanup of configure.ac, updates to modern autoconf releases,
diff --git a/libtelnet/genget.c b/libtelnet/genget.c
index 6051f7b4..c2b0a37a 100644
--- a/libtelnet/genget.c
+++ b/libtelnet/genget.c
@@ -87,7 +87,7 @@ genget (char *name, char **table, int stlen)
   register char **c, **found;
   register int n;
 
-  if (name == 0)
+  if (name == 0 || (name[0] == ' ' && name[1] == '\0'))
     return 0;
 
   found = 0;
@@ -95,8 +95,6 @@ genget (char *name, char **table, int stlen)
     {
       if ((n = isprefix (name, *c)) == 0)
 	continue;
-      if (n < 0)		/* exact match */
-	return (c);
       if (found)
 	return (&ambiguous);
       found = c;
diff --git a/telnet/commands.c b/telnet/commands.c
index 9e04944f..feb80ab0 100644
--- a/telnet/commands.c
+++ b/telnet/commands.c
@@ -132,10 +132,12 @@ typedef struct
   int needconnect;		/* Do we need to be connected to execute? */
 } Command;
 
+#define TELNET_MAX_ARGS 20
+
 static char line[256];
 static char saveline[256];
 static int margc;
-static char *margv[20];
+static char *margv[TELNET_MAX_ARGS];
 
 static void
 makeargv (void)
@@ -159,6 +161,11 @@ makeargv (void)
 	c = *++cp;
       if (c == '\0')
 	break;
+      if (margc + 1 >= TELNET_MAX_ARGS)
+	{
+	  fprintf (stderr, "Ignoring excess arguments\n.");
+	  break;
+	}
       *argp++ = cp;
       margc += 1;
       for (cp2 = cp; c != '\0'; c = *++cp)
@@ -1136,6 +1143,11 @@ setcmd (int argc, char *argv[])
       (*ct->handler) (argv[2]);
       printf ("%s set to \"%s\".\n", ct->name, (char *) ct->charp);
     }
+  else if (!ct->charp)
+    {
+      fprintf (stderr, "'%s': invalid argument ('set ?' for help).\n",
+	       argv[1]);
+    }
   else
     {
       if (strcmp ("off", argv[2]))
@@ -1222,6 +1234,12 @@ unsetcmd (int argc, char *argv[])
 	  (*ct->handler) (0);
 	  printf ("%s reset to \"%s\".\n", ct->name, (char *) ct->charp);
 	}
+      else if (!ct->charp)
+	{
+	  fprintf (stderr, "'%s': invalid argument ('unset ?' for help).\n",
+		   name);
+	  return 0;
+	}
       else
 	{
 	  *(ct->charp) = _POSIX_VDISABLE;
@@ -2931,7 +2949,7 @@ static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead";
 static char escapehelp[] = "deprecated command -- use 'set escape' instead";
 
 static Command cmdtab2[] = {
-  {"help", 0, help, 0},
+  {"help", helphelp, help, 0},
   {"escape", escapehelp, setescape, 0},
   {"crmod", crmodhelp, togcrmod, 0},
   {NULL, NULL, NULL, 0}
@@ -3090,7 +3108,7 @@ help (int argc, char *argv[])
 	printf ("?Ambiguous help command %s\n", arg);
       else if (c == (Command *) 0)
 	printf ("?Invalid help command %s\n", arg);
-      else
+      else if (c->help)
 	printf ("%s\n", c->help);
     }
   return 0;
-- 
2.17.1

