Return to BSD News archive
Newsgroups: comp.bugs.2bsd
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!news.rmit.EDU.AU!news.unimelb.EDU.AU!munnari.OZ.AU!news.ecn.uoknor.edu!news.cis.okstate.edu!newsfeed.ksu.ksu.edu!news.mid.net!sbctri.tri.sbc.com!newspump.wustl.edu!news.ecn.bgu.edu!vixen.cso.uiuc.edu!newsfeed.internetmci.com!salliemae!europa.chnt.gtegsc.com!wlbr!moe!sms
From: sms@moe.2bsd.com (Steven M. Schultz)
Subject: tcsh dumps core when traversing symlinks (#313)
Organization: 2BSD, Simi Valley CA USA
Message-ID: <DpDMqq.5uG@moe.2bsd.com>
Date: Fri, 5 Apr 1996 06:44:50 GMT
Lines: 481
Subject: tcsh dumps core when traversing symlinks (#313)
Index: new/tcsh/sh.dir.c,alloc11.c,... 2.11BSD
Description:
tcsh dumps core with no error message when traversing symlinks.
Repeat-By:
/u is a symlink to where the home directories reside. In my case
a "ln -s /userfiles /u" had been done earlier.
Then:
cd /
cd u
cd sms1
pwd
*BOOM* - core dump with no diagnostic message
Another way, suggested a year ago (yes, it's taken that long for this
to bubble to the top of the TODO list):
mkdir tmp
cd
cd /u/sms1
cd tmp
*BOOM*
Fix:
There were two problems, the second being triggered by the first.
The first problem was a corruption of the malloc arena due to a
string copy overrunning a malloc'd buffer (when the allocation was
done room was not reserved for the terminating NULL).
The second problem was that 'botch()' called 'printf' in an attempt
to report the first error. Printf() calls malloc - but the malloc arena
was corrupt, so the botch() routine gets called to report the error.
See a pattern here? Eventually the stack underflows and the kernel
mercifully terminates the program with a core dump.
In the process of fixing the above the base segment grew above 48kb.
To avoid having to rearrange the overlays a couple other .c files
were modified to include additional "register" declarations. This
reduced the code size to less than it was before the bugs were fixed!
The overlay arrangement should be revisited some day. It is definitely
sub optimal - the simplest command causing many overlay switches. It's
a tribute to the efficiency of the kernel overlay switching that the
interactive response of tcsh is not noticeably affected.
Cut where indicated, saving to a file (/tmp/313). Then:
patch -p0 < /tmp/313
cd /usr/src/new/tcsh
make
make install
make clean
this takes about 50 minutes.
This and previous updates are available via anonymous FTP to either
FTP.IIPO.GTEGSC.COM and MOE.2BSD.COM in the directory /pub/2.11BSD.
==========================cut here=========================
*** /usr/src/new/tcsh/sh.dir.c.old Wed Aug 21 10:47:20 1991
--- /usr/src/new/tcsh/sh.dir.c Thu Apr 4 21:11:17 1996
***************
*** 1,4 ****
- /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.dir.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
/*
* sh.dir.c: Directory manipulation functions
*/
--- 1,3 ----
***************
*** 37,43 ****
#include "config.h"
#if !defined(lint) && !defined(pdp11)
static char *rcsid()
! { return "$Id: sh.dir.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
#endif
--- 36,42 ----
#include "config.h"
#if !defined(lint) && !defined(pdp11)
static char *rcsid()
! { return "$Id: sh.dir.c,v 3.0.1 1996/04/04 21:49:28 sms Exp $"; }
#endif
***************
*** 160,166 ****
Char ***v;
char *str;
{
! Char **n = *v, *s;
dirflag = 0;
for (n++; *n != NOSTR && (*n)[0] == '-'; n++)
--- 159,165 ----
Char ***v;
char *str;
{
! register Char **n = *v, *s;
dirflag = 0;
for (n++; *n != NOSTR && (*n)[0] == '-'; n++)
***************
*** 248,254 ****
void
dtilde()
{
! struct directory *d = dcwd;
do {
if (d == &dhead)
--- 247,253 ----
void
dtilde()
{
! register struct directory *d = dcwd;
do {
if (d == &dhead)
***************
*** 266,272 ****
*/
Char *
dnormalize(cp)
! Char *cp;
{
#define UC (unsigned char)
--- 265,271 ----
*/
Char *
dnormalize(cp)
! register Char *cp;
{
#define UC (unsigned char)
***************
*** 279,285 ****
#ifdef S_IFLNK
if (adrof(STRig__symlinks)) {
int dotdot = 0;
! Char *dp, *cwd;
#ifdef apollo
bool slashslash;
#endif
--- 278,284 ----
#ifdef S_IFLNK
if (adrof(STRig__symlinks)) {
int dotdot = 0;
! register Char *dp, *cwd;
#ifdef apollo
bool slashslash;
#endif
***************
*** 974,980 ****
*/
p2 = cp + Strlen(p2);
sp = newcp = (Char *) xmalloc((size_t)
! ((cc + Strlen(p2)) * sizeof(Char)));
while (*p1)
*sp++ = *p1++;
while (*p2)
--- 973,979 ----
*/
p2 = cp + Strlen(p2);
sp = newcp = (Char *) xmalloc((size_t)
! ((cc + Strlen(p2) + 1) * sizeof(Char)));
while (*p1)
*sp++ = *p1++;
while (*p2)
***************
*** 1031,1037 ****
Char *s;
int cnt;
{
! struct directory *dp;
dp = dcwd;
if (cnt < 0) { /* < 0 ==> last dir requested. */
--- 1030,1036 ----
Char *s;
int cnt;
{
! register struct directory *dp;
dp = dcwd;
if (cnt < 0) { /* < 0 ==> last dir requested. */
***************
*** 1061,1067 ****
*/
void
dextract(dp)
! struct directory *dp;
{
if (dp == dcwd)
return;
--- 1060,1066 ----
*/
void
dextract(dp)
! register struct directory *dp;
{
if (dp == dcwd)
return;
*** /usr/src/new/tcsh/alloc11.c.old Mon Aug 19 07:41:13 1991
--- /usr/src/new/tcsh/alloc11.c Thu Apr 4 20:48:49 1996
***************
*** 1,16 ****
#if !defined(lint) && !defined(NOSCCS)
! static char *sccsid = "@(#)alloc.c 4.1 10/9/80";
#endif
#include "config.h"
! /* #include "sh.local.h" */
#define debug
#ifdef debug
#define ASSERT(p) if(!(p))botch("p");else
botch(s)
char *s;
{
! printf("assertion botched: %s\n",s);
abort();
}
#else
--- 1,38 ----
#if !defined(lint) && !defined(NOSCCS)
! static char *sccsid = "@(#)alloc.c 4.1.1 1996/4/4";
#endif
#include "config.h"
! #include <unistd.h>
! #include <sys/types.h>
! #include <sys/uio.h>
!
#define debug
#ifdef debug
#define ASSERT(p) if(!(p))botch("p");else
+
+ /*
+ * Can't use 'printf' below because that can call malloc(). If the malloc
+ * arena is corrupt the result is a recursive loop which underflows the stack
+ * and obfuscates the initial problem.
+ */
botch(s)
char *s;
{
! struct iovec iov[3];
! register struct iovec *v = iov;
! char *ab = "assertion botched: ";
!
! v->iov_base = ab;
! v->iov_len = strlen(ab);
! v++;
! v->iov_base = s;
! v->iov_len = strlen(s);
! v++;
! v->iov_base = "\n";
! v->iov_len = 1;
!
! writev(STDOUT_FILENO, iov, 3);
abort();
}
#else
***************
*** 47,53 ****
#define WORD sizeof(union store)
#define BLOCK 1024 /* a multiple of WORD*/
#define BUSY 1
! #define NULL 0
#define testbusy(p) ((INT)(p)&BUSY)
#define setbusy(p) (union store *)((INT)(p)|BUSY)
#define clearbusy(p) (union store *)((INT)(p)&~BUSY)
--- 69,75 ----
#define WORD sizeof(union store)
#define BLOCK 1024 /* a multiple of WORD*/
#define BUSY 1
!
#define testbusy(p) ((INT)(p)&BUSY)
#define setbusy(p) (union store *)((INT)(p)|BUSY)
#define clearbusy(p) (union store *)((INT)(p)&~BUSY)
***************
*** 220,224 ****
free += i;
}
}
! printf("%d used, %d free, %u end\n", used, free, clearbusy(alloct));
}
--- 242,246 ----
free += i;
}
}
! printf("%u used, %u free, %u end\n", used, free, clearbusy(alloct));
}
*** /usr/src/new/tcsh/ed.defns.c.old Tue Aug 20 20:57:42 1991
--- /usr/src/new/tcsh/ed.defns.c Thu Apr 4 21:10:08 1996
***************
*** 1,4 ****
- /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/ed.defns.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
/*
* ed.defns.c: Editor function definitions and initialization
*/
--- 1,3 ----
***************
*** 37,43 ****
#include "config.h"
#if !defined(lint) && !defined(pdp11)
static char *rcsid()
! { return "$Id: ed.defns.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
#endif
#include "sh.h"
--- 36,42 ----
#include "config.h"
#if !defined(lint) && !defined(pdp11)
static char *rcsid()
! { return "$Id: ed.defns.c,v 3.0.1 1996/04/04 21:49:28 sms Exp $"; }
#endif
#include "sh.h"
***************
*** 1482,1488 ****
{
Char buf[3];
register int i;
! KEYCMD *map;
map = CcKeyMap;
for (i = 0; i <= 0377 && CcKeyMap[i] != F_METANEXT; i++);
--- 1481,1487 ----
{
Char buf[3];
register int i;
! register KEYCMD *map;
map = CcKeyMap;
for (i = 0; i <= 0377 && CcKeyMap[i] != F_METANEXT; i++);
*** /usr/src/new/tcsh/sh.hist.c.old Tue Aug 20 12:13:00 1991
--- /usr/src/new/tcsh/sh.hist.c Thu Apr 4 21:31:23 1996
***************
*** 1,4 ****
- /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.hist.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
/*
* sh.hist.c: Shell history expansions and substitutions
*/
--- 1,3 ----
***************
*** 37,43 ****
#include "config.h"
#if !defined(lint) && !defined(pdp11)
static char *rcsid()
! { return "$Id: sh.hist.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
#endif
#include "sh.h"
--- 36,42 ----
#include "config.h"
#if !defined(lint) && !defined(pdp11)
static char *rcsid()
! { return "$Id: sh.hist.c,v 3.0.1 1996/04/04 21:49:28 sms Exp $"; }
#endif
#include "sh.h"
***************
*** 171,178 ****
static void
dohist1(hp, np, rflg, hflg, tflg)
! struct Hist *hp;
! int *np, rflg, hflg, tflg;
{
bool print = (*np) > 0;
--- 170,178 ----
static void
dohist1(hp, np, rflg, hflg, tflg)
! register struct Hist *hp;
! register int *np;
! int rflg, hflg, tflg;
{
bool print = (*np) > 0;
***************
*** 195,201 ****
register struct Hist *hp;
int hflg, tflg;
{
! struct tm *t;
char ampm = 'a';
if (hflg == 0) {
--- 195,201 ----
register struct Hist *hp;
int hflg, tflg;
{
! register struct tm *t;
char ampm = 'a';
if (hflg == 0) {
*** /usr/src/new/tcsh/tc.alloc.c.old Tue Aug 20 12:13:08 1991
--- /usr/src/new/tcsh/tc.alloc.c Thu Apr 4 21:08:28 1996
***************
*** 1,4 ****
- /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/tc.alloc.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
/*
* tc.alloc.c (Caltech) 2/21/82
* Chris Kingsley, kingsley@cit-20.
--- 1,3 ----
***************
*** 45,51 ****
#include "config.h"
#if !defined(lint) && !defined(pdp11)
static char *rcsid()
! { return "$Id: tc.alloc.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
#endif
--- 44,50 ----
#include "config.h"
#if !defined(lint) && !defined(pdp11)
static char *rcsid()
! { return "$Id: tc.alloc.c,v 3.0.1 1996/04/04 21:49:28 sms Exp $"; }
#endif
***************
*** 496,502 ****
memalign_t
Realloc(p, n)
ptr_t p;
! size_t n;
{
ptr_t ptr;
--- 495,501 ----
memalign_t
Realloc(p, n)
ptr_t p;
! register size_t n;
{
ptr_t ptr;
***************
*** 510,518 ****
memalign_t
Calloc(s, n)
! size_t s, n;
{
! char *sptr;
ptr_t ptr;
n *= s;
--- 509,517 ----
memalign_t
Calloc(s, n)
! register size_t s, n;
{
! register char *sptr;
ptr_t ptr;
n *= s;
*** /VERSION.old Sat Mar 30 20:46:46 1996
--- /VERSION Thu Apr 4 21:52:18 1996
***************
*** 1,4 ****
! Current Patch Level: 312
2.11 BSD
============
--- 1,4 ----
! Current Patch Level: 313
2.11 BSD
============