[ttssh2-commit] [10354] ランダムデータを表示させるとクラッシュする

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2022年 11月 9日 (水) 23:13:52 JST


Revision: 10354
          https://osdn.net/projects/ttssh2/scm/svn/commits/10354
Author:   zmatsuo
Date:     2022-11-09 23:13:52 +0900 (Wed, 09 Nov 2022)
Log Message:
-----------
ランダムデータを表示させるとクラッシュする

- `cat /dev/urandom` でテスト
- 制御文字(C0,C1)はバッファに入れないようにした
- 全角文字に上書き時にバッファ外へアクセスしていた
- バッファ上で文字のコピーを行ったとき結合などで長くなった文字のコピーを行っていなかった
  - バッファの開放(free())が重複して行われてしまう原因になっていた
- 代替画面バッファを使用した際メモリリークが発生していた
- 全角より大きな文字の扱い(TODO)
  - 全角(=2cellの文字)より大きな文字(3cell以上)が現れることがある
  - 現在3cell以上の文字の扱いをケアしていない
  - IsBuffFullWidth(), AttrKanji など

ticket #45763

Ticket Links:
------------
    https://osdn.net/projects/ttssh2/tracker/detail/45763

Modified Paths:
--------------
    trunk/teraterm/teraterm/buffer.c

-------------- next part --------------
Modified: trunk/teraterm/teraterm/buffer.c
===================================================================
--- trunk/teraterm/teraterm/buffer.c	2022-11-06 15:35:13 UTC (rev 10353)
+++ trunk/teraterm/teraterm/buffer.c	2022-11-09 14:13:52 UTC (rev 10354)
@@ -49,6 +49,8 @@
 #include "asprintf.h"
 #include "ttcstd.h"
 
+#define	ENABLE_CELL_INDEX	0
+
 // \x83o\x83b\x83t\x83@\x93\xE0\x82̔\xBC\x8Ap1\x95\xB6\x8E\x9A\x95\xAA\x82̏\xEE\x95\xF1
 typedef struct {
 	char32_t u32;
@@ -70,6 +72,9 @@
 	unsigned char attr;
 	unsigned char attr2;
 	unsigned short ansi_char;
+#if ENABLE_CELL_INDEX
+	int idx;	// \x83Z\x83\x8B\x92ʂ\xB5\x94ԍ\x86
+#endif
 } buff_char_t;
 
 #define BuffXMax TermWidthMax
@@ -79,7 +84,7 @@
 #define BuffYMax 500000
 #define BuffSizeMax (BuffYMax * 80)
 
-// 1\x95\xB6\x8E\x9A\x82\xA0\x82\xBD\x82\xE8\x82̗̈\xE6\x8Dő\xE5\x83T\x83C\x83Y
+// 1\x95\xB6\x8E\x9A\x82\xA0\x82\xBD\x82\xE8\x82̃R\x83\x93\x83r\x83l\x81[\x83V\x83\x87\x83\x93\x83o\x83b\x83t\x83@\x8Dő\xE5\x83T\x83C\x83Y
 #define MAX_CHAR_SIZE	100
 
 // status line
@@ -123,22 +128,90 @@
 static void BuffDrawLineI(int DrawX, int DrawY, int SY, int IStart, int IEnd);
 static void BuffDrawLineIPrn(int SY, int IStart, int IEnd);
 
+/**
+ *	buff_char_t \x82\xF0 rel\x83Z\x83\x8B\x88ړ\xAE\x82\xB7\x82\xE9
+ *
+ *	@param	CodeBuffW_	\x95\xB6\x8E\x9A\x83o\x83b\x83t\x83@\x82̐擪\x83|\x83C\x83\x93\x83^
+ *	@param	BufferSize_	\x95\xB6\x8E\x9A\x83o\x83b\x83t\x83@\x82̃T\x83C\x83Y(buff_char_t\x92P\x88\xCA)
+ *	@param	p			\x88ړ\xAE\x82\xB3\x82\xB9\x82\xE9\x83|\x83C\x83\x93\x83^
+ *	@param	rel			\x88ړ\xAE\x97\xCA
+ *	@retval	\x88ړ\xAE\x8C\xE3\x82̃|\x83C\x83\x93\x83^
+ */
+static buff_char_t *GetPtrRel(buff_char_t *CodeBuffW_, size_t BufferSize_, buff_char_t *p, int rel)
+{
+	ptrdiff_t idx = (ptrdiff_t)(p - CodeBuffW_) + rel;
+	for (;;) {
+		if (idx < 0) {
+			idx += BufferSize_;
+		}
+		else if (idx >= (ptrdiff_t)BufferSize_) {
+			idx -= BufferSize_;
+		}
+		else {
+			break;
+		}
+	}
+	p = &CodeBuffW_[(int)idx];
+	return p;
+}
+
+static void FreeCombinationBuf(buff_char_t *b)
+{
+	if (b->pCombinationChars16 != NULL) {
+		free(b->pCombinationChars16);
+		b->pCombinationChars16 = NULL;
+	}
+	b->CombinationCharSize16 = 0;
+	b->CombinationCharCount16 = 0;
+
+	if (b->pCombinationChars32 != NULL) {
+		free(b->pCombinationChars32);
+		b->pCombinationChars32 = NULL;
+	}
+	b->CombinationCharSize32 = 0;
+	b->CombinationCharCount32 = 0;
+}
+
+static void DupCombinationBuf(buff_char_t *b)
+{
+	size_t size;
+
+	size = b->CombinationCharSize16;
+	if (size > 0) {
+		wchar_t *new_buf = malloc(sizeof(wchar_t) * size);
+		memcpy(new_buf, b->pCombinationChars16, sizeof(wchar_t) * size);
+		b->pCombinationChars16 = new_buf;
+	}
+	size = b->CombinationCharSize32;
+	if (size > 0) {
+		char32_t *new_buf = malloc(sizeof(char32_t) * size);
+		memcpy(new_buf, b->pCombinationChars32, sizeof(char32_t) * size);
+		b->pCombinationChars32 = new_buf;
+	}
+}
+
+static void CopyCombinationBuf(buff_char_t *dest, const buff_char_t *src)
+{
+	FreeCombinationBuf(dest);
+
+	// \x8D\\x91\xA2\x91̂\xF0\x83R\x83s\x81[\x82\xB7\x82\xE9
+#if ENABLE_CELL_INDEX
+	int idx = dest->idx;
+#endif
+	*dest = *src;
+#if ENABLE_CELL_INDEX
+	dest->idx = idx;
+#endif
+
+	DupCombinationBuf(dest);
+}
+
 static void BuffSetChar2(buff_char_t *buff, char32_t u32, char property, BOOL half_width, char emoji)
 {
 	size_t wstr_len;
 	buff_char_t *p = buff;
-	if (p->pCombinationChars16 != NULL) {
-		free(p->pCombinationChars16);
-		p->pCombinationChars16 = NULL;
-	}
-	p->CombinationCharCount16 = 0;
-	p->CombinationCharSize16 = 0;
-	if (p->pCombinationChars32 != NULL) {
-		free(p->pCombinationChars32);
-		p->pCombinationChars32 = NULL;
-	}
-	p->CombinationCharCount32 = 0;
-	p->CombinationCharSize32 = 0;
+
+	FreeCombinationBuf(p);
 	p->WidthProperty = property;
 	p->cell = half_width ? 1 : 2;
 	p->u32 = u32;
@@ -261,26 +334,19 @@
 	}
 }
 
-// TODO: \x83\x8A\x81[\x83N\x94\xAD\x90\xB6
 static void memcpyW(buff_char_t *dest, const buff_char_t *src, size_t count)
 {
 	size_t i;
-	memcpy(dest, src, count * sizeof(buff_char_t));
-	for (i=0; i<count; i++) {
-		buff_char_t *p = &dest[i];
-		size_t size = p->CombinationCharSize16;
-		if (size > 0) {
-			wchar_t *new_buf = malloc(sizeof(wchar_t) * size);
-			memcpy(new_buf, p->pCombinationChars16, sizeof(wchar_t) * size);
-			p->pCombinationChars16 = new_buf;
-		}
-		size = p->CombinationCharSize32;
-		if (size > 0) {
-			char32_t *new_buf = malloc(sizeof(char32_t) * size);
-			memcpy(new_buf, p->pCombinationChars32, sizeof(char32_t) * size);
-			p->pCombinationChars32 = new_buf;
-		}
+
+	if (dest == src || count == 0) {
+		return;
 	}
+
+	for (i = 0; i < count; i++) {
+		CopyCombinationBuf(dest, src);
+		dest++;
+		src++;
+	}
 }
 
 static void memsetW(buff_char_t *dest, wchar_t ch, unsigned char fg, unsigned char bg, unsigned char attr, unsigned char attr2, size_t count)
@@ -298,7 +364,27 @@
 
 static void memmoveW(buff_char_t *dest, const buff_char_t *src, size_t count)
 {
-	memmove(dest, src, count * sizeof(buff_char_t));
+	size_t i;
+
+	if (dest == src || count == 0) {
+		return;
+	}
+
+
+	if (dest < src) {
+		// \x91O\x82\xA9\x82\xE7\x83R\x83s\x81[\x82\xB7\x82\xE9? -> memcpyW() \x82\xC5ok
+		memcpyW(dest, src, count);
+	}
+	else {
+		// \x8C\xE3\x82납\x82\xE7\x83R\x83s\x81[\x82\xB7\x82\xE9
+		dest += count - 1;
+		src += count - 1;
+		for (i = 0; i < count; i++) {
+			CopyCombinationBuf(dest, src);
+			dest--;
+			src--;
+		}
+	}
 }
 
 static BOOL IsBuffPadding(const buff_char_t *b)
@@ -395,6 +481,14 @@
 	}
 
 	memset(&CodeDestW[0], 0, NewSize * sizeof(buff_char_t));
+#if ENABLE_CELL_INDEX
+	{
+		int i;
+		for (i = 0; i < NewSize; i++) {
+			CodeDestW[i].idx = i;
+		}
+	}
+#endif
 	memsetW(&CodeDestW[0], 0x20, AttrDefaultFG, AttrDefaultBG, AttrDefault, AttrDefault, NewSize);
 	if ( CodeBuffW != NULL ) {
 		if ( NumOfColumns > Nx ) {
@@ -545,25 +639,14 @@
 	}
 }
 
-static void FreeCombinationBuffer(void)
+void FreeBuffer(void)
 {
 	int i;
+
 	for (i = 0; i < NumOfColumns * NumOfLinesInBuff; i++) {
-		buff_char_t *b = &CodeBuffW[i];
-		if (b->pCombinationChars16 != NULL) {
-			free(b->pCombinationChars16);
-			b->pCombinationChars16 = NULL;
-		}
-		if (b->pCombinationChars32 != NULL) {
-			free(b->pCombinationChars32);
-			b->pCombinationChars32 = NULL;
-		}
+		FreeCombinationBuf(&CodeBuffW[i]);
 	}
-}
 
-void FreeBuffer(void)
-{
-	FreeCombinationBuffer();
 	BuffLock = 1;
 	UnlockBuffer();
 	if (CodeBuffW != NULL) {
@@ -2674,8 +2757,8 @@
 static buff_char_t *IsCombiningChar(int x, int y, BOOL wrap, unsigned int u32, int *combine)
 {
 	buff_char_t *p = NULL;  // NULL\x82̂Ƃ\xAB\x81A\x91O\x82̕\xB6\x8E\x9A\x82͂Ȃ\xA2
-	LONG LinePtr = GetLinePtr(PageStart+y);
-	buff_char_t *CodeLineW = &CodeBuffW[LinePtr];
+	LONG LinePtr_ = GetLinePtr(PageStart+y);
+	buff_char_t *CodeLineW = &CodeBuffW[LinePtr_];
 	int combine_type;	// 0 or 1 or 2
 
 	combine_type = (u32 == 0x200d) ? 1 : 0;		// U+200d = \x83[\x83\x8D\x95\x9D\x90ڍ\x87\x8Eq,ZERO WIDTH JOINER(ZWJ)
@@ -2700,7 +2783,7 @@
 		}
 		else {
 			// padding\x82ł͂Ȃ\xA2\x83Z\x83\x8B\x82\xF0\x92T\x82\xB7
-			x = LeftHalfOfDBCS(LinePtr, x - 1);		// 1cell\x91O\x82\xA9\x82璲\x82ׂ\xE9
+			x = LeftHalfOfDBCS(LinePtr_, x - 1);		// 1cell\x91O\x82\xA9\x82璲\x82ׂ\xE9
 			if (!IsBuffPadding(&CodeLineW[x])) {
 				p = &CodeLineW[x];
 			}
@@ -2817,6 +2900,12 @@
 	OutputDebugPrintfW(L"BuffPutUnicode(U+%06x,(%d,%d)\n", u32, CursorX, CursorY);
 #endif
 
+	if (u32 < 0x20 || (0x80 <= u32 && u32 <= 0x9f)) {
+		// C0/C1 Controls \x82͕\xB6\x8E\x9A\x82Ƃ\xB5\x82ď\x88\x97\x9D\x82\xB5\x82Ȃ\xA2
+		//assert(FALSE);	// \x93\xFC\x82\xC1\x82Ă\xAD\x82\xE9\x82̂͂\xA8\x82\xA9\x82\xB5\x82\xA2
+		return 0;
+	}
+
 	if (ts.EnableContinuedLineCopy && CursorX == 0 && (CodeLineW[0].attr & AttrLineContinued)) {
 		Attr.Attr |= AttrLineContinued;
 	}
@@ -2826,11 +2915,13 @@
 	p = IsCombiningChar(CursorX, CursorY, Wrap, u32, &combining_type);
 	if (p != NULL || combining_type != 0) {
 		// \x8C\x8B\x8D\x87\x82\xB7\x82\xE9
+		BOOL add_base_char = FALSE;
 		move_x = 0;  // \x83J\x81[\x83\\x83\x8B\x88ړ\xAE\x97\xCA=0
 
 		if (p == NULL) {
 			// \x91O\x82̂\xE0\x82\xB6(\x8A\xEE\x92ꕶ\x8E\x9A)\x82\xAA\x82Ȃ\xA2\x82̂Ɍ\x8B\x8D\x87\x95\xB6\x8E\x9A\x82\xAA\x8Fo\x82Ă\xAB\x82\xBD\x82Ƃ\xAB
 			// NBSP(non-breaking space) U+00A0 \x82Ɍ\x8B\x8D\x87\x82\xB3\x82\xB9\x82\xE9
+			add_base_char = TRUE;
 			p = &CodeLineW[CursorX];
 			BuffSetChar(p, 0xa0, 'H');
 
@@ -2861,14 +2952,18 @@
 			}
 
 			// \x83J\x81[\x83\\x83\x8B\x88ʒu\x82̕\xB6\x8E\x9A\x82\xCD Padding\x82ɂ\xB7\x82\xE9
-			//	\x82\xBD\x82\xBE\x82\xB5\x8Ds\x96\x96\x82̂Ƃ\xAB\x82\xCDPadding\x82\xF0\x93\xFC\x82\xEA\x82Ȃ\xA2
+			//	\x82\xBD\x82\xBE\x82\xB5\x8E\x9F\x82̎\x9E\x82\xCD Padding \x82\xF0\x93\xFC\x82\xEA\x82Ȃ\xA2
+			//	- \x8Ds\x96\x96\x82̂Ƃ\xAB (TODO \x82\xB1\x82̏\xF0\x8C\x8F\x82͕s\x97v?)
+			//	- \x8A\xEE\x92ꕶ\x8E\x9A\x82\xAA\x82\xA0\x82\xE9\x8F\xF3\x91ԂŁASpacing Mark\x95\xB6\x8E\x9A(\x83J\x81[\x83\\x83\x8B\x82\xAA+1\x88ړ\xAE\x82\xB7\x82錋\x8D\x87\x95\xB6\x8E\x9A)\x82\xAA\x93\xFC\x97͂\xB3\x82ꂽ\x82Ƃ\xAB
 			if (CursorX < NumOfColumns - 1) {
-				BuffSetChar(&CodeLineW[CursorX], 0, 'H');
-				CodeLineW[CursorX].Padding = TRUE;
-				CodeLineW[CursorX].attr = Attr.Attr;
-				CodeLineW[CursorX].attr2 = Attr.Attr2;
-				CodeLineW[CursorX].fg = Attr.Fore;
-				CodeLineW[CursorX].bg = Attr.Back;
+				if (add_base_char == FALSE) {
+					BuffSetChar(&CodeLineW[CursorX], 0, 'H');
+					CodeLineW[CursorX].Padding = TRUE;
+					CodeLineW[CursorX].attr = Attr.Attr;
+					CodeLineW[CursorX].attr2 = Attr.Attr2;
+					CodeLineW[CursorX].fg = Attr.Fore;
+					CodeLineW[CursorX].bg = Attr.Back;
+				}
 			}
 		}
 
@@ -2934,10 +3029,11 @@
 		}
 		// \x8C\xBB\x8D݂̈ʒu\x82\xAA\x91S\x8Ap\x82̍\xB6\x91\xA4 && \x93\xFC\x97͕\xB6\x8E\x9A\x82\xAA\x94\xBC\x8Ap ?
 		if (half_width && IsBuffFullWidth(p)) {
-			// \x91S\x8Ap\x82\xF0\x83X\x83y\x81[\x83X\x82ɒu\x82\xAB\x8A\xB7\x82\xA6\x82\xE9
-			assert(CursorX < NumOfColumns - 1);  // \x8Ds\x96\x96\x82ɑS\x8Ap\x82̍\xB6\x82͂\xB1\x82Ȃ\xA2
+			// \x8Ds\x96\x96\x82ɑS\x8Ap(2cell)\x88ȏ\xE3\x82̕\xB6\x8E\x9A\x82\xAA\x91\xB6\x8D݂\xB7\x82\xE9\x89”\\x90\xAB\x82\xAA\x82\xA0\x82\xE9
 			BuffSetChar(p, ' ', 'H');
-			BuffSetChar(p + 1, ' ', 'H');
+			if (CursorX < NumOfColumns - 1) {
+				BuffSetChar(p + 1, ' ', 'H');
+			}
 			if (StrChangeCount == 0) {
 				StrChangeCount = 3;
 				StrChangeStart = CursorX;
@@ -2951,11 +3047,17 @@
 				}
 			}
 		}
-		// \x8E\x9F\x82̕\xB6\x8E\x9A\x82\xAA\x91S\x8Ap && \x93\xFC\x97͕\xB6\x8E\x9A\x82\xAA\x91S\x8Ap ?
-		if (!Insert && !half_width && IsBuffFullWidth(p + 1)) {
-			// \x91S\x8Ap\x82\xF0\x92ׂ\xB7
-			BuffSetChar(p + 1, ' ', 'H');
-			BuffSetChar(p + 2, ' ', 'H');
+
+		{
+			buff_char_t *p1 = GetPtrRel(CodeBuffW, BufferSize, p, 1);
+
+			// \x8E\x9F\x82̕\xB6\x8E\x9A\x82\xAA\x91S\x8Ap && \x93\xFC\x97͕\xB6\x8E\x9A\x82\xAA\x91S\x8Ap ?
+			if (!Insert && !half_width && IsBuffFullWidth(p1)) {
+				// \x91S\x8Ap\x82\xF0\x92ׂ\xB7
+				buff_char_t *p2 = GetPtrRel(CodeBuffW, BufferSize, p1, 1);
+				BuffSetChar(p1, ' ', 'H');
+				BuffSetChar(p2, ' ', 'H');
+			}
 		}
 
 		if (Insert) {
@@ -3045,13 +3147,13 @@
 		else {
 			if ((Attr.AttrEx & AttrPadding) != 0) {
 				// \x8Bl\x82ߕ\xA8
-				buff_char_t *p = &CodeLineW[CursorX];
-				BuffSetChar(p, u32, 'H');
-				p->Padding = TRUE;
-				CodeLineW[CursorX].attr = Attr.Attr;
-				CodeLineW[CursorX].attr2 = Attr.Attr2;
-				CodeLineW[CursorX].fg = Attr.Fore;
-				CodeLineW[CursorX].bg = Attr.Back;
+				buff_char_t *b = &CodeLineW[CursorX];
+				BuffSetChar(b, u32, 'H');
+				b->Padding = TRUE;
+				b->attr = Attr.Attr;
+				b->attr2 = Attr.Attr2;
+				b->fg = Attr.Fore;
+				b->bg = Attr.Back;
 				move_x = 1;
 			}
 			else {
@@ -3085,13 +3187,13 @@
 				if (!half_width) {
 					// \x91S\x8Ap\x82̎\x9E\x82͎\x9F\x82̃Z\x83\x8B\x82͋l\x82ߕ\xA8
 					if (CursorX < NumOfColumns - 1) {
-						buff_char_t *p = &CodeLineW[CursorX + 1];
-						BuffSetChar(p, 0, 'H');
-						p->Padding = TRUE;
-						CodeLineW[CursorX + 1].attr = 0;
-						CodeLineW[CursorX + 1].attr2 = 0;
-						CodeLineW[CursorX + 1].fg = 0;
-						CodeLineW[CursorX + 1].bg = 0;
+						buff_char_t *b = &CodeLineW[CursorX + 1];
+						BuffSetChar(b, 0, 'H');
+						b->Padding = TRUE;
+						b->attr = 0;
+						b->attr2 = 0;
+						b->fg = 0;
+						b->bg = 0;
 					}
 				}
 			}
@@ -3264,7 +3366,7 @@
 			{
 				unsigned short ansi_char = b->ansi_char;
 				int i;
-				int cell = b->cell;
+				char cell = b->cell;
 				int c = 0;
 				if (ansi_char < 0x100) {
 					bufA[lenA] = ansi_char & 0xff;
@@ -4977,13 +5079,10 @@
 	DispSetCurCharAttr(Attr);
 }
 
-// TODO
 void BuffSaveScreen(void)
 {
-	PCHAR CodeDest, AttrDest, AttrDest2, AttrDestFG, AttrDestBG;
 	buff_char_t *CodeDestW;
 	LONG ScrSize;
-	size_t AllocSize;
 	LONG SrcPtr, DestPtr;
 	int i;
 
@@ -4990,15 +5089,9 @@
 	if (SaveBuff == NULL) {
 		ScrSize = NumOfColumns * NumOfLines;	// 1\x89\xE6\x96ʕ\xAA\x82̃o\x83b\x83t\x83@\x82̕ۑ\xB6\x90\x94
 		// \x91S\x89\xE6\x96ʕ\xAA\x82̃o\x83C\x83g\x90\x94
-		AllocSize = ScrSize * (5+sizeof(buff_char_t));
-		SaveBuff = malloc(AllocSize);
+		SaveBuff = calloc(sizeof(buff_char_t), ScrSize);
 		if (SaveBuff != NULL) {
-			CodeDest = SaveBuff;
-			AttrDest = CodeDest + ScrSize;
-			AttrDest2 = AttrDest + ScrSize;
-			AttrDestFG = AttrDest2 + ScrSize;
-			AttrDestBG = AttrDestFG + ScrSize;
-			CodeDestW = (buff_char_t *)(AttrDestBG + ScrSize);
+			CodeDestW = (buff_char_t *)SaveBuff;
 
 			SaveBuffX = NumOfColumns;
 			SaveBuffY = NumOfLines;
@@ -5018,41 +5111,17 @@
 
 void BuffRestoreScreen(void)
 {
-	PCHAR CodeSrc, AttrSrc, AttrSrc2, AttrSrcFG, AttrSrcBG;
 	buff_char_t *CodeSrcW;
-	LONG ScrSize;
 	LONG SrcPtr, DestPtr;
 	int i, CopyX, CopyY;
 
 	_CrtCheckMemory();
 	if (SaveBuff != NULL) {
-		CodeSrc = SaveBuff;
-		ScrSize = SaveBuffX * SaveBuffY;
+		CodeSrcW = (buff_char_t*)SaveBuff;
 
-		AttrSrc = CodeSrc + ScrSize;
-		AttrSrc2 = AttrSrc + ScrSize;
-		AttrSrcFG = AttrSrc2 + ScrSize;
-		AttrSrcBG = AttrSrcFG + ScrSize;
-		CodeSrcW = (buff_char_t*)(AttrSrcBG + ScrSize);
-
 		CopyX = (SaveBuffX > NumOfColumns) ? NumOfColumns : SaveBuffX;
 		CopyY = (SaveBuffY > NumOfLines) ? NumOfLines : SaveBuffY;
 
-		DestPtr = GetLinePtr(PageStart);
-		for (i=0; i<CopyY; i++) {
-			buff_char_t *p = &CodeBuffW[DestPtr];
-			int j;
-			for (j=0; j<CopyX; j++) {
-				if (p->CombinationCharSize16 > 0) {
-					free(p->pCombinationChars16);
-				}
-				if (p->CombinationCharSize32 > 0) {
-					free(p->pCombinationChars32);
-				}
-			}
-			DestPtr = NextLinePtr(DestPtr);
-		}
-
 		SrcPtr = 0;
 		DestPtr = GetLinePtr(PageStart);
 
@@ -5067,8 +5136,7 @@
 		}
 		BuffUpdateRect(WinOrgX,WinOrgY,WinOrgX+WinWidth-1,WinOrgY+WinHeight-1);
 
-		free(SaveBuff);
-		SaveBuff = NULL;
+		BuffDiscardSavedScreen();
 	}
 	_CrtCheckMemory();
 }
@@ -5076,6 +5144,13 @@
 void BuffDiscardSavedScreen(void)
 {
 	if (SaveBuff != NULL) {
+		int i;
+		buff_char_t *b = (buff_char_t *)SaveBuff;
+
+		for (i = 0; i < SaveBuffX * SaveBuffY; i++) {
+			FreeCombinationBuf(&b[i]);
+		}
+
 		free(SaveBuff);
 		SaveBuff = NULL;
 	}


ttssh2-commit メーリングリストの案内
Back to archive index