Hi all, I found emelFM2 very interesting project, to substitute Midnight Commander in X environment, but was very surprised when emelFM shows 'Segmentation Fault' at first run! Digging into code shows that root of the problem was in e2_fs_get_file_contents(), which continue to execute even if e2_fs_safeopen() return -1. Even more - it tries to make stat() call on bad descriptor and use statbuf.st_size to allocate memory, regardless of successful or unsuccessful stat(). On first start emelfm tries to open ~/.config/emelfm2/cache file with this function. I'have attached patch that adding 'else' statements, so execution will continue only on success :) Patch is against 0.3.6, but SVN version is affected too (as of rev.806). Best regards, Dmitry Zamaruev.
diff -Naur emelfm2-0.3.6.orig/src/filesystem/e2_fs.c emelfm2-0.3.6/src/filesystem/e2_fs.c --- emelfm2-0.3.6.orig/src/filesystem/e2_fs.c 2007-11-22 23:36:34.000000000 +0200 +++ emelfm2-0.3.6/src/filesystem/e2_fs.c 2008-02-14 17:08:28.000000000 +0200 @@ -2214,70 +2214,71 @@ { retval = FALSE; fmt = _("Cannot open file %s"); - } - if (e2_fs_fstat (fdesc, &sb)) - { - retval = FALSE; - fmt = _("Cannot get information about %s"); - e2_fs_safeclose (fdesc); - } - - size_t len = sb.st_size; - if (string) - len += sizeof (gchar); //in case we need to append a 0 - -// *contents = malloc (len); //not size-limited, but imposes cleanup hassles - *contents = g_try_malloc (len); //allows up to ULONG_MAX - if (*contents == NULL) - { - e2_utils_show_memory_message (); + } else { + if (e2_fs_fstat (fdesc, &sb)) + { + retval = FALSE; + fmt = _("Cannot get information about %s"); + e2_fs_safeclose (fdesc); + } else { + + size_t len = sb.st_size; + if (string) + len += sizeof (gchar); //in case we need to append a 0 + +// *contents = malloc (len); //not size-limited, but imposes cleanup hassles + *contents = g_try_malloc (len); //allows up to ULONG_MAX + if (*contents == NULL) + { + e2_utils_show_memory_message (); #ifdef E2_VFSTMP -// *E2_ERR_NAME = g_error_new_literal (G_FILE_ERROR, errno, g_strerror (errno)); -// E2_ERR_CLEARBACKUP (localerr); +// *E2_ERR_NAME = g_error_new_literal (G_FILE_ERROR, errno, g_strerror (errno)); +// E2_ERR_CLEARBACKUP (localerr); #endif - e2_fs_safeclose (fdesc); - return FALSE; - } - + e2_fs_safeclose (fdesc); + return FALSE; + } /*ssize_t*/gulong nread = e2_fs_read (fdesc, *contents, sb.st_size E2_ERR_SAMEARG()); - if (nread < 0) - { - g_free (*contents); //or free() if needed - *contents = NULL; - nread = 0; - retval = FALSE; - fmt = _("Error reading file %s"); - } -/* if (retval && nread < (gulong)sb.st_size) - { - read less than expected - } -*/ - if (retval && string) - { - gchar *s; - if (nread >= sizeof (gchar)) - { - s = *contents + nread - sizeof (gchar); - if (*s == '\0') - nread -= sizeof (gchar); //OK ? - else - { - s += sizeof (gchar); - *s = '\0'; - } - } - else //nothing read - { - s = *contents; - *s = '\0'; - } - } - e2_fs_safeclose (fdesc); - - if (contlength != NULL) - *contlength = nread; + if (nread < 0) + { + g_free (*contents); //or free() if needed + *contents = NULL; + nread = 0; + retval = FALSE; + fmt = _("Error reading file %s"); + } +/* if (retval && nread < (gulong)sb.st_size) + { + read less than expected + } +*/ + if (retval && string) + { + gchar *s; + if (nread >= sizeof (gchar)) + { + s = *contents + nread - sizeof (gchar); + if (*s == '\0') + nread -= sizeof (gchar); //OK ? + else + { + s += sizeof (gchar); + *s = '\0'; + } + } + else //nothing read + { + s = *contents; + *s = '\0'; + } + } + e2_fs_safeclose (fdesc); + + if (contlength != NULL) + *contlength = nread; + } + } if (!retval && app.output.opt_show_on_new != NULL) //at session-start, when reading config //etc, we can't yet show any error