mutt/2714: Segfaults when trying to read header cache if cwd does not exist.
>Number: 2714
>Category: mutt
>Synopsis: Segfaults when trying to read header cache if cwd does not
>exist.
>Confidential: no
>Severity: normal
>Priority: medium
>Responsible: mutt-dev
>State: open
>Keywords:
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Jan 27 12:05:01 +0100 2007
>Originator: Christoph Berg <cb@xxxxxxxx>
>Release:
>Description:
Hi,
the attached patch looks sane to me.
Christoph
Reply-To: Daniel Burrows <dburrows@xxxxxxxxxx>, 386003@xxxxxxxxxxxxxxx
Date: Mon, 04 Sep 2006 08:57:44 -0700
From: Daniel Burrows <dburrows@xxxxxxxxxx>
To: Debian Bug Tracking System <submit@xxxxxxxxxxxxxxx>
Package: mutt
Version: 1.5.13-1
Severity: normal
Tags: patch
If I create a directory, cd to it, and delete it, then run mutt, I get
a segfault:
Reading /home/daniel/Mail/INBOX...Segmentation fault
Backtrace:
#0 mutt_hcache_open (
path=0x810e260 "/home/daniel/.mutt/header_cache/0e22bb19e355e524ac163
08aeab641c5", folder=0x816f048 "/home/daniel/Mail/INBOX") at ../hcache.c:985
#1 0x0808f640 in maildir_delayed_parsing (ctx=0x81443c8, md=0x0)
at ../mh.c:953
#2 0x0808f967 in mh_read_dir (ctx=0x81443c8, subdir=0x80fde3b "new")
at ../mh.c:1039
#3 0x0808f99e in maildir_read_dir (ctx=0x81443c8) at ../mh.c:1051
#4 0x0809323c in mx_open_mailbox (path=0xaf86f728 "/home/daniel/Mail/INBOX",
flags=0, pctx=0x0) at ../mx.c:708
#5 0x080879fe in main (argc=1, argv=0xaf86f914) at ../main.c:966
The relevant code fragment is:
---- snip ----
ret = (*h->env->open)(h->env, NULL, DB_INIT_MPOOL | DB_CREATE | DB_PRIVATE,
0600);
if (!ret)
{
ret = db_create(&h->db, h->env, 0);
if (ret)
{
h->env->close(h->env, 0);
mx_unlock_file(h->lockfile, h->fd, 0);
close(h->fd);
FREE(&h);
return NULL;
}
}
if (stat(path, &sb) != 0 && errno == ENOENT)
{
createflags |= DB_EXCL;
h->db->set_pagesize(h->db, pagesize);
}
ret = (*h->db->open)(h->db, NULL, path, folder, DB_BTREE, createflags, 0600);
----- snip -----
The last line is the one that crashes. In that line, h->db is NULL.
I've traced through the code, and what happens is that the call to
h->env->open fails (with a non-zero return code). mutt does not handle
this case; it simply leaves h->db set to NULL and blithely tries to
dereference it a few lines later.
I see two bugs here:
(1) why should opening the header cache database
(/home/daniel/.mutt/header_cache) fail when the cwd doesn't exist? This
seems rather unintuitive.
(2) obviously, mutt needs to handle failure of h->env->open more
gracefully than crashing. I suggest the attached patch;
it just uses the same unwinding code for both a failure of
env->open and db_create. When I apply it, mutt seems to work
fine (maybe it's slower because of not using the header cache,
but I haven't particularly noticed that yet).
Daniel
-- System Information:
Debian Release: testing/unstable
APT prefers unstable
APT policy: (500, 'unstable'), (1, 'experimental'), (1, 'unstable')
Architecture: i386 (i686)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.17-2-686
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Versions of packages mutt depends on:
ii esmtp-run [mail-transpo 0.5.1-4 User configurable relay-only MTA
ii libc6 2.3.6.ds1-4 GNU C Library: Shared libraries
ii libdb4.4 4.4.20-8 Berkeley v4.4 Database Libraries [
ii libgnutls13 1.4.2-1 the GNU TLS library - runtime libr
ii libidn11 0.6.5-1 GNU libidn library, implementation
ii libncursesw5 5.5-2 Shared libraries for terminal hand
ii libsasl2 2.1.19.dfsg1-0.2 Authentication abstraction library
Versions of packages mutt recommends:
ii locales 2.3.6.ds1-4 GNU C Library: National Language (
ii mime-support 3.37-1 MIME files 'mime.types' & 'mailcap
-- no debconf information
--- hcache.c 2006-05-18 11:44:29.000000000 -0700
+++ hcache.c.new 2006-09-04 08:56:55.000000000 -0700
@@ -966,14 +966,15 @@
if (!ret)
{
ret = db_create(&h->db, h->env, 0);
- if (ret)
- {
- h->env->close(h->env, 0);
- mx_unlock_file(h->lockfile, h->fd, 0);
- close(h->fd);
- FREE(&h);
- return NULL;
- }
+ }
+
+ if (ret)
+ {
+ h->env->close(h->env, 0);
+ mx_unlock_file(h->lockfile, h->fd, 0);
+ close(h->fd);
+ FREE(&h);
+ return NULL;
}
if (stat(path, &sb) != 0 && errno == ENOENT)
Christoph
--
cb@xxxxxxxx | http://www.df7cb.de/
>Fix:
Unknown
>Add-To-Audit-Trail: