hansen@pegasus.UUCP (Tony L. Hansen) (04/27/85)
I've found a few bugs in the termcap library that still exist in 4.2BSD. 1: tgetent() cannot be called more than once in a program (hopcount doesn't get rezeroed). 2: an entry with ":tc=foo" but no trailing colon will cause coredumps. 3. buffer overflows can still occur, causing coredumps. 4. in tc=foo, foo can only be 16 chars long. this is not checked. Apply patch at will. Tony Hansen pegasus!hansen *** /tmp/termcap.c Fri Apr 26 16:41:17 1985 --- /tmp/ntermcap.c Fri Apr 26 16:57:40 1985 *************** *** 2,8 static char sccsid[] = "@(#)termcap.c 4.1 (Berkeley) 6/27/83"; #endif ! #define BUFSIZ 1024 #define MAXHOP 32 /* max number of tc= indirections */ #define E_TERMCAP "/etc/termcap" --- 2,8 ----- static char sccsid[] = "@(#)termcap.c 4.1 (Berkeley) 6/27/83"; #endif ! #define TBUFSIZE 2048 #define MAXHOP 32 /* max number of tc= indirections */ #define E_TERMCAP "/etc/termcap" *************** *** 36,41 tgetent(bp, name) char *bp, *name; { register char *cp; register int c; register int i = 0, cnt = 0; --- 36,59 ----- tgetent(bp, name) char *bp, *name; { + /* Tony Hansen */ + int ret; + hopcount = 0; + ret = _tgetent(bp, name); + /* + There is some sort of bug in the check way down below to prevent + buffer overflow. I really don't want to track it down, so I + upped the standard buffer size and check here to see if the created + buffer is larger than the old buffer size. + */ + if (strlen(bp) >= 1024) + write(2,"Termcap entry too long\n", 23); + return ret; + } + + static _tgetent(bp, name) + char *bp, *name; + { register char *cp; register int c; register int i = 0, cnt = 0; *************** *** 39,45 register char *cp; register int c; register int i = 0, cnt = 0; ! char ibuf[BUFSIZ]; char *cp2; int tf; --- 57,63 ----- register char *cp; register int c; register int i = 0, cnt = 0; ! char ibuf[TBUFSIZ]; char *cp2; int tf; *************** *** 77,83 cp = bp; for (;;) { if (i == cnt) { ! cnt = read(tf, ibuf, BUFSIZ); if (cnt <= 0) { close(tf); return (0); --- 95,101 ----- cp = bp; for (;;) { if (i == cnt) { ! cnt = read(tf, ibuf, TBUFSIZE); if (cnt <= 0) { close(tf); return (0); *************** *** 92,98 } break; } ! if (cp >= bp+BUFSIZ) { write(2,"Termcap entry too long\n", 23); break; } else --- 110,116 ----- } break; } ! if (cp >= bp+TBUFSIZE) { write(2,"Termcap entry too long\n", 23); break; } else *************** *** 120,125 tnchktc() { register char *p, *q; char tcname[16]; /* name of similar terminal */ char tcbuf[BUFSIZ]; char *holdtbuf = tbuf; --- 138,145 ----- tnchktc() { register char *p, *q; + #define TERMNAMESIZE 16 + char tcname[TERMNAMESIZE]; /* name of similar terminal */ char tcname[16]; /* name of similar terminal */ char tcbuf[TBUFSIZE]; char *holdtbuf = tbuf; *************** *** 121,127 { register char *p, *q; char tcname[16]; /* name of similar terminal */ ! char tcbuf[BUFSIZ]; char *holdtbuf = tbuf; int l; --- 141,147 ----- #define TERMNAMESIZE 16 char tcname[TERMNAMESIZE]; /* name of similar terminal */ char tcname[16]; /* name of similar terminal */ ! char tcbuf[TBUFSIZE]; char *holdtbuf = tbuf; int l; *************** *** 135,140 /* p now points to beginning of last field */ if (p[0] != 't' || p[1] != 'c') return(1); strcpy(tcname,p+3); q = tcname; while (q && *q != ':') --- 155,161 ----- /* p now points to beginning of last field */ if (p[0] != 't' || p[1] != 'c') return(1); + strncpy(tcname,p+3, TERMNAMESIZE); /* TLH */ strcpy(tcname,p+3); q = tcname; while (*q && *q != ':') *************** *** 137,143 return(1); strcpy(tcname,p+3); q = tcname; ! while (q && *q != ':') q++; *q = 0; if (++hopcount > MAXHOP) { --- 158,164 ----- strncpy(tcname,p+3, TERMNAMESIZE); /* TLH */ strcpy(tcname,p+3); q = tcname; ! while (*q && *q != ':') q++; *q = 0; if (++hopcount > MAXHOP) { *************** *** 144,150 write(2, "Infinite tc= loop\n", 18); return (0); } ! if (tgetent(tcbuf, tcname) != 1) return(0); for (q=tcbuf; *q != ':'; q++) ; --- 165,171 ----- write(2, "Infinite tc= loop\n", 18); return (0); } ! if (_tgetent(tcbuf, tcname) != 1) return(0); for (q=tcbuf; *q != ':'; q++) ; *************** *** 149,155 for (q=tcbuf; *q != ':'; q++) ; l = p - holdtbuf + strlen(q); ! if (l > BUFSIZ) { write(2, "Termcap entry too long\n", 23); q[BUFSIZ - (p-tbuf)] = 0; } --- 170,176 ----- for (q=tcbuf; *q != ':'; q++) ; l = p - holdtbuf + strlen(q); ! if (l > TBUFSIZE) { write(2, "Termcap entry too long\n", 23); q[TBUFSIZE - (p-tbuf)] = 0; } *************** *** 151,157 l = p - holdtbuf + strlen(q); if (l > BUFSIZ) { write(2, "Termcap entry too long\n", 23); ! q[BUFSIZ - (p-tbuf)] = 0; } strcpy(p, q+1); tbuf = holdtbuf; --- 172,178 ----- l = p - holdtbuf + strlen(q); if (l > TBUFSIZE) { write(2, "Termcap entry too long\n", 23); ! q[TBUFSIZE - (p-tbuf)] = 0; } strcpy(p, q+1); tbuf = holdtbuf;