Skip to main content.
home | support | download

Back to List Archive

3 anti-crash patches for swish(-e)

From: Luc Claeys <claeys(at)not-real.innet.be>
Date: Mon Mar 30 1998 - 09:02:03 GMT
I have 3 patches for the old swish, but they apply to swish-e as well

Context : sources from swish-efiles.1.1.tar.Z
	  Linux version 2.0.29
          gcc version egcs-2.90.23 980102 (egcs-1.0.1 release)

1) when there is no file extension and there is a dot in the path, 
   the stack can be overwritten.

   The function   ishtml(filename) [in "src/check.c" line 184] 
   copies the part of a filename after the last dot in a small local
   buffer.
   When that part of the filename is larger than the buffer, 
   the stack gets overwritten
   and we get a segmentation violation and indexing ends :-(

   for example, with the following path:
	/var/abc.1996/def/some_file_without_extension
   the last dot is ^
   the extension is ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   and that's longer than MAXSUFFIXLEN (10)

 Solution:
 ~~~~~~~~~

   I have changed the function ishtml() as follows
   avoiding the copy altogether. (diff patches at the end of the message)

int ishtml(filename)
     char *filename;
{
	char *suffix;

        /* point the last dot, in filename or in path */
	suffix = (char *) strrchr(filename, '.');

	if (suffix == NULL)
		return 0;

        suffix++;	/* point char after last dot */

	switch (strlen(suffix)) {
	    case 3: return strcmp(suffix, "htm")   == 0
                        || strcmp(suffix, "HTM")   == 0;
	    case 4: return strcmp(suffix, "html")  == 0
                        || strcmp(suffix, "HTML")  == 0;
	    case 5: return strcmp(suffix, "shtml") == 0
                        || strcmp(suffix, "SHTML") == 0;
	    default: return 0;
	}
}

2) The function isoksuffix(filename, rulelist) in file check.c
   corrupts the stack when a file without suffix is tested and there is a
   dot somewhere in the path.

  This occurs only when:
    the config option 'NoContents' is used and 
    there is no dot in the filename
    and there is a dot in the path 
    and the length of the string after the dot in the path is longer
    than MAXSUFFIXLEN.


 Solution:
 ~~~~~~~~~

  test length of the part of the path after the last dot.
  When it's longer than MAXSUFFIXLEN, do as if there was no dot 
  in the filename.  (diff patches at the end of the message)

int isoksuffix(filename, rulelist)
     char *filename;
     struct swline *rulelist;
{
	int badfile;
	char *c, suffix[MAXSUFFIXLEN], checksuffix[MAXSUFFIXLEN];
	struct swline *tmplist;

	tmplist = rulelist;
        if (tmplist == NULL)
                return 1;
	if ((c = (char *) strrchr(filename, '.')) == NULL)
		return 0;

+	/* when apparent suffix is too long, its probably a dot in the path. */
+	/* act as if there is no suffix */
+	if (strlen(c)  >  MAXSUFFIXLEN)
+	    return 0;
        
        badfile = 1;
	strcpy(checksuffix, c + 1);
        while (tmplist != NULL) {
		if ((c = (char *) strrchr(tmplist->line, '.')) == NULL)
			strcpy(suffix, tmplist->line);
		else
			strcpy(suffix, c + 1);
                if (lstrstr(suffix, checksuffix) && strlen(suffix) ==
		strlen(checksuffix))
                        badfile = 0;
                tmplist = tmplist->next;
        }
	return !(badfile);
}


3) In function   converttoascii(s)   in file   src/string.c   line 445
   When the conversion fails and does not change the string, the
   recursive call will recurse until the stack blows (after a long time).

 Solution:
 ~~~~~~~~~

   I propose to use an extra boolean flag that is set when the string is
   changed. If the string is not changed, there should not be a recursive
   call. In that case I propose to return a null string, thus throwing
   away that trouble-word.  (diff patches at the end of the message)

char *converttoascii(s)
     char *s;
{
	int i;
	char *c, *d, wrdent[MAXENTLEN], nument[MAXENTLEN];
	static char newword[MAXWORDLEN];
+       int  string_modified = 0;

	strcpy(newword, s);
	for (i = 0; entities[i] != NULL; i += 3) {

		sprintf(wrdent, "%s;", entities[i]);
		sprintf(nument, "%s;", entities[i + 1]);

		c = d = NULL;
		if ((entities[i])[0] != '\0')
			c = (char *) strstr(newword, wrdent);
		if ((entities[i + 1])[0] != '\0')
			d = (char *) strstr(newword, nument);
		if ((entities[i + 2])[0] != '\0') {
!			if (c != NULL) {
				strcpy(newword, (char *) replace(newword,
				wrdent, entities[i + 2]));
+                               string_modified = 1;
+                       }
!			if (d != NULL) {
				strcpy(newword, (char *) replace(newword,
				nument, entities[i + 2]));
+                               string_modified = 1;
+                       }
		}
	}

+	if (string_modified) {
            while (hasnonascii(newword))
		strcpy(newword, (char *) converttoascii(newword));
+       } else {
+           /* cannot convert, delete word */
+           newword[0] = 0;
+       }
	return newword;
}

