]> git.wh0rd.org Git - nano.git/commitdiff
in display_string(), fix memory corruption problems caused by not
authorDavid Lawrence Ramsey <pooka109@gmail.com>
Fri, 3 Feb 2006 03:58:49 +0000 (03:58 +0000)
committerDavid Lawrence Ramsey <pooka109@gmail.com>
Fri, 3 Feb 2006 03:58:49 +0000 (03:58 +0000)
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
src/winio.c

index 9d1e7f61092c4c047b59e44cf78cf7fe24b7ebd5..c1f55573cc363eda9c6ab504fc760bdd35a0cd5c 100644 (file)
--- 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:
index 4a3c8a0abeb6a2c0345f750c22b57a4e57a6401d..b0897aca0a8cf54c16993d9db8599d203970aa42 100644 (file)
@@ -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);