I was seeing this error too.  It looks like there's a string handling
error in the part of it that collects filenames to index as it
traverses the source directory tree.  The commands below give a
reproducible text case, at least in my environment:

$ mkdir -p 
/tmp/debian-bug-276824/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/012345678901234567890
$ ./ra-index /tmp/ /tmp/debian-bug-276824/ 
Segmentation fault


You can see the problem in get_files_from_directory in parsedoc.c...

...
  char filename[256], *shortname;
...
    entry = readdir(directory);
    while (entry != NULL) {
      shortname = entry->d_name;
      if(strcmp(shortname,".") && strcmp(shortname,"..")) {
        strncpy(filename, sourcename, sizeof(filename)-2);
        filename[sizeof(filename)-1] = '\0';
        if (filename[strlen(filename)-1] != '/')
          strcat(filename, "/");
        strncat(filename, shortname, sizeof(filename)-1);
        
        /* find the end of the chain of filenames, and recursively append */
        for (current_filename = list_of_filenames; 
             (current_filename->next != NULL); 
             current_filename = current_filename->next);
        current_filename->next = get_files_from_directory (filename, excludees);
      }
      entry = readdir(directory);
    }
    /* Get rid of the dummy entry */
...

Care is taken to terminate the string after the strncpy but not after
the strncat.  filename is badly named here, perhaps, since it's really
a full pathname and can easily exceed 256 characters as subdirectory
names are catenated onto it.  When the combined length of filename,
the directory separator and shortname is 256 or greater strncat will
not zero terminate the string.  In my testing it seemed to take a
somewhat long subdirectory within the subdirectory that made the whole
path longer than 256 characters to trigger the segv for some reason,
as I do in the test case above, but that might have been random.

gdb output...

Starting program: /home/smallm/src/debian/remem-2.12/main/ra-index /tmp/ 
/tmp/debian-bug-276824/

Program received signal SIGSEGV, Segmentation fault.
get_files_from_directory (sourcename=0x10021ca8 "/tmp/debian-bug-276824", 
excludees=0x10021c88)
    at parsedoc.c:272
(gdb) bt
#0  get_files_from_directory (sourcename=0x10021ca8 "/tmp/debian-bug-276824", 
    excludees=0x10021c88) at parsedoc.c:272
#1  0x10005c0c in get_and_append_filenames (sources=0x10021c78, 
excludees=<value optimized out>, 
    lof=0x7f8fe528) at parsedoc.c:145
#2  0x100014f4 in main (argc=3, argv=0x7f8ff8b4) at imain.c:396


I think it makes more sense for filename to be dynamically allocated
based on the lengths of sourcename and shortname.  There's a patch
with that change attached.  With it ra-index passed the test case
above and was able to index my home directory without segfaulting.
I'm not checking for memory failure from malloc since that doesn't
seem to be done anywhere else in the program -- a problem for another
day?


-- 
Mike Small
[EMAIL PROTECTED]

--- remem-2.12/template/parsedoc.c.orig	2003-11-25 05:09:17.000000000 -0500
+++ remem-2.12/template/parsedoc.c	2006-07-23 17:17:12.000000000 -0400
@@ -165,7 +165,7 @@
 List_of_Filenames *get_files_from_directory(char *sourcename, char **excludees)
 {
   int i, isurl=0;
-  char filename[256], *shortname;
+  char *shortname;
   struct stat buf;
   DIR *directory;
   savant_direct *entry;
@@ -176,8 +176,6 @@
   list_of_filenames = (List_of_Filenames *) malloc (sizeof(List_of_Filenames));
   list_of_filenames->next = NULL;
 
-  filename[sizeof(filename)-1] = '\0';
-
   if ((strncmp(sourcename, "http://";, 7) == 0) || (strncmp(sourcename, "ftp://";, 6)==0)) {
     /* It's a URL, so it it's not excluded then just return the URL itself */
     isurl=1;
@@ -250,17 +248,24 @@
     while (entry != NULL) {
       shortname = entry->d_name;
       if(strcmp(shortname,".") && strcmp(shortname,"..")) {
-        strncpy(filename, sourcename, sizeof(filename)-2);
-        filename[sizeof(filename)-1] = '\0';
-        if (filename[strlen(filename)-1] != '/')
+        char * filename;
+        size_t sourcelen;
+
+        sourcelen = strlen(sourcename);
+        filename = (char *) malloc (sizeof(char) * (sourcelen + strlen(shortname) + 2));
+        strcpy(filename, sourcename);
+
+        if (filename[sourcelen-1] != '/')
           strcat(filename, "/");
-        strncat(filename, shortname, sizeof(filename)-1);
+        strcat(filename, shortname);
         
         /* find the end of the chain of filenames, and recursively append */
         for (current_filename = list_of_filenames; 
              (current_filename->next != NULL); 
              current_filename = current_filename->next);
         current_filename->next = get_files_from_directory (filename, excludees);
+
+        free(filename);
       }
       entry = readdir(directory);
     }

Reply via email to