I hope this is useful,

Luc Claeys <claeys@innet.be>

=======   here is the diff file with the 3 patches  =======
diff -cr orig/check.c src/check.c
*** orig/check.c	Fri Dec 19 00:47:55 1997
--- src/check.c	Mon Mar 30 10:19:18 1998
***************
*** 26,31 ****
--- 26,36 ----
  	if ((c = (char *) strrchr(filename, '.')) == NULL)
  		return 0;
  
+ 	/* when apparent suffix is too long, its probably a dot in the path. */
+ 	/* act as if there is no suffix */
+ 	if (strlen(c)  >  MAXSUFFIXLEN)
+ 	    return 0;
+         
  	badfile = 1;
  	strcpy(checksuffix, c + 1);
          while (tmplist != NULL) {
***************
*** 184,206 ****
  int ishtml(filename)
       char *filename;
  {
! 	char *c, suffix[MAXSUFFIXLEN];
  
! 	c = (char *) strrchr(filename, '.');
  
! 	if (c == NULL)
! 		return 0;
! 	strcpy(suffix, c + 1);
! 	if (suffix[0] == '\0')
  		return 0;
  
! 	if (!strncmp(suffix, "htm", 3))
! 		return 1;
! 	else if (!strncmp(suffix, "HTM", 3))
! 		return 1;
! 	else if (!strncmp(suffix, "shtml", 5))
! 		return 1;
! 	else if (!strncmp(suffix, "SHTML", 5))
! 		return 1;
! 	return 0;
  }
--- 189,211 ----
  int ishtml(filename)
       char *filename;
  {
! 	char *suffix;
  
!         /* point the last dot, in filename or in path */
! 	suffix = (char *) strrchr(filename, '.');
  
! 	if (suffix == NULL)
  		return 0;
  
!         suffix++;	/* point char after last dot */
! 
! 	switch (strlen(suffix)) {
! 	    case 3: return strcmp(suffix, "htm")   == 0
!                         || strcmp(suffix, "HTM")   == 0;
! 	    case 4: return strcmp(suffix, "html")  == 0
!                         || strcmp(suffix, "HTML")  == 0;
! 	    case 5: return strcmp(suffix, "shtml") == 0
!                         || strcmp(suffix, "SHTML") == 0;
! 	    default: return 0;
! 	}
  }
diff -cr orig/string.c src/string.c
*** orig/string.c	Fri Dec 19 00:47:55 1997
--- src/string.c	Mon Mar 30 10:17:21 1998
***************
*** 450,455 ****
--- 450,456 ----
  	int i;
  	char *c, *d, wrdent[MAXENTLEN], nument[MAXENTLEN];
  	static char newword[MAXWORDLEN];
+         int  string_modified = 0;
  
  	strcpy(newword, s);
  	for (i = 0; entities[i] != NULL; i += 3) {
***************
*** 463,480 ****
  		if ((entities[i + 1])[0] != '\0')
  			d = (char *) strstr(newword, nument);
  		if ((entities[i + 2])[0] != '\0') {
! 			if (c != NULL)
  				strcpy(newword, (char *) replace(newword,
  				wrdent, entities[i + 2]));
! 			if (d != NULL)
  				strcpy(newword, (char *) replace(newword,
  				nument, entities[i + 2]));
  		}
  	}
  
! 	while (hasnonascii(newword))
  		strcpy(newword, (char *) converttoascii(newword));
! 
  	return newword;
  }
  
--- 464,489 ----
  		if ((entities[i + 1])[0] != '\0')
  			d = (char *) strstr(newword, nument);
  		if ((entities[i + 2])[0] != '\0') {
! 			if (c != NULL) {
  				strcpy(newword, (char *) replace(newword,
  				wrdent, entities[i + 2]));
!                                 string_modified = 1;
!                         }
! 			if (d != NULL) {
  				strcpy(newword, (char *) replace(newword,
  				nument, entities[i + 2]));
+                                 string_modified = 1;
+                         }
  		}
  	}
  
! 	if (string_modified) {
!             while (hasnonascii(newword))
  		strcpy(newword, (char *) converttoascii(newword));
!         } else {
!             /* cannot convert, delete word */
!             newword[0] = 0;
!         }
  	return newword;
  }
  
Received on Mon Mar 30 06:58:12 1998