Package: sylpheed-claws Version: 0.9.13-1 Severity: normal Tags: patch Sylpheed-claws segfaults when using the sylpheed-claws-pgpinline-plugin from <URL:http://sylpheed.mine.nu:9981/debian/>.
Steps to reproduce: * Start sylpheed-claws * Load pgpinline-plugin * Click "Compose Email" * Write some nonsense (fill To/Subject/Body) * Check Options->Privacy System->PGP Inline * Check Options->Sign * Click Submit * Enter your passphrase * Sylpheed-Claws segfaults Tracking the bug down showed that it's caused by pgpinline_sign()'s call to procmime_encode_content() [pgpinline.c:442]. Looking at the latter function it can be seen that: a) The function will always fail when (meminfo->content == MIMECONTENT_MEM) && (encoding == ENC_BASE64). b) The error handling of that function terribly sucks, which turns a not-so-serious bug into a segfault. The source of the bug is line 432: --- if (canonicalize_file(mimeinfo->data.filename, tmp_file) < 0) { --- It is always called, no matter what mimeinfo->content is. Since mimeinfo->data is a union (filename/mem), canonicalize_file tries to open the passed mime data (the gpg-clearsigned message) as file, which fails. At this point tmp_file has not yet been created by canonicalize_file, so the following fopen on it (line 436) fails too, which causes fread to access an invalid FILE* [tmp_fd] on line 444, which results in the segfault. So this bug is clearly one of sylpheed-claws, and not of the pgpinline-plugin. Fixing the segfault is easy, adding >return FALSE;< in 2 places is enough. See attatchment sylpheed-claws-fixsegv.patch. Making the function fully working with is a bit more problematic, since procmime_encode_content() doesn't even know the name of the file where the mime content is stored. The name isn't passed up by str_open_as_stream() (which in turn doesn't have it itself, because it's not returned by my_tmpfile()). So you're basically left with two options: modify my_tmpfile and str_open_as_stream to pass up the filename of the temporary file, or to make a canonicalize_file variant which works on FILE* objects. An implementation of the second way is in sylpheed-claws-fullfix.patch. Please apply sylpheed-claws-fixsegv.patch as well as sylpheed-claws-fullfix.patch. The first one fixes the error handling, the second one makes the thing work right. Perhaps this bug is related to #292089 and #280160. The symptoms look similar, but I don't really understand what the submitter means in #292089, and I don't use SA via sylpheed, so I can't check #280160. Cheers, Greek0 -- System Information: Debian Release: 3.1 APT prefers unstable APT policy: (990, 'unstable'), (500, 'testing') Architecture: i386 (i686) Kernel: Linux 2.6.8r01112004 Locale: [EMAIL PROTECTED], [EMAIL PROTECTED] (charmap=ISO-8859-15) Versions of packages sylpheed-claws depends on: ii libaspell15 0.50.5-5 The GNU Aspell spell-checker runti ii libc6 2.3.2.ds1-20 GNU C Library: Shared libraries an ii libcompfaceg1 1989.11.11-24 Compress/decompress images for mai ii libglib1.2 1.2.10-9 The GLib library of C routines ii libgpgme6 0.3.16-2 GPGME - GnuPG Made Easy ii libgtk1.2 1.2.10-17 The GIMP Toolkit set of widgets fo ii libldap2 2.1.30-3 OpenLDAP libraries ii libpisock8 0.11.8-10 Library for communicating with a P ii libssl0.9.7 0.9.7e-3 SSL shared libraries ii libx11-6 4.3.0.dfsg.1-10 X Window System protocol client li ii libxext6 4.3.0.dfsg.1-10 X Window System miscellaneous exte ii libxi6 4.3.0.dfsg.1-10 X Window System Input extension li ii sylpheed-claws-i18n 0.9.13-1 Locale data for Sylpheed Claws (i1 ii xlibs 4.3.0.dfsg.1-10 X Keyboard Extension (XKB) configu -- no debconf information
--- old/sylpheed-claws-0.9.13/src/procmime.c 2004-12-04 09:09:00.000000000 +0100 +++ sylpheed-claws-0.9.13/src/procmime.c 2005-01-28 00:56:01.000000000 +0100 @@ -432,12 +432,14 @@ if (canonicalize_file(mimeinfo->data.filename, tmp_file) < 0) { g_free(tmp_file); fclose(infp); + return FALSE; } if ((tmp_fp = fopen(tmp_file, "rb")) == NULL) { FILE_OP_ERROR(tmp_file, "fopen"); unlink(tmp_file); g_free(tmp_file); fclose(infp); + return FALSE; } }
diff -Nur old/sylpheed-claws-0.9.13.fixsegv/src/common/utils.c sylpheed-claws-0.9.13/src/common/utils.c --- old/sylpheed-claws-0.9.13.fixsegv/src/common/utils.c 2005-01-29 11:04:33.000000000 +0100 +++ sylpheed-claws-0.9.13/src/common/utils.c 2005-01-29 11:23:57.000000000 +0100 @@ -2597,10 +2597,7 @@ gint canonicalize_file(const gchar *src, const gchar *dest) { FILE *src_fp, *dest_fp; - gchar buf[BUFFSIZE]; - gint len; - gboolean err = FALSE; - gboolean last_linebreak = FALSE; + gint ErrorCode; if ((src_fp = fopen(src, "rb")) == NULL) { FILE_OP_ERROR(src, "fopen"); @@ -2618,6 +2615,44 @@ g_warning("can't change file mode\n"); } + + if ((ErrorCode = canonicalize_file_from_fp(src_fp, dest_fp)) < 0) { + switch (ErrorCode) { + case -1: + FILE_OP_ERROR(src, "reading from"); + break; + case -2: + FILE_OP_ERROR(dest, "writing to"); + break; + default: + fprintf(stderr, + "Unknown Error in canonicalize_file_from_fp"); + break; + } + + fclose(src_fp); + fclose(dest_fp); + unlink(dest); + return -1; + } + + fclose(src_fp); + fclose(dest_fp); + return 0; +} + +/* canonicalize_file_from_fp reads from src_fp, changes all line endings to + * CRLF and adds a CRLF to the last line, if needed. The output is written to + * dest_fp. 0 is returned on normal operation, -1 if there was an error reading + * from src_fp, and -2 if there was an error writing to dest_fp. + * canonicalize_file_from_fp rewinds both fp's when it completed without + * errors. Otherwise the positions of the streams are undefined. */ +gint canonicalize_file_from_fp(FILE* src_fp, FILE* dest_fp) +{ + gchar buf[BUFFSIZE]; + gint len; + gboolean last_linebreak = FALSE; + while (fgets(buf, sizeof(buf), src_fp) != NULL) { gint r = 0; @@ -2641,34 +2676,21 @@ } if (r == EOF) { - g_warning("writing to %s failed.\n", dest); - fclose(dest_fp); - fclose(src_fp); - unlink(dest); - return -1; + return -2; } } if (last_linebreak == TRUE) { if (fputs("\r\n", dest_fp) == EOF) - err = TRUE; + return -2; } if (ferror(src_fp)) { - FILE_OP_ERROR(src, "fgets"); - err = TRUE; - } - fclose(src_fp); - if (fclose(dest_fp) == EOF) { - FILE_OP_ERROR(dest, "fclose"); - err = TRUE; - } - - if (err) { - unlink(dest); return -1; } + rewind(src_fp); + rewind(dest_fp); return 0; } diff -Nur old/sylpheed-claws-0.9.13.fixsegv/src/common/utils.h sylpheed-claws-0.9.13/src/common/utils.h --- old/sylpheed-claws-0.9.13.fixsegv/src/common/utils.h 2005-01-29 11:04:33.000000000 +0100 +++ sylpheed-claws-0.9.13/src/common/utils.h 2005-01-29 11:24:10.000000000 +0100 @@ -410,6 +410,7 @@ gchar *canonicalize_str (const gchar *str); gint canonicalize_file (const gchar *src, const gchar *dest); +gint canonicalize_file_from_fp(FILE* src_fp, FILE* dest_fp); gint canonicalize_file_replace (const gchar *file); gint uncanonicalize_file (const gchar *src, const gchar *dest); diff -Nur old/sylpheed-claws-0.9.13.fixsegv/src/procmime.c sylpheed-claws-0.9.13/src/procmime.c --- old/sylpheed-claws-0.9.13.fixsegv/src/procmime.c 2005-01-29 11:07:40.000000000 +0100 +++ sylpheed-claws-0.9.13/src/procmime.c 2005-01-29 10:50:19.000000000 +0100 @@ -425,20 +425,39 @@ gchar inbuf[B64_LINE_SIZE], outbuf[B64_BUFFSIZE]; FILE *tmp_fp = infp; gchar *tmp_file = NULL; + gint ErrorCode; if (mimeinfo->type == MIMETYPE_TEXT || mimeinfo->type == MIMETYPE_MESSAGE) { + tmp_file = get_tmp_file(); - if (canonicalize_file(mimeinfo->data.filename, tmp_file) < 0) { + if ((tmp_fp = fopen(tmp_file, "w+b")) == NULL) { + FILE_OP_ERROR(tmp_file, "fopen"); + unlink(tmp_file); g_free(tmp_file); fclose(infp); return FALSE; } - if ((tmp_fp = fopen(tmp_file, "rb")) == NULL) { - FILE_OP_ERROR(tmp_file, "fopen"); + + if ((ErrorCode = canonicalize_file_from_fp(infp, tmp_fp)) < 0) { + switch (ErrorCode) { + case -1: + fprintf(stderr, + "Read error in canonicalize_file_from_fp"); + break; + case -2: + FILE_OP_ERROR(tmp_file, "writing to"); + break; + default: + fprintf(stderr, + "Unknown error in canonicalize_file_from_fp"); + break; + } + + fclose(infp); + fclose(tmp_fp); unlink(tmp_file); g_free(tmp_file); - fclose(infp); return FALSE; } }