Subject: bin/1431: ftp coredumps if a command line has more than 20 arguments
To: None <gnats-bugs@gnats.netbsd.org>
From: John F. Woods <jfw@jfwhome.funhouse.com>
List: netbsd-bugs
Date: 09/01/1995 10:42:14
>Number:         1431
>Category:       bin
>Synopsis:       ftp coredumps if a command line has more than 20 arguments
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Sep  1 16:35:02 1995
>Last-Modified:
>Originator:     John F. Woods
>Organization:
Misanthropes-R-Us
>Release:        present in 9/1/95 sup
>Environment:
	
System: NetBSD jfwhome.funhouse.com 1.0A NetBSD 1.0A (JFW) #14: Wed Aug 9 21:35:57 EDT 1995 jfw@jfwhome.funhouse.com:/usr/src/sys/arch/i386/compile/JFW i386


>Description:
	ftp can be made to coredump if given more than 20 arguments on a
command line.  There is a fixed-length buffer of word pointers whose bounds
are not checked.
>How-To-Repeat:
    From: Jukka Marin <jmarin@teeri.jmp.fi>

    ftp in -current (950819 snapshot) does this:

    jmarin@silakka ~ %(42)ftp teeri
    Connected to teeri.jmp.fi.
    220 teeri.jmp.fi FTP server (SunOS 4.1) ready.
    Name (teeri:jmarin):
    331 Password required for jmarin.
    Password:
    230 User jmarin logged in.
    ftp> cd /tmp
    250 CWD command successful.
    ftp> lcd /tmp
    Local directory now /var/tmp
    ftp> mget a* b* c* d* e* f* g* h* i* j* k* l* m* n* o* p* q* r* s* t* u* v* w* x* y* z*
    Segmentation fault

>Fix:
A nearly-arbitrary number of arguments can be accepted by the following:

*** ftp_var.h.orig	Fri Sep  1 07:48:37 1995
--- ftp_var.h	Fri Sep  1 07:49:21 1995
***************
*** 98,104 ****
  char	argbuf[200];		/* argument storage buffer */
  char	*argbase;		/* current storage point in arg buffer */
  int	margc;			/* count of arguments on input line */
! char	*margv[20];		/* args parsed from input line */
  int     cpend;                  /* flag: if != 0, then pending server reply */
  int	mflag;			/* flag: if != 0, then active multi command */
  
--- 98,105 ----
  char	argbuf[200];		/* argument storage buffer */
  char	*argbase;		/* current storage point in arg buffer */
  int	margc;			/* count of arguments on input line */
! char	**margv;		/* args parsed from input line */
! int	maxmargc;		/* how large margv is currently */
  int     cpend;                  /* flag: if != 0, then pending server reply */
  int	mflag;			/* flag: if != 0, then active multi command */
  



*** main.c.orig	Fri Sep  1 07:48:46 1995
--- main.c	Fri Sep  1 08:00:56 1995
***************
*** 317,329 ****
  {
  	char **argp;
  
  	margc = 0;
  	argp = margv;
  	stringbase = line;		/* scan from first of buffer */
  	argbase = argbuf;		/* store from first of buffer */
  	slrflag = 0;
! 	while (*argp++ = slurpstring())
  		margc++;
  }
  
  /*
--- 317,347 ----
  {
  	char **argp;
  
+ 	if (margv == 0) {
+ 		if ((margv = malloc(20 * sizeof(char *))) == 0) {
+ 			perror("can't allocate argv array");
+ 			exit(1);
+ 		}
+ 		maxmargc = 20;
+ 	}
  	margc = 0;
  	argp = margv;
  	stringbase = line;		/* scan from first of buffer */
  	argbase = argbuf;		/* store from first of buffer */
  	slrflag = 0;
! 	while (*argp++ = slurpstring()) {
  		margc++;
+ 		if (margc == maxmargc) {
+ 			if ((margv = realloc(margv,
+ 					     (maxmargc + 20)*sizeof(char *)))
+ 			    == NULL) {
+ 				perror("can't reallocate argv array");
+ 				exit(1);
+ 			}
+ 			maxmargc += 20;
+ 			argp = margv + margc;
+ 		}
+ 	}
  }
  
  /*
>Audit-Trail:
>Unformatted: