[comp.sources.bugs] NULL pointer reference bug in system 5 ARC

root@hobbes.UUCP (John Plocher) (07/16/87)

This is a note to report a few (more) problems with the System5 ARC 
which was posted back before May 87.  These problems may also be in
the BSD and MS-DOS versions.

The reason I got into ARC again was that I wanted to add handling for PKarc's
SCRUNCHING (compression type 9).  I have not added the compression/decompression
routines; all I did was modify arclst.c and arcunp.c to spit out helpful notes
upon encountering type 9 headers.

I also made System5 14 char filenames OPTIONAL and DOS 12 char filenames the
DEFAULT!  This program is primarily used to handle DOS stuff...

Anyways, here is the stuff I found:

To repeat:

	/usr/src/dos/ls> ls
	LS.C	LS.OBJ	LS.EXE	LS.arc
	/usr/src/dos/ls> arc ai LS.arc LS*
	Segmentation violation  core dumped
	/usr/src/dos/ls>

Reason:	Boundry condition!
	The file LS.arc is the LAST member of the arg[] list sent to
	sortarg().  Since LS.arc is the name of the *archive*, it is
	removed by:

	    while (strcmp(arg[top],arcname) == 0) {
		for (seek = top; seek < num;seek++)
		    arg[seek] = arg[seek + 1];
		arg[--num] = '\0';
		dups++;
	    }

	When the loop goes into pass 2 after 'removing' LS.arc it does
	a strcmp(0, arcname).

	BTW:  Change   arg[--num] = '\0';   to   arg[--num] = NULL;
	      arg is declared as char *arg[];   An array of POINTERS to
	      chars!  The way it is coded is WRONG.

	The following loop which checks for duplicate names has the
	same problem.

Fix:

/*
 *	arcmisc.c	1.2
 ...

sortarg(num,arg)                       /* sort argument list, remove dups */
int num;
char *arg[];
{
    ...

    /* find any occurences of 'arcname', and remove them */

    for (top = 0;top < num;top++) {
!       while (arg[top] && strcmp(arg[top],arcname) == 0) {
            for (seek = top; seek < num;seek++)
                arg[seek] = arg[seek + 1];
!           arg[--num] = NULL;
            dups++;
        }
    }

    /* find any other duplicate arguments (ignoring pathnames), */
    /* and remove the second and subsequent occurences */

    for (top = 0;top < num-1;top++) {
        buf1 = arg[top];
        buf2 = arg[top + 1];
        if (i = strrchr(arg[top],'/')) buf1 = i + 1;
        if (i = strrchr(arg[top + 1],'/')) buf2 = i + 1;
!       while (buf1 && buf2 && strcmp(buf1,buf2) == 0) {
            for (seek = top + 1;seek < num;seek++)
                arg[seek] = arg[seek + 1];
!           arg[--num] = NULL;
            buf2 = arg[top + 1];
            if (i = strrchr(arg[top + 1],'/')) buf2 = i + 1;
            dups++;
        }
    }
    ...

-- 
John Plocher uwvax!geowhiz!uwspan!plocher  plocher%uwspan.UUCP@uwvax.CS.WISC.EDU