From shigio@wafu.netgate.net  Thu Aug 13 10:50:09 1998
Received: from wafu.netgate.net (wafu.netgate.net [204.145.147.80])
          by hub.freebsd.org (8.8.8/8.8.8) with SMTP id KAA07368
          for <FreeBSD-gnats-submit@freebsd.org>; Thu, 13 Aug 1998 10:50:06 -0700 (PDT)
          (envelope-from shigio@wafu.netgate.net)
Received: (qmail 22663 invoked from network); 13 Aug 1998 09:50:18 -0000
Received: from ins69.tama-ap3.dti.ne.jp (HELO choota.signet.or.jp) (203.181.67.87)
  by wafu.netgate.net with SMTP; 13 Aug 1998 09:50:18 -0000
Received: (from shigio@localhost) by choota.signet.or.jp (8.8.7/) id CAA04744; Fri, 14 Aug 1998 02:51:57 +0900 (JST)
Message-Id: <199808131750.KAA07368@hub.freebsd.org>
Date: Fri, 14 Aug 1998 02:51:57 +0900 (JST)
From: shigio@wafu.netgate.net
Reply-To: shigio@wafu.netgate.net
To: FreeBSD-gnats-submit@freebsd.org
Cc: shigio@wafu.netgate.net
Subject: GTAGS patch for nvi has posibility of buffer overflow.
X-Send-Pr-Version: 3.2

>Number:         7607
>Category:       bin
>Synopsis:       GTAGS patch for nvi has posibility of buffer overflow.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Aug 13 11:00:00 PDT 1998
>Closed-Date:    Sat Aug 21 20:48:52 PDT 1999
>Last-Modified:  Sat Aug 21 20:49:29 PDT 1999
>Originator:     Shigio Yamaguchi
>Release:        FreeBSD 2.2.5-RELEASE i386
>Organization:
freelance programmer
>Environment:

	All environment.

>Description:

	GTAGS patch for nvi has posibility of buffer overflow.
	o gtag_slist() - sprintf() brings buffer overflow.
	o getentry() - insufficient error check and buffer size.

>How-To-Repeat:

	no

>Fix:
	
	o gtags_slist() - use snprintf() instead of sprintf().
	o getentry() - error check added and doesn't use small buffer.

	Here is a patch for /usr/src/contrib/nvi/ex/ex_tag.c.
	(FreeBSD-current, FreeBSD-stable)

*** ex_tag.c.org	Fri Aug 14 02:30:36 1998
--- ex_tag.c	Fri Aug 14 02:32:22 1998
***************
*** 47,53 ****
  static void	 ctag_file __P((SCR *, TAGF *, char *, char **, size_t *));
  static int	 ctag_search __P((SCR *, char *, size_t, char *));
  #ifdef GTAGS
! static int	 getentry __P((char *, char *, char *, char *));
  static TAGQ	*gtag_slist __P((SCR *, char *, int));
  #endif
  static int	 ctag_sfile __P((SCR *, TAGF *, TAGQ *, char *));
--- 47,53 ----
  static void	 ctag_file __P((SCR *, TAGF *, char *, char **, size_t *));
  static int	 ctag_search __P((SCR *, char *, size_t, char *));
  #ifdef GTAGS
! static int	 getentry __P((char *, char **, char **, char **));
  static TAGQ	*gtag_slist __P((SCR *, char *, int));
  #endif
  static int	 ctag_sfile __P((SCR *, TAGF *, TAGQ *, char *));
***************
*** 1013,1042 ****
   */
  static int
  getentry(buf, tag, file, line)
