Make sure we don't run out of the output buffer. Maybe fixes bug #3557
[claws.git] / src / codeconv.c
index 98b41b3b02fe3159b7bb6bc871243672802f2128..39e259fc6bf31c9f89a591ec5e830fb6de1b3be0 100644 (file)
@@ -155,10 +155,10 @@ void codeconv_set_strict(gboolean mode)
 static gint conv_jistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
 {
        const guchar *in = inbuf;
-       guchar *out = outbuf;
+       gchar *out = outbuf;
        JISState state = JIS_ASCII;
 
-       while (*in != '\0') {
+       while (*in != '\0' && (out - outbuf) > outlen - 3) {
                if (*in == ESC) {
                        in++;
                        if (*in == '$') {
@@ -291,10 +291,10 @@ static gint conv_jis_hantozen(guchar *outbuf, guchar jis_code, guchar sound_sym)
 static gint conv_euctojis(gchar *outbuf, gint outlen, const gchar *inbuf)
 {
        const guchar *in = inbuf;
-       guchar *out = outbuf;
+       gchar *out = outbuf;
        JISState state = JIS_ASCII;
 
-       while (*in != '\0') {
+       while (*in != '\0' && (out - outbuf) < outlen - 3) {
                if (IS_ASCII(*in)) {
                        K_OUT();
                        *out++ = *in++;
@@ -380,9 +380,9 @@ static gint conv_euctojis(gchar *outbuf, gint outlen, const gchar *inbuf)
 static gint conv_sjistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
 {
        const guchar *in = inbuf;
-       guchar *out = outbuf;
+       gchar *out = outbuf;
 
-       while (*in != '\0') {
+       while (*in != '\0' && (out - outbuf) < outlen - 3) {
                if (IS_ASCII(*in)) {
                        *out++ = *in++;
                } else if (issjiskanji1(*in)) {
@@ -467,7 +467,7 @@ static gint conv_euctoutf8(gchar *outbuf, gint outlen, const gchar *inbuf)
                if (cd == (iconv_t)-1) {
                        cd = iconv_open(CS_UTF_8, CS_EUC_JP);
                        if (cd == (iconv_t)-1) {
-                               g_warning("conv_euctoutf8(): %s\n",
+                               g_warning("conv_euctoutf8(): %s",
                                          g_strerror(errno));
                                iconv_ok = FALSE;
                                strncpy2(outbuf, inbuf, outlen);
@@ -524,7 +524,7 @@ static gint conv_utf8toeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
                if (cd == (iconv_t)-1) {
                        cd = iconv_open(CS_EUC_JP, CS_UTF_8);
                        if (cd == (iconv_t)-1) {
-                               g_warning("conv_utf8toeuc(): %s\n",
+                               g_warning("conv_utf8toeuc(): %s",
                                          g_strerror(errno));
                                iconv_ok = FALSE;
                                strncpy2(outbuf, inbuf, outlen);
@@ -695,6 +695,8 @@ conv_get_fallback_for_private_encoding(const gchar *encoding)
 {
        if (encoding && (encoding[0] == 'X' || encoding[0] == 'x') &&
            encoding[1] == '-') {
+               if (!g_ascii_strcasecmp(encoding, CS_X_MACCYR))
+                       return CS_MACCYR;
                if (!g_ascii_strcasecmp(encoding, CS_X_GBK))
                        return CS_GBK;
        }
@@ -749,8 +751,17 @@ gchar *conv_codeset_strdup(const gchar *inbuf,
        size_t len;
        CodeConvFunc conv_func;
 
-       if (!strcmp2(src_code, dest_code))
+       if (!strcmp2(src_code, dest_code)) {
+               CharSet dest_charset = conv_get_charset_from_str(dest_code);
+               if (strict_mode && dest_charset == C_UTF_8) {
+                       /* ensure valid UTF-8 if target is UTF-8 */
+                       if (!g_utf8_validate(inbuf, -1, NULL)) {
+                               return NULL;
+                       }
+               }
+               /* otherwise, try for a lucky day */
                return g_strdup(inbuf);
+       }
 
        src_code = conv_get_fallback_for_private_encoding(src_code);
        conv_func = conv_get_code_conv_func(src_code, dest_code);
@@ -945,7 +956,7 @@ gchar *conv_iconv_strdup_with_cd(const gchar *inbuf, iconv_t cd)
                } else if (E2BIG == errno) {
                        EXPAND_BUF();
                } else {
-                       g_warning("conv_iconv_strdup(): %s\n",
+                       g_warning("conv_iconv_strdup(): %s",
                                  g_strerror(errno));
                        break;
                }
@@ -956,7 +967,7 @@ gchar *conv_iconv_strdup_with_cd(const gchar *inbuf, iconv_t cd)
                if (E2BIG == errno) {
                        EXPAND_BUF();
                } else {
-                       g_warning("conv_iconv_strdup(): %s\n",
+                       g_warning("conv_iconv_strdup(): %s",
                                  g_strerror(errno));
                        break;
                }
@@ -1013,6 +1024,7 @@ static const struct {
        {C_WINDOWS_1257,        CS_WINDOWS_1257},
        {C_WINDOWS_1258,        CS_WINDOWS_1258},
        {C_KOI8_R,              CS_KOI8_R},
+       {C_MACCYR,              CS_MACCYR},
        {C_KOI8_T,              CS_KOI8_T},
        {C_KOI8_U,              CS_KOI8_U},
        {C_ISO_2022_JP,         CS_ISO_2022_JP},
@@ -1675,7 +1687,7 @@ void conv_encode_header_full(gchar *dest, gint len, const gchar *src,
                                                *dest = '\0';
                                                return;
                                        } else {
-                                               g_warning("conv_encode_header(): code conversion failed\n");
+                                               g_warning("conv_encode_header(): code conversion failed");
                                                conv_unreadable_8bit(part_str);
                                                out_str = g_strdup(part_str);
                                        }
@@ -1708,7 +1720,7 @@ void conv_encode_header_full(gchar *dest, gint len, const gchar *src,
                                out_str = conv_codeset_strdup
                                        (part_str, cur_encoding, out_encoding);
                                if (!out_str) {
-                                       g_warning("conv_encode_header(): code conversion failed\n");
+                                       g_warning("conv_encode_header(): code conversion failed");
                                        conv_unreadable_8bit(part_str);
                                        out_str = g_strdup(part_str);
                                }
@@ -1722,8 +1734,10 @@ void conv_encode_header_full(gchar *dest, gint len, const gchar *src,
 
                                if (use_base64)
                                        enc_str = g_base64_encode(out_str, out_str_len);
-                               else
+                               else {
+                                       Xalloca(enc_str, out_enc_str_len + 1, );
                                        qp_q_encode(enc_str, out_str);
+                               }
 
                                g_free(out_str);
 
@@ -1732,7 +1746,10 @@ void conv_encode_header_full(gchar *dest, gint len, const gchar *src,
                                g_snprintf(destp, mime_block_len + 1,
                                           MIMESEP_BEGIN "%s%s%s" MIMESEP_END,
                                           out_encoding, mimesep_enc, enc_str);
-                               g_free(enc_str);
+
+                               if (use_base64)
+                                       g_free(enc_str);
+
                                destp += mime_block_len;
                                srcp += cur_len;
 
@@ -1782,7 +1799,7 @@ gchar *conv_filename_to_utf8(const gchar *fs_file)
 
        utf8_file = g_filename_to_utf8(fs_file, -1, NULL, NULL, &error);
        if (error) {
-               g_warning("failed to convert encoding of file name: %s\n",
+               g_warning("failed to convert encoding of file name: %s",
                          error->message);
                g_error_free(error);
        }