diff options
author | Kevin McCarthy <kevin@8t8.us> | 2022-04-08 20:19:27 -0700 |
---|---|---|
committer | Kevin McCarthy <kevin@8t8.us> | 2022-04-12 11:07:15 -0700 |
commit | f26d304b22e18942e4af6f98f826006cf27e8fde (patch) | |
tree | 61791e189db1c8406a73f16980213b79236affe7 /charset.c | |
parent | 4ae494ca621842c97f16da0bba61689ab458556c (diff) |
Fix integer overflow in mutt_convert_string().
In the case of a *very* large message header (which is possible via a
compressed encrypted message) it's possible to overflow the incorrect
assignment of strlen() to an int local variable.
Thanks to Tavis Ormandy for the bug report and patch, which this
commit is based upon.
Although Tavis wasn't able to find an exploit, it was almost possible
to make ob small and obl big, which would have allowed attacker
control of a heap corruption.
Change the strlen() to assign directly to ibl (of type size_t). This
prevents signed to unsigned conversion of len to ibl, which make the
attack almost possible.
Note that ibl should reflect the number of bytes to be converted by
iconv(), so the change of ibl to strlen() instead of (strlen() + 1) is
intentional, and correct.
ob is allocated with an additional byte for a trailing nul, which is
appended after the conversion.
Diffstat (limited to 'charset.c')
-rw-r--r-- | charset.c | 12 |
1 files changed, 9 insertions, 3 deletions
@@ -33,6 +33,7 @@ #include <dirent.h> #include <unistd.h> #include <errno.h> +#include <stdint.h> #include "mutt.h" #include "charset.h" @@ -489,7 +490,6 @@ int mutt_convert_string (char **ps, const char *from, const char *to, int flags) if (to && from && (cd = mutt_iconv_open (to, from, flags)) != (iconv_t)-1) { - int len; ICONV_CONST char *ib; char *buf, *ob; size_t ibl, obl; @@ -503,8 +503,14 @@ int mutt_convert_string (char **ps, const char *from, const char *to, int flags) else outrepl = "?"; - len = strlen (s); - ib = s, ibl = len + 1; + ib = s; + ibl = strlen (s); + if (ibl >= SIZE_MAX / MB_LEN_MAX) + { + iconv_close (cd); + return -1; + } + obl = MB_LEN_MAX * ibl; ob = buf = safe_malloc (obl + 1); |