! 	char *buf, *tag, *file, *line;
  {
! 	char *p;
  
! 	p = tag;
! 	while (*buf && !isspace(*buf))		/* tag name */
! 		*p++ = *buf++;
! 	*p = 0;
! 	while (*buf && isspace(*buf))		/* skip blanks */
! 		buf++;
! 	p = line;
! 	while (*buf && !isspace(*buf))		/* line no */
! 		*p++ = *buf++;
! 	*p = 0;
! 	while (*buf && isspace(*buf))		/* skip blanks */
! 		buf++;
! 	p = file;
! 	while (*buf && !isspace(*buf))		/* file name */
! 		*p++ = *buf++;
	*p = 0;
  
	/* value check */
! 	if (strlen(tag) && strlen(line) && strlen(file) && atoi(line) > 0)
		return 1;	/* OK */
	return 0;		/* ERROR */
  }
  
--- 1013,1052 ----
   */
  static int
  getentry(buf, tag, file, line)
! 	char *buf, **tag, **file, **line;
  {
! 	char *p = buf;
  
! 	for (*tag = p; *p && !isspace(*p); p++)		/* tag name */
! 		;
! 	if (*p == 0)
! 		goto err;
! 	*p++ = 0;
! 	for (; *p && isspace(*p); p++)			/* (skip blanks) */
! 		;
! 	if (*p == 0)
! 		goto err;
! 	*line = p;					/* line no */
! 	for (*line = p; *p && !isspace(*p); p++)
! 		;
! 	if (*p == 0)
! 		goto err;
! 	*p++ = 0;
! 	for (; *p && isspace(*p); p++)			/* (skip blanks) */
! 		;
! 	if (*p == 0)
! 		goto err;
! 	*file = p;					/* file name */
! 	for (*file = p; *p && !isspace(*p); p++)
! 		;
! 	if (*p == 0)
! 		goto err;
	*p = 0;
  
	/* value check */
! 	if (strlen(*tag) && strlen(*line) && strlen(*file) && atoi(*line) > 0)
		return 1;	/* OK */
+ err:
	return 0;		/* ERROR */
  }
  
***************
*** 1056,1064 ****
	size_t len;
	int echk;
	TAG *tp;
! 	static char name[80], file[200], line[10];
! 	char command[200];
! 	char buf[BUFSIZ+1];
	FILE *fp;
  
	/* Allocate and initialize the tag queue structure. */
--- 1066,1074 ----
	size_t len;
	int echk;
	TAG *tp;
! 	char *name, *file, *line;
! 	char command[BUFSIZ];
! 	char buf[BUFSIZ];
	FILE *fp;
  
	/* Allocate and initialize the tag queue structure. */
***************
*** 1072,1078 ****
	 * Find the tag, only display missing file messages once, and
	 * then only if we didn't find the tag.
	 */
! 	sprintf(command, "global -%s '%s'", ref ? "rx" : "x", tag);
	if (fp = popen(command, "r")) {
		while (fgets(buf, sizeof(buf), fp)) {
			if (buf[strlen(buf)-1] == '\n')		/* chop(buf) */
--- 1082,1088 ----
	 * Find the tag, only display missing file messages once, and
	 * then only if we didn't find the tag.
	 */
! 	snprintf(command, sizeof(command), "global -%s '%s'", ref ? "rx" : "x", tag);
	if (fp = popen(command, "r")) {
		while (fgets(buf, sizeof(buf), fp)) {
			if (buf[strlen(buf)-1] == '\n')		/* chop(buf) */
***************
*** 1080,1086 ****
			else
				while (fgetc(fp) != '\n')
					;
! 			if (getentry(buf, name, file, line) == 0) {
				echk = 1;
				F_SET(tfp, TAGF_ERR);
				break;
--- 1090,1096 ----
			else
				while (fgetc(fp) != '\n')
					;
! 			if (getentry(buf, &name, &file, &line) == 0) {
				echk = 1;
				F_SET(tfp, TAGF_ERR);
				break;
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: hoek 
State-Changed-When: Sat Aug 21 20:48:52 PDT 1999 
State-Changed-Why:  
Patch committed to -current.  I hope to merge it in time for 3.3-release. 
>Unformatted:
