Re: [Fwd: mutt buffer overflow]
On 2005-08-18 19:25:54 +0100, Lars Hecking forwarded from bugtraq:
> overwriting other memory with many possible consequences. This
> counter should never exceed the size and I believe the logic in
> the convert_to_state() function is supposed to reset it to 0,
> however there is a flaw - I have included a possible fix but I'm
> not sure it's the 100% correct fix and there seem to be no
> developers willing to fix this so far. There are other functions
> affected in the same way due to copy/paste, such as
> mutt_decode_uuencoded() that this patch should also fix.
To begin with, neither of the proof of concept examples [1], [2]
posted to bugtraq leads to a buffer overflow here (latest CVS built
on Fedora Core 4).
1. ftp://ftp.00f.net/misc/mutt-crash-poc.mbox
2. http://sightly.net/peter/tmp/mutt-bug
So Frank's observation that this might be tied to a particular iconv
implementation seems to be valid. Still, the question is if mutt is
making assumptions that it shouldn't make, or if that iconv
implementation is broken.
The assumption that is made in mutt_decode_xbit is that
mutt_convert_to_state actually decreases the l counter by at least
one -- if l is sufficiently large.
This maps to a similar assumption that mutt_iconv doesn't return
without at least consuming one byte.
mutt_convert_to_state invokes mutt_iconv with inrepls set to 0, and
outrepl being "?", which immediately leaves out a lot of the
complexity in that function.
Reading through it, the one way in which that function does not
consume any input is when the input buffer begins with an incomplete
multibyte sequence. Our assumption now becomes that any string of
sufficient length either begins with a valid (hence consumed, at
least partially) or invalid (hence skipped) multibyte sequence, but
not with an incomplete one.
I'd be curious to hear what the attached program prints on a
platform where the iso-2022-jp example [1] leads to a crash.
Regards,
--
Thomas Roessler · Personal soap box at <http://log.does-not-exist.org/>.
#include <stdio.h>
#include <string.h>
#include <iconv.h>
#include <errno.h>
int main ()
{
iconv_t cd = iconv_open ("ISO_8859-15", "ISO-2022-JP");
char _ib[] =
"\033AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
char _ob[1000];
size_t ibl = sizeof (_ib) - 1;
size_t obl = sizeof (_ob);
char *ib = _ib;
char *ob = _ob;
int rv = iconv (cd, &ib, &ibl, &ob, &obl);
printf ("rv = %d, errno = %d (%s)\n",
rv, errno, errno == EILSEQ ? "EILSEQ" : errno == EINVAL ? "EINVAL" :
"?");
printf ("'%s'\n", _ob);
return 0;
}