Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libterm PR/10266: t_getstr() leaks memory. This PR will ...



details:   https://anonhg.NetBSD.org/src/rev/92ce4c1ad2d3
branches:  trunk
changeset: 516867:92ce4c1ad2d3
user:      christos <christos%NetBSD.org@localhost>
date:      Wed Oct 31 21:52:17 2001 +0000

description:
PR/10266: t_getstr() leaks memory. This PR will stay in feedback
until the problem gets addressed properly. The following fix
is a stopgap measure to stop the leaking :-(

I fixed the t_getstr() memory leak problem, but that instantly
revealed a problem in t_agetstr() which is an extremely broken
interface. It realloc's memory, potentially moving the area where
it returned pointers into in previous calls. This function needs
to be removed and or changed. I added a horrible work-around for
now, but I will revisit the problem shortly. In the meantime nobody
should be using the t_agetstr() API, and I'll be fixing the rest
of the programs and or the API when I figure out the best solution...
This is t_agetstr() is used by:

        games/hack/hack.termcap.c
        games/larn/io.c
        games/tetris/screen.c
        lib/libterm/termcap.c
        lib/libterm/termcap.h
        libexec/getty/main.c
        usr.bin/top/screen.c
        usr.bin/ul/ul.c

diffstat:

 lib/libterm/termcap.c |  46 +++++++++++++++++++++++++++++-----------------
 1 files changed, 29 insertions(+), 17 deletions(-)

diffs (121 lines):

diff -r 7f7a9a8c68a7 -r 92ce4c1ad2d3 lib/libterm/termcap.c
--- a/lib/libterm/termcap.c     Wed Oct 31 21:39:02 2001 +0000
+++ b/lib/libterm/termcap.c     Wed Oct 31 21:52:17 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: termcap.c,v 1.38 2001/01/29 01:22:31 christos Exp $    */
+/*     $NetBSD: termcap.c,v 1.39 2001/10/31 21:52:17 christos Exp $    */
 
 /*
  * Copyright (c) 1980, 1993
@@ -38,7 +38,7 @@
 #if 0
 static char sccsid[] = "@(#)termcap.c  8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: termcap.c,v 1.38 2001/01/29 01:22:31 christos Exp $");
+__RCSID("$NetBSD: termcap.c,v 1.39 2001/10/31 21:52:17 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -101,9 +101,13 @@
        cap_ptr = capability;
        limit = 255;
        (*bp)->up = t_getstr(*bp, "up", &cap_ptr, &limit);
+       if ((*bp)->up)
+               (*bp)->up = strdup((*bp)->up);
        cap_ptr = capability;
        limit = 255;
        (*bp)->bc = t_getstr(*bp, "bc", &cap_ptr, &limit);
+       if ((*bp)->bc)
+               (*bp)->bc = strdup((*bp)->bc);
        
        return 0;
 }
@@ -240,9 +244,13 @@
                cap_ptr = capability;
                limit = 255;
                (*bp)->up = t_getstr(*bp, "up", &cap_ptr, &limit);
+               if ((*bp)->up)
+                       (*bp)->up = strdup((*bp)->up);
                cap_ptr = capability;
                limit = 255;
                (*bp)->bc = t_getstr(*bp, "bc", &cap_ptr, &limit);
+               if ((*bp)->bc)
+                       (*bp)->bc = strdup((*bp)->bc);
        }
                
        return (i + 1);
@@ -354,8 +362,6 @@
  * placed in area, which is a ref parameter which is updated.
  * limit is the number of characters allowed to be put into
  * area, this is updated.
- *
- * returns dynamically allocated region, passed from cgetstr().
  */
 char *
 t_getstr(info, id, area, limit)
@@ -390,7 +396,9 @@
                        return NULL;
                }
        
-               strcpy(*area, s);
+               (void)strcpy(*area, s);
+               free(s);
+               s = *area;
                *area += i + 1;
                if (limit != NULL) *limit -= i;
        
@@ -446,11 +454,17 @@
  * also returned to the caller.  If the string is not found or a
  * memory allocation fails then NULL is returned and bufptr and area
  * are unchanged.
+ *
+ * XXX: This is horribly broken because realloc's can move memory and
+ * invalidate attributes we've already returned. Only possible way to
+ * fix it for now is to allocate a lot -- 8K, and leak if we need to
+ * realloc. This API needs to be destroyed!.
  */
+#define BSIZE 8192
 char *
 t_agetstr(struct tinfo *info, const char *id, char **bufptr, char **area)
 {
-       size_t new_size, offset;
+       size_t new_size;
        char *new_buf;
        
        _DIAGASSERT(info != NULL);
@@ -461,26 +475,24 @@
        t_getstr(info, id, NULL, &new_size);
 
          /* either the string is empty or the capability does not exist. */
-       if (new_size == 0)
+       if (new_size == 0 || new_size > BSIZE)
                return NULL;
 
          /* check if we have a buffer, if not malloc one and fill it in. */
        if (*bufptr == NULL) {
-               if ((new_buf = (char *) malloc(new_size)) == NULL)
+               if ((new_buf = (char *) malloc(BSIZE)) == NULL)
                        return NULL;
                *bufptr = new_buf;
                *area = new_buf;
-       } else {
-               offset = *area - *bufptr;
-               if ((new_buf = realloc(*bufptr, offset + new_size)) == NULL)
-                       return NULL;
-               
-               *bufptr = new_buf;
-               *area = *bufptr + offset; /* we need to do this just in case
-                                            realloc shifted the buffer. */
+       } else if (*area - *bufptr >= BSIZE - new_size) {
+               char buf[BSIZE];
+               char *b = buf;
+               size_t len = BSIZE;
+               /* Leak! */
+               return strdup(t_getstr(info, id, &b, &len));
        }
+       return t_getstr(info, id, area, NULL);
        
-       return t_getstr(info, id, area, NULL);
 }
  
 /*



Home | Main Index | Thread Index | Old Index