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