From 114cfb63f449a7e6520ad9e5406dbbf606abc301 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Fri, 3 Feb 2006 03:58:49 +0000 Subject: [PATCH] in display_string(), fix memory corruption problems caused by not allocating enough space for converted when a line ends in a tab(s) and we're not in UTF-8 mode git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@3272 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 3 +++ src/winio.c | 34 ++++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9d1e7f61..c1f55573 100644 --- a/ChangeLog +++ b/ChangeLog @@ -37,6 +37,9 @@ CVS code - Mike Frysinger) display_string() - Fix minor memory leak. (DLR) + - Fix memory corruption problems caused by not allocating enough + space for converted when a line ends in a tab(s) and we're not + in UTF-8 mode. (DLR, found by Nick Warne and Mike Frysinger) - doc/nano.1: - Better display the default values for quotestr. (DLR) - doc/nanorc.5: diff --git a/src/winio.c b/src/winio.c index 4a3c8a0a..b0897aca 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1809,10 +1809,22 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool assert(column <= start_col); - /* Allocate enough space for the entire line. */ - alloc_len = (mb_cur_max() * (COLS + 1)); + /* Make sure there's enough room for the initial character, whether + * it's a multibyte control character, a non-control multibyte + * character, a tab character, or a null terminator. Rationale: + * + * multibyte control character followed by a null terminator: + * 1 byte ('^') + mb_cur_max() bytes + 1 byte ('\0') + * multibyte non-control character followed by a null terminator: + * mb_cur_max() bytes + 1 byte ('\0') + * tab character followed by a null terminator: + * mb_cur_max() bytes + (tabsize - 1) bytes + 1 byte ('\0') + * + * Since tabsize has a minimum value of 1, it can substitute for 1 + * byte above. */ + alloc_len = (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE; + converted = charalloc(alloc_len); - converted = charalloc(alloc_len + 1); index = 0; if (buf[start_index] != '\t' && (column < start_col || (dollars && @@ -1849,9 +1861,17 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool #endif } - while (index < alloc_len - 1 && buf[start_index] != '\0') { + while (buf[start_index] != '\0') { buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL); + /* Make sure there's enough room for the next character, whether + * it's a multibyte control character, a non-control multibyte + * character, a tab character, or a null terminator. */ + if (index + mb_cur_max() + tabsize + 1 >= alloc_len - 1) { + alloc_len += (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE; + converted = charealloc(converted, alloc_len); + } + /* If buf contains a tab character, interpret it. */ if (*buf_mb == '\t') { #if !defined(NANO_TINY) && defined(ENABLE_NANORC) @@ -1923,8 +1943,10 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool free(buf_mb); - if (index < alloc_len - 1) - converted[index] = '\0'; + assert(alloc_len >= index + 1); + + /* Null terminate converted. */ + converted[index] = '\0'; /* Make sure converted takes up no more than len columns. */ index = actual_x(converted, len);