NetBSD Problem Report #50092

From www@NetBSD.org  Sun Jul 26 09:59:58 2015
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 34772A5864
	for <gnats-bugs@gnats.NetBSD.org>; Sun, 26 Jul 2015 09:59:58 +0000 (UTC)
Message-Id: <20150726095956.85BEFA6552@mollari.NetBSD.org>
Date: Sun, 26 Jul 2015 09:59:56 +0000 (UTC)
From: okuyama@flex.phys.tohoku.ac.jp
Reply-To: okuyama@flex.phys.tohoku.ac.jp
To: gnats-bugs@NetBSD.org
Subject: huge memory leaks in vi(1) when changing screen size
X-Send-Pr-Version: www-1.0

>Number:         50092
>Category:       bin
>Synopsis:       huge memory leaks in vi(1) when changing screen size
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bin-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jul 26 10:00:00 +0000 2015
>Closed-Date:    Tue May 31 06:10:57 +0000 2016
>Last-Modified:  Sun Dec 18 06:40:00 +0000 2016
>Originator:     Rin Okuyama
>Release:        7.99.20
>Organization:
Department of Physics, Tohoku University
>Environment:
NetBSD XXX 7.99.20 NetBSD 7.99.20 (XXX) #0: Sun Jul 19 18:42:21 JST 2015  root@XXX:XXX amd64
>Description:
The memory consumption of vi(1) grows order of MB by changing the
screen size.
>How-To-Repeat:
Execute vi(1), and change the screen size several times. You will
observe massive increase in the memory consumption.
>Fix:
This is caused by (I) vi(1) itself and underlying (II) curses and
(III) terminfo libraries.

(I) When the screen size is changed, vi(1) calls newterm(3) without
removing the established screen. For this problem, nvi2 [1,2] and
OpenBSD [3,4] provide patches, but unfortunately, we cannot apply
their patches for two reasons. First, they assume that
set_term(NULL) returns the current screen without any side effects.
This is *not* guaranteed by X/Open standards [5], and causes null
pointer dereferences for our implementation [6]. Second, their
patches break vertically splitted windows [2]. I've prepared an
alternative patch derived from nvi-1.79nb16 [7]: use setterm(3) and
resizeterm(3) instead of newterm(3) for reinitializing the screen.

[1] https://github.com/lichray/nvi2/commit/a8c38480adb030a05bbb2aafec6067dd65d8c2eb
[2] https://github.com/lichray/nvi2/commit/879d2ad6dd4a4343eb0a588ebfe637e1c9845bc4
[3] http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/vi/cl/cl_screen.c#rev1.23
[4] http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/vi/cl/cl_term.c#rev1.20
[5] http://pubs.opengroup.org/onlinepubs/7908799/xcurses/set_term.html
[6] http://nxr.netbsd.org/source/xref/src/lib/libcurses/screen.c#46
[7] http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.bin/vi/cl/Attic/cl_screen.c#rev1.7

(II) _cursesi_setterm() does not delete the established terminal
before calling ti_setupterm(3). I've also found other small memory
leaks.

(III) _ti_readterm() uses [cm]alloc(3) without checking whether
buffers have been allocated or not. I've also addressed other small
memory leaks.

After applying this patch, the memory consumption of vi(1) grows
order of 10KB for the first time you change the screen size; there
are possibly other memory leaks. However, it saturates by a few
times of resizing and does not increases infinitely.

I shall add one more comment. If you change the screen size rapidly,
sometimes you get error messages and additional memory consumption.
I guess that this is because a succeeding SIGWINCH interrupts the
reinitialization of screen due to a preceding SIGWINCH. It would be
better to neglect SIGWINCH during the (re)initialization of curses
screen. I'd like to hear your opinion.

--- src/external/bsd/nvi/Makefile.inc.orig	2015-07-26 01:29:59.000000000 +0900
+++ src/external/bsd/nvi/Makefile.inc	2015-07-26 01:30:05.000000000 +0900
@@ -7,4 +7,4 @@
 BINDIR=/usr/bin

 CWARNFLAGS.clang+=	-Wno-error=unused-const-variable
-VERSION=1.81.6-2013-11-20
+VERSION=1.81.6-2013-11-20nb1
--- src/external/bsd/nvi/dist/cl/cl_screen.c.orig	2015-07-25 08:26:48.000000000 +0900
+++ src/external/bsd/nvi/dist/cl/cl_screen.c	2015-07-25 11:50:37.000000000 +0900
@@ -189,6 +189,7 @@
 cl_vi_init(SCR *sp)
 {
 	CL_PRIVATE *clp;
+	static int newterm_done = 0;
 	char *o_cols, *o_lines, *o_term;
 	const char *ttype;

@@ -249,13 +250,17 @@
 	 * have to specify the terminal type.
 	 */
 	errno = 0;
-	if (newterm(__UNCONST(ttype), stdout, stdin) == NULL) {
+	if (!newterm_done && newterm(__UNCONST(ttype), stdout, stdin) == NULL) {
 		if (errno)
 			msgq(sp, M_SYSERR, "%s", ttype);
 		else
 			msgq(sp, M_ERR, "%s: unknown terminal type", ttype);
 		return (1);
+	} else if (newterm_done) {
+		setterm(__UNCONST(ttype));
+		resizeterm(O_VAL(sp, O_LINES), O_VAL(sp, O_COLUMNS));
 	}
+	newterm_done = 1;

 	if (o_term == NULL)
 		cl_unsetenv(sp, "TERM");
--- src/external/bsd/nvi/dist/cl/cl_term.c.orig	2015-07-25 08:31:16.000000000 +0900
+++ src/external/bsd/nvi/dist/cl/cl_term.c	2015-07-26 01:20:08.000000000 +0900
@@ -417,7 +417,6 @@
 			*rowp = row;
 		if (colp != NULL)
 			*colp = col;
-		resizeterm(row, col);
 		return (0);
 	}

--- src/lib/libcurses/screen.c.orig	2015-07-25 09:11:42.000000000 +0900
+++ src/lib/libcurses/screen.c	2015-07-26 00:06:12.000000000 +0900
@@ -207,6 +207,9 @@
 	return new_screen;

   error_exit:
+	if (new_screen->term != NULL)
+		(void)del_curterm(new_screen->term);
+	free(new_screen->unget_list);
 	free(new_screen);
 	return NULL;
 }
@@ -239,7 +242,7 @@
 	_cursesi_free_keymap(screen->base_keymap);

 	free(screen->stdbuf);
-	screen->stdbuf = NULL;
+	free(screen->unget_list);
 	if (_cursesi_screen == screen)
 		_cursesi_screen = NULL;
 	free(screen);
--- src/lib/libcurses/setterm.c.orig	2015-07-25 09:04:58.000000000 +0900
+++ src/lib/libcurses/setterm.c	2015-07-25 09:25:16.000000000 +0900
@@ -66,6 +66,8 @@
 	struct winsize win;
 	char *p;

+	if (screen->term != NULL)
+		(void)del_curterm(screen->term);
 	if (type[0] == '\0')
 		type = "xx";
 	unknown = 0;
--- src/lib/libterminfo/compile.c.orig	2015-07-25 22:09:17.000000000 +0900
+++ src/lib/libterminfo/compile.c	2015-07-25 22:09:58.000000000 +0900
@@ -653,10 +653,10 @@
 		free(tic->name);
 		free(tic->alias);
 		free(tic->desc);
-		free(tic->extras.buf);
 		free(tic->flags.buf);
 		free(tic->nums.buf);
 		free(tic->strs.buf);
+		free(tic->extras.buf);
 		free(tic);
 	}
 }
--- src/lib/libterminfo/curterm.c.orig	2015-07-25 09:13:21.000000000 +0900
+++ src/lib/libterminfo/curterm.c	2015-07-25 22:03:18.000000000 +0900
@@ -134,11 +134,12 @@

 	if (oterm == NULL)
 		return ERR;
-	free(oterm->_area);
-	free(oterm->strs);
-	free(oterm->nums);
 	free(oterm->flags);
+	free(oterm->nums);
+	free(oterm->strs);
+	free(oterm->_area);
 	free(oterm->_userdefs);
+	free(oterm->_buf);
 	free(oterm);
 	return OK;
 }
--- src/lib/libterminfo/term.c.orig	2015-07-25 22:17:02.000000000 +0900
+++ src/lib/libterminfo/term.c	2015-07-26 00:26:29.000000000 +0900
@@ -68,20 +68,30 @@
 		return -1;
 	}

-	term->flags = calloc(TIFLAGMAX + 1, sizeof(char));
-	if (term->flags == NULL)
-		return -1;
-	term->nums = malloc((TINUMMAX + 1) * sizeof(short));
-	if (term->nums == NULL)
-		return -1;
+	if (term->flags == NULL) {
+		term->flags = calloc(TIFLAGMAX + 1, sizeof(char));
+		if (term->flags == NULL)
+			return -1;
+	} else
+		memset(term->flags, 0, (TIFLAGMAX + 1) * sizeof(char));
+	if (term->nums == NULL) {
+		term->nums = malloc((TINUMMAX + 1) * sizeof(short));
+		if (term->nums == NULL)
+			return -1;
+	}
 	memset(term->nums, (short)-1, (TINUMMAX + 1) * sizeof(short));
-	term->strs = calloc(TISTRMAX + 1, sizeof(char *));
-	if (term->strs == NULL)
-		return -1;
+	if (term->strs == NULL) {
+		term->strs = calloc(TISTRMAX + 1, sizeof(char *));
+		if (term->strs == NULL)
+			return -1;
+	} else
+		memset(term->strs, 0, (TISTRMAX + 1) * sizeof(char *));
 	term->_arealen = caplen;
-	term->_area = malloc(term->_arealen);
-	if (term->_area == NULL)
-		return -1;
+	if (term->_area == NULL) {
+		term->_area = malloc(term->_arealen);
+		if (term->_area == NULL)
+			return -1;
+	}
 	memcpy(term->_area, cap, term->_arealen);

 	cap = term->_area;
@@ -352,11 +362,11 @@
 			e = strdup(e); /* So we don't destroy env */
 		if (e  == NULL)
 			tic = NULL;
-		else
+		else {
 			tic = _ti_compile(e, TIC_WARNING |
 			    TIC_ALIAS | TIC_DESCRIPTION | TIC_EXTRA);
-		if (c == NULL && e != NULL)
 			free(e);
+		}
 		if (tic != NULL && ticcmp(tic, name) == 0) {
 			len = _ti_flatten(&f, tic);
 			if (len != -1) {
--- src/lib/libterminfo/termcap.c.orig	2015-07-25 22:38:49.000000000 +0900
+++ src/lib/libterminfo/termcap.c	2015-07-25 22:39:29.000000000 +0900
@@ -553,8 +553,11 @@
 			else
 				len += rl;
 			p = realloc(info, len);
-			if (p == NULL)
+			if (p == NULL) {
+				if (fv)
+					free(val);
 				return NULL;
+			}
 			info = p;
 		}


>Release-Note:

>Audit-Trail:
From: Julian Coleman <jdc@coris.org.uk>
To: gnats-bugs@NetBSD.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: bin/50092: huge memory leaks in vi(1) when changing screen size
Date: Mon, 27 Jul 2015 12:21:17 +0100

 Hi,

 > I shall add one more comment. If you change the screen size rapidly,
 > sometimes you get error messages and additional memory consumption.
 > I guess that this is because a succeeding SIGWINCH interrupts the
 > reinitialization of screen due to a preceding SIGWINCH. It would be
 > better to neglect SIGWINCH during the (re)initialization of curses
 > screen. I'd like to hear your opinion.

 If we resize many times, we probably only care about the final size.  So,
 we really could ignore any apart from the last resize.  However, if we're
 already processing a resize, we should finish processing so that everthing
 is consistent (i.e. not interrupt the current resize).

 I wonder if we can just save the new size when we're already processing and
 check at the end of the current processing if a new (and different) size is
 saved?  Then we would re-run the resize with the new saved size.

 Regards,

 J

 -- 
    My other computer runs NetBSD too   -         http://www.netbsd.org/

From: Rin Okuyama <okuyama@flex.phys.tohoku.ac.jp>
To: Julian Coleman <jdc@coris.org.uk>, gnats-bugs@NetBSD.org
Cc: 
Subject: Re: bin/50092: huge memory leaks in vi(1) when changing screen size
Date: Tue, 28 Jul 2015 00:10:55 +0900

 Thank you for your comment.

 > If we resize many times, we probably only care about the final size.  So,
 > we really could ignore any apart from the last resize.  However, if we're
 > already processing a resize, we should finish processing so that everthing
 > is consistent (i.e. not interrupt the current resize).

 Exactly.

 > I wonder if we can just save the new size when we're already processing and
 > check at the end of the current processing if a new (and different) size is
 > saved?  Then we would re-run the resize with the new saved size.

 I think that your suggestion is a right way to deal with the problem.
 Theoretically, we can do so by switching signal handlers appropriately.
 Let me think for a while about actual implementation.

 Except this problem, my patch improves the situation. At least, vi no
 longer wastes MB of memory. Other commands using terminfo/curses, less,
 more, rogue, tetris, and sysinst work fine. Could anyone please review
 and commit it?

 Rin

From: Rin Okuyama <okuyama@flex.phys.tohoku.ac.jp>
To: Julian Coleman <jdc@coris.org.uk>, gnats-bugs@NetBSD.org
Cc: 
Subject: Re: bin/50092: huge memory leaks in vi(1) when changing screen size
Date: Mon, 3 Aug 2015 10:56:19 +0900

 This is a multi-part message in MIME format.
 --------------070700000004050800030903
 Content-Type: text/plain; charset=us-ascii; format=flowed
 Content-Transfer-Encoding: 7bit

 Hi,

 > If we resize many times, we probably only care about the final size.  So,
 > we really could ignore any apart from the last resize.  However, if we're
 > already processing a resize, we should finish processing so that everthing
 > is consistent (i.e. not interrupt the current resize).
 >
 > I wonder if we can just save the new size when we're already processing and
 > check at the end of the current processing if a new (and different) size is
 > saved?  Then we would re-run the resize with the new saved size.

 I examined the problem with the continuous screen size change in detail,
 using icewm/xterm on a slow virtual machine.

 (a) The original NetBSD version sometimes aborts with message
 "ex/vi: Error: screen: Interrupted system call". This is because
 newterm(3) is interrupted by SIGWINCH. This problem was reported for
 nvi-1.79 as bin/25849:

 http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=25849

 The fix is merged to NetBSD at that time, however it seems to be
 overlooked when nvi-1.86 was imported.

 (b) The patched version attached to my PR does not abort as it is based
 on the fix to bin/25849. However, it sometimes issues error messages
 like "Error: move: l(48 + 0) c(0 + 0)". This is because setterm(3) or
 resizeterm(3) are interrupted by SIGWINCH and the screen initialization
 fails. The fix to bin/25849 is not sufficient; the reason why it does
 not abort is simply because it does not check return values of
 setterm(3) and resizeterm(3).

 To address the problem, I modified the patch as follows.

 (1) During initialization of the screen, block signals to make sure that
 curses/terminfo routines are not interrupted.

 (2) In the signal handler for SIGWINCH, wait up to 1/10 seconds for a
 succeeding SIGWINCH received. This approximately realizes your
 suggestion.

 In addition, I made following changes.

 (3) Use delscreen(3) and newterm(3) for reinitialization of the screen,
 instead of setterm(3) and resizeterm(3), that are BSD/ncurses extension
 to the X/Open standards. This also resolves a memory leak when
 switching to ex-mode from vi-mode.

 (4) Delete the terminfo cur_term when we enter to vi-mode. We must
 initialize it in main() for processing .exrc or EXINIT. However, in
 vi-mode, it is overwritten by newterm(3), which results in a memory
 leak.

 (5) In ex-mode, use del_curterm(3) and setupterm(3) to update the
 terminfo database when the terminal type is changed. In the original
 version, we forget this before retrieving the terminfo entries.

 For memory leaks in libcurses/terminfo, I will send another PRs if
 necessary.

 Thanks,
 Rin

 --------------070700000004050800030903
 Content-Type: text/plain; charset=UTF-8; x-mac-type="0"; x-mac-creator="0";
  name="nvi.patch"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="nvi.patch"

 Index: src/external/bsd/nvi/Makefile.inc
 diff -u src/external/bsd/nvi/Makefile.inc:1.1.1.1 src/external/bsd/nvi/Makefile.inc:1.4
 --- src/external/bsd/nvi/Makefile.inc:1.1.1.1	Fri Jul 31 20:44:59 2015
 +++ src/external/bsd/nvi/Makefile.inc	Mon Aug  3 00:21:50 2015
 @@ -7,4 +7,4 @@
  BINDIR=/usr/bin

  CWARNFLAGS.clang+=	-Wno-error=unused-const-variable
 -VERSION=1.81.6-2013-11-20
 +VERSION=1.81.6-2013-11-20nb1
 Index: src/external/bsd/nvi/dist/cl/cl.h
 diff -u src/external/bsd/nvi/dist/cl/cl.h:1.1.1.1 src/external/bsd/nvi/dist/cl/cl.h:1.2
 --- src/external/bsd/nvi/dist/cl/cl.h:1.1.1.1	Fri Jul 31 20:44:59 2015
 +++ src/external/bsd/nvi/dist/cl/cl.h	Sat Aug  1 18:24:49 2015
 @@ -42,6 +42,8 @@
  	struct termios ex_enter;/* Terminal values to enter ex. */
  	struct termios vi_enter;/* Terminal values to enter vi. */

 +	SCREEN	*screen;	/* Curses screen. */
 +
  	char	*el;		/* Clear to EOL terminal string. */
  	char	*cup;		/* Cursor movement terminal string. */
  	char	*cuu1;		/* Cursor up terminal string. */
 @@ -77,6 +79,8 @@
  #define	CL_SIGTERM	0x0100	/* SIGTERM arrived. */
  #define	CL_SIGWINCH	0x0200	/* SIGWINCH arrived. */
  #define	CL_STDIN_TTY	0x0400	/* Talking to a terminal. */
 +#define	CL_SETUPTERM	0x0800	/* Terminal initialized. */
 +#define	CL_CHANGE_TERM	0x1000	/* Terminal changed. */
  	u_int32_t flags;
  } CL_PRIVATE;

 Index: src/external/bsd/nvi/dist/cl/cl_main.c
 diff -u src/external/bsd/nvi/dist/cl/cl_main.c:1.1.1.1 src/external/bsd/nvi/dist/cl/cl_main.c:1.4
 --- src/external/bsd/nvi/dist/cl/cl_main.c:1.1.1.1	Fri Jul 31 20:44:59 2015
 +++ src/external/bsd/nvi/dist/cl/cl_main.c	Mon Aug  3 00:21:14 2015
 @@ -109,6 +109,7 @@
  		ttype = "unknown";
  	}
  	term_init(gp->progname, ttype);
 +	F_SET(clp, CL_SETUPTERM);

  	/* Add the terminal type to the global structure. */
  	if ((OG_D_STR(gp, GO_TERM) =
 @@ -292,6 +293,22 @@
  h_winch(int signo)
  {
  	GLOBAL_CLP;
 +	sigset_t sigset;
 +	struct timespec timeout;
 +
 +	/*
 +	 * Some window managers continuously change the screen size of terminal
 +	 * emulators, by which a lot of SIGWINCH signals are to be received. In
 +	 * such a case, we only need to respond the final signal; the remaining
 +	 * signals are meaningless.  Thus, we wait here up to 1/10 of a second
 +	 * for a succeeding signal received.
 +	 */
 +	(void)sigemptyset(&sigset);
 +	(void)sigaddset(&sigset, SIGWINCH);
 +	timeout.tv_sec = 0;
 +	timeout.tv_nsec = 100 * 1000 * 1000;
 +	while (sigtimedwait(&sigset, NULL, &timeout) != -1)
 +		continue;

  	F_SET(clp, CL_SIGWINCH);
  }
 Index: src/external/bsd/nvi/dist/cl/cl_screen.c
 diff -u src/external/bsd/nvi/dist/cl/cl_screen.c:1.1.1.1 src/external/bsd/nvi/dist/cl/cl_screen.c:1.5
 --- src/external/bsd/nvi/dist/cl/cl_screen.c:1.1.1.1	Fri Jul 31 20:44:59 2015
 +++ src/external/bsd/nvi/dist/cl/cl_screen.c	Mon Aug  3 00:29:51 2015
 @@ -34,6 +34,10 @@
  #include "../common/common.h"
  #include "cl.h"

 +#ifndef BLOCK_SIGNALS
 +extern sigset_t __sigblockset;
 +#endif
 +
  static int	cl_ex_end __P((GS *));
  static int	cl_ex_init __P((SCR *));
  static void	cl_freecap __P((CL_PRIVATE *));
 @@ -53,26 +57,37 @@
  	CL_PRIVATE *clp;
  	WINDOW *win;
  	GS *gp;
 +	int ret;

  	gp = sp->gp;
  	clp = CLP(sp);
  	win = CLSP(sp) ? CLSP(sp) : stdscr;

 +	ret = 0;
 +
 +	/*
 +	 * During initialization of the screen, block signals to make sure that
 +	 * curses/terminfo routines are not interrupted.
 +	 */
 +	(void)sigprocmask(SIG_BLOCK, &__sigblockset, NULL);
 +
  	/* See if the current information is incorrect. */
  	if (F_ISSET(gp, G_SRESTART)) {
  		if (CLSP(sp)) {
  		    delwin(CLSP(sp));
  		    sp->cl_private = NULL;
  		}
 -		if (cl_quit(gp))
 -			return (1);
 +		if (cl_quit(gp)) {
 +			ret = 1;
 +			goto end;
 +		}
  		F_CLR(gp, G_SRESTART);
  	}

  	/* See if we're already in the right mode. */
  	if ((LF_ISSET(SC_EX) && F_ISSET(sp, SC_SCR_EX)) ||
  	    (LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI)))
 -		return (0);
 +		goto end;

  	/*
  	 * Fake leaving ex mode.
 @@ -109,8 +124,10 @@

  	/* Enter the requested mode. */
  	if (LF_ISSET(SC_EX)) {
 -		if (cl_ex_init(sp))
 -			return (1);
 +		if (cl_ex_init(sp)) {
 +			ret = 1;
 +			goto end;
 +		}
  		F_SET(clp, CL_IN_EX | CL_SCR_EX_INIT);

  		/*
 @@ -121,12 +138,17 @@
  			tputs(tgoto(clp->cup,
  			    0, O_VAL(sp, O_LINES) - 1), 1, cl_putchar);
  	} else {
 -		if (cl_vi_init(sp))
 -			return (1);
 +		if (cl_vi_init(sp)) {
 +			ret = 1;
 +			goto end;
 +		}
  		F_CLR(clp, CL_IN_EX);
  		F_SET(clp, CL_SCR_VI_INIT);
  	}
 -	return (0);
 +end:
 +	/* Unblock signals. */
 +	(void)sigprocmask(SIG_UNBLOCK, &__sigblockset, NULL);
 +	return ret;
  }

  /*
 @@ -234,10 +256,14 @@
  	o_cols = getenv("COLUMNS");
  	cl_putenv(sp, "COLUMNS", NULL, (u_long)O_VAL(sp, O_COLUMNS));

 +	/* Delete cur_term if exists. */
 +	if (F_ISSET(clp, CL_SETUPTERM)) {
 +		if (del_curterm(cur_term))
 +			return (1);
 +		F_CLR(clp, CL_SETUPTERM);
 +	}
 +
  	/*
 -	 * We don't care about the SCREEN reference returned by newterm, we
 -	 * never have more than one SCREEN at a time.
 -	 *
  	 * XXX
  	 * The SunOS initscr() can't be called twice.  Don't even think about
  	 * using it.  It fails in subtle ways (e.g. select(2) on fileno(stdin)
 @@ -249,7 +275,7 @@
  	 * have to specify the terminal type.
  	 */
  	errno = 0;
 -	if (newterm(__UNCONST(ttype), stdout, stdin) == NULL) {
 +	if ((clp->screen = newterm(__UNCONST(ttype), stdout, stdin)) == NULL) {
  		if (errno)
  			msgq(sp, M_SYSERR, "%s", ttype);
  		else
 @@ -374,8 +400,6 @@

  fast:	/* Set the terminal modes. */
  	if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &clp->vi_enter)) {
 -		if (errno == EINTR)
 -			goto fast;
  		msgq(sp, M_SYSERR, "tcsetattr");
  err:		(void)cl_vi_end(sp->gp);
  		return (1);
 @@ -416,6 +440,9 @@
  	/* End curses window. */
  	(void)endwin();

 +	/* Delete curses screen. */
 +	delscreen(clp->screen);
 +
  	/*
  	 * XXX
  	 * The screen TE sequence just got sent.  See the comment in
 @@ -434,6 +461,8 @@
  cl_ex_init(SCR *sp)
  {
  	CL_PRIVATE *clp;
 +	int error;
 +	const char *ttype;

  	clp = CLP(sp);

 @@ -445,6 +474,22 @@
  	if (!F_ISSET(clp, CL_STDIN_TTY))
  		return (0);

 +	if (F_ISSET(clp, CL_CHANGE_TERM)) {
 +		if (F_ISSET(clp, CL_SETUPTERM) && del_curterm(cur_term))
 +			return (1);
 +		F_CLR(clp, CL_SETUPTERM | CL_CHANGE_TERM);
 +	}
 +
 +	if (!F_ISSET(clp, CL_SETUPTERM)) {
 +		/* We'll need a terminal type. */
 +		if (opts_empty(sp, O_TERM, 0))
 +			return (1);
 +		ttype = O_STR(sp, O_TERM);
 +		(void)setupterm(ttype, STDOUT_FILENO, &error);
 +		if (error == 0 || error == -1)
 +			return (1);
 +	}
 +
  	/* Get the ex termcap/terminfo strings. */
  	(void)cl_getcap(sp, "cup", &clp->cup);
  	(void)cl_getcap(sp, "smso", &clp->smso);
 Index: src/external/bsd/nvi/dist/cl/cl_term.c
 diff -u src/external/bsd/nvi/dist/cl/cl_term.c:1.1.1.1 src/external/bsd/nvi/dist/cl/cl_term.c:1.3
 --- src/external/bsd/nvi/dist/cl/cl_term.c:1.1.1.1	Fri Jul 31 20:44:59 2015
 +++ src/external/bsd/nvi/dist/cl/cl_term.c	Sat Aug  1 18:24:49 2015
 @@ -268,9 +268,12 @@
  	clp = CLP(sp);

  	switch (opt) {
 +	case O_TERM:
 +		if (F_ISSET(sp, SC_SCR_EX))
 +			F_SET(clp, CL_CHANGE_TERM);
 +		/* FALLTHROUGH */
  	case O_COLUMNS:
  	case O_LINES:
 -	case O_TERM:
  		/*
  		 * Changing the columns, lines or terminal require that
  		 * we restart the screen.
 @@ -417,7 +420,6 @@
  			*rowp = row;
  		if (colp != NULL)
  			*colp = col;
 -		resizeterm(row, col);
  		return (0);
  	}


 --------------070700000004050800030903--

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/50092 CVS commit: src/lib/libcurses
Date: Mon, 23 Nov 2015 20:59:33 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Tue Nov 24 01:59:33 UTC 2015

 Modified Files:
 	src/lib/libcurses: setterm.c

 Log Message:
 PR/50092: don't leak screen on multiple setterms.


 To generate a diff of this commit:
 cvs rdiff -u -r1.52 -r1.53 src/lib/libcurses/setterm.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/50092 CVS commit: src/lib/libterminfo
Date: Wed, 25 Nov 2015 13:38:22 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Wed Nov 25 18:38:22 UTC 2015

 Modified Files:
 	src/lib/libterminfo: curterm.c

 Log Message:
 PR/50092: Fix memory leak.


 To generate a diff of this commit:
 cvs rdiff -u -r1.10 -r1.11 src/lib/libterminfo/curterm.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/50092 CVS commit: src/lib/libterminfo
Date: Wed, 25 Nov 2015 13:46:24 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Wed Nov 25 18:46:24 UTC 2015

 Modified Files:
 	src/lib/libterminfo: termcap.c

 Log Message:
 PR/50092: Rin Okuyama: Fix memory leak.


 To generate a diff of this commit:
 cvs rdiff -u -r1.17 -r1.18 src/lib/libterminfo/termcap.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/50092 CVS commit: src/lib/libterminfo
Date: Wed, 25 Nov 2015 14:13:50 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Wed Nov 25 19:13:49 UTC 2015

 Modified Files:
 	src/lib/libterminfo: term.c

 Log Message:
 From PR/50092:
 - handle calling _ti_readterm with an existing initialized terminal
 - simplify free code
 Also:
 - fix an inconsistency in userdefs count computation


 To generate a diff of this commit:
 cvs rdiff -u -r1.17 -r1.18 src/lib/libterminfo/term.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/50092 CVS commit: src/external/bsd/nvi
Date: Wed, 25 Nov 2015 15:25:20 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Wed Nov 25 20:25:20 UTC 2015

 Modified Files:
 	src/external/bsd/nvi: Makefile.inc
 	src/external/bsd/nvi/dist/cl: cl.h cl_main.c cl_screen.c cl_term.c

 Log Message:
 PR/50092: Rin Okuyama: Fix memory leaks in vi when resizing.


 To generate a diff of this commit:
 cvs rdiff -u -r1.1 -r1.2 src/external/bsd/nvi/Makefile.inc
 cvs rdiff -u -r1.2 -r1.3 src/external/bsd/nvi/dist/cl/cl.h
 cvs rdiff -u -r1.4 -r1.5 src/external/bsd/nvi/dist/cl/cl_main.c \
     src/external/bsd/nvi/dist/cl/cl_screen.c \
     src/external/bsd/nvi/dist/cl/cl_term.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Rin Okuyama <okuyama@flex.phys.tohoku.ac.jp>
To: gnats-bugs@NetBSD.org, christos@netbsd.org
Cc: 
Subject: Re: PR/50092 CVS commit: src/external/bsd/nvi
Date: Thu, 26 Nov 2015 08:34:02 +0900

 Thank you for your improvement and commitment of my patches. I shall
 make two comments.

 (1) For _ti_readbuf() in libterminfo, cap should always be copied into
 the buffer; caplen can accidentally be same as before.

 ======
 --- src/lib/libterminfo/term.c.orig	2015-11-26 08:14:56.000000000 +0900
 +++ src/lib/libterminfo/term.c	2015-11-26 08:15:33.000000000 +0900
 @@ -100,8 +100,8 @@
  		term->_area = realloc(term->_area, term->_arealen);
  		if (term->_area == NULL)
  			return -1;
 -		memcpy(term->_area, cap, term->_arealen);
  	}
 +	memcpy(term->_area, cap, term->_arealen);

  	cap = term->_area;
  	len = le16dec(cap);
 ======

 (2) For libcurses, screen->unget_list and screen->term should be freed
 when we delete screen.

 ======
 --- src/lib/libcurses/screen.c.orig	2015-07-25 09:11:42.000000000 +0900
 +++ src/lib/libcurses/screen.c	2015-07-26 00:06:12.000000000 +0900
 @@ -207,6 +207,9 @@
  	return new_screen;

    error_exit:
 +	if (new_screen->term != NULL)
 +		(void)del_curterm(new_screen->term);
 +	free(new_screen->unget_list);
  	free(new_screen);
  	return NULL;
  }
 @@ -239,7 +242,7 @@
  	_cursesi_free_keymap(screen->base_keymap);

  	free(screen->stdbuf);
 -	screen->stdbuf = NULL;
 +	free(screen->unget_list);
  	if (_cursesi_screen == screen)
  		_cursesi_screen = NULL;
  	free(screen);
 ======

 Thanks,
 Rin

From: christos@zoulas.com (Christos Zoulas)
To: Rin Okuyama <okuyama@flex.phys.tohoku.ac.jp>, gnats-bugs@NetBSD.org
Cc: 
Subject: Re: PR/50092 CVS commit: src/external/bsd/nvi
Date: Wed, 25 Nov 2015 20:05:30 -0500

 On Nov 26,  8:34am, okuyama@flex.phys.tohoku.ac.jp (Rin Okuyama) wrote:
 -- Subject: Re: PR/50092 CVS commit: src/external/bsd/nvi

 | Thank you for your improvement and commitment of my patches. I shall
 | make two comments.

 Thank you again! Applied.

 christos

From: Rin Okuyama <okuyama@flex.phys.tohoku.ac.jp>
To: gnats-bugs@NetBSD.org, christos@netbsd.org
Cc: 
Subject: Re: PR/50092 CVS commit: src/external/bsd/nvi
Date: Thu, 26 Nov 2015 11:40:47 +0900

 Fix confirmed. Thank you very much!

From: christos@zoulas.com (Christos Zoulas)
To: Rin Okuyama <okuyama@flex.phys.tohoku.ac.jp>, gnats-bugs@NetBSD.org
Cc: 
Subject: Re: PR/50092 CVS commit: src/external/bsd/nvi
Date: Thu, 26 Nov 2015 11:19:48 -0500

 On Nov 26, 11:40am, okuyama@flex.phys.tohoku.ac.jp (Rin Okuyama) wrote:
 -- Subject: Re: PR/50092 CVS commit: src/external/bsd/nvi

 | Fix confirmed. Thank you very much!

 Thank you for the patch!

 christos

State-Changed-From-To: open->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Tue, 31 May 2016 06:10:57 +0000
State-Changed-Why:
All committed as of back in November.


From: "Soren Jacobsen" <snj@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/50092 CVS commit: [netbsd-7] src/lib/libterminfo
Date: Mon, 12 Dec 2016 07:37:53 +0000

 Module Name:	src
 Committed By:	snj
 Date:		Mon Dec 12 07:37:53 UTC 2016

 Modified Files:
 	src/lib/libterminfo [netbsd-7]: curterm.c term.c termcap.c terminfo.3
 	    tparm.c

 Log Message:
 Pull up following revision(s) (requested by riastradh in ticket #1307):
 	lib/libterminfo/curterm.c: revisions 1.11, 1.12
 	lib/libterminfo/term.c: revisions 1.18-1.20
 	lib/libterminfo/termcap.c: revisions 1.18, 1.19
 	lib/libterminfo/terminfo.3: revision 1.13
 	lib/libterminfo/tparm.c: revision 1.16
 terminfo.3: fix ti_puts prototype
 --
 PR/50092: Fix memory leak.
 --
 PR/50092: Rin Okuyama: Fix memory leak.
 --
 We have the max length; use snprintf.
 --
 From PR/50092:
 - handle calling _ti_readterm with an existing initialized terminal
 - simplify free code
 Also:
 - fix an inconsistency in userdefs count computation
 --
 Always copy the area buffer, even when the length was the same
 (from Rin Okuyama)
 --
 - if we are freeing cur_term, set it to NULL.
 - preserve and free "last" properly.
 --
 off-by-one in memcpy. Found by ASAN (Carsten Kunze)


 To generate a diff of this commit:
 cvs rdiff -u -r1.10 -r1.10.4.1 src/lib/libterminfo/curterm.c
 cvs rdiff -u -r1.17 -r1.17.6.1 src/lib/libterminfo/term.c
 cvs rdiff -u -r1.17 -r1.17.18.1 src/lib/libterminfo/termcap.c
 cvs rdiff -u -r1.12 -r1.12.4.1 src/lib/libterminfo/terminfo.3
 cvs rdiff -u -r1.15 -r1.15.6.1 src/lib/libterminfo/tparm.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Soren Jacobsen" <snj@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/50092 CVS commit: [netbsd-7] src/external/bsd/nvi
Date: Sun, 18 Dec 2016 06:37:31 +0000

 Module Name:	src
 Committed By:	snj
 Date:		Sun Dec 18 06:37:30 UTC 2016

 Modified Files:
 	src/external/bsd/nvi [netbsd-7]: Makefile.inc
 	src/external/bsd/nvi/dist/cl [netbsd-7]: cl.h cl_main.c cl_screen.c
 	    cl_term.c
 	src/external/bsd/nvi/dist/common [netbsd-7]: key.h vi_db1.c
 	src/external/bsd/nvi/dist/docs/vi.man [netbsd-7]: vi.1
 	src/external/bsd/nvi/dist/ex [netbsd-7]: ex_map.c ex_script.c
 	src/external/bsd/nvi/usr.bin/nvi [netbsd-7]: Makefile

 Log Message:
 Pull up following revision(s) (requested by riastradh in ticket #1312):
 	external/bsd/nvi/Makefile.inc: revisions 1.2-1.4
 	external/bsd/nvi/dist/cl/cl.h: revision 1.3
 	external/bsd/nvi/dist/cl/cl_main.c: revision 1.5
 	external/bsd/nvi/dist/cl/cl_screen.c: revision 1.5
 	external/bsd/nvi/dist/cl/cl_term.c: revision 1.5
 	external/bsd/nvi/dist/common/key.h: revision 1.3
 	external/bsd/nvi/dist/common/vi_db1.c: revision 1.8
 	external/bsd/nvi/dist/docs/vi.man/vi.1: revisions 1.3, 1.4
 	external/bsd/nvi/dist/ex/ex_map.c: revision 1.4
 	external/bsd/nvi/dist/ex/ex_script.c: revisions 1.5, 1.6
 	external/bsd/nvi/usr.bin/nvi/Makefile: revision 1.7
 PR/50092: Rin Okuyama: Fix memory leaks in vi when resizing.
 --
 PR/50484: Rin Okuyama: fix the script command of vi(1)
 --
 Fix > 1024 char lines in script. (Rin Okuyama)
 --
 remove CONST; it is unused from Brad Harder
 --
 add default: to appease gcc.
 --
 Restore the first line of the copyright header, which accidentally got
 zapped in -r1.2.
 --
 PR 51446 Brad Harder: fix synopsis for :tagprev


 To generate a diff of this commit:
 cvs rdiff -u -r1.1 -r1.1.6.1 src/external/bsd/nvi/Makefile.inc
 cvs rdiff -u -r1.2 -r1.2.6.1 src/external/bsd/nvi/dist/cl/cl.h
 cvs rdiff -u -r1.4 -r1.4.6.1 src/external/bsd/nvi/dist/cl/cl_main.c \
     src/external/bsd/nvi/dist/cl/cl_screen.c \
     src/external/bsd/nvi/dist/cl/cl_term.c
 cvs rdiff -u -r1.2 -r1.2.6.1 src/external/bsd/nvi/dist/common/key.h
 cvs rdiff -u -r1.7 -r1.7.6.1 src/external/bsd/nvi/dist/common/vi_db1.c
 cvs rdiff -u -r1.2 -r1.2.6.1 src/external/bsd/nvi/dist/docs/vi.man/vi.1
 cvs rdiff -u -r1.3 -r1.3.6.1 src/external/bsd/nvi/dist/ex/ex_map.c
 cvs rdiff -u -r1.4 -r1.4.6.1 src/external/bsd/nvi/dist/ex/ex_script.c
 cvs rdiff -u -r1.5 -r1.5.2.1 src/external/bsd/nvi/usr.bin/nvi/Makefile

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.