From c3bbb22f131ea6e273d4921bd60c73e78a13e00b Mon Sep 17 00:00:00 2001
From: "Ying-Chun Liu (PaulLiu)" <paulliu@debian.org>
Date: Sat, 8 Aug 2020 03:45:19 +0800
Subject: [PATCH] src/codeconv.c: Fix CVE-2015-8614

This code comes from the latest claws-mail upstream which fixes
the security issue.

Signed-off-by: Ying-Chun Liu (PaulLiu) <paulliu@debian.org>
---
 src/codeconv.c | 74 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 48 insertions(+), 26 deletions(-)

diff --git a/src/codeconv.c b/src/codeconv.c
index 254843e..0efbc13 100644
--- a/src/codeconv.c
+++ b/src/codeconv.c
@@ -128,10 +128,14 @@ typedef enum
 void 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') {
+	/*
+	 * Loop outputs up to 3 bytes in each pass (aux kanji) and we
+	 * need 1 byte to terminate the output
+	 */
+	while (*in != '\0' && (out - outbuf) < outlen - 4) {
 		if (*in == ESC) {
 			in++;
 			if (*in == '$') {
@@ -192,6 +196,7 @@ void conv_jistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
 	}
 
 	*out = '\0';
+	return ;
 }
 
 #define JIS_HWDAKUTEN		0x5e
@@ -263,10 +268,15 @@ static gint conv_jis_hantozen(guchar *outbuf, guchar jis_code, guchar sound_sym)
 void 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') {
+	/*
+	 * Loop outputs up to 6 bytes in each pass (aux shift + aux
+	 * kanji) and we need up to 4 bytes to terminate the output
+	 * (ASCII shift + null)
+	 */
+	while (*in != '\0' && (out - outbuf) < outlen - 10) {
 		if (isascii(*in)) {
 			K_OUT();
 			*out++ = *in++;
@@ -286,26 +296,32 @@ void conv_euctojis(gchar *outbuf, gint outlen, const gchar *inbuf)
 			}
 		} else if (iseuchwkana1(*in)) {
 			if (iseuchwkana2(*(in + 1))) {
-			  guchar jis_ch[2];
-			  gint len;
-			  
-			  if (iseuchwkana1(*(in + 2)) &&
-			      iseuchwkana2(*(in + 3)))
-			    len = conv_jis_hantozen
-			      (jis_ch,
-			       *(in + 1), *(in + 3));
-			  else
-			    len = conv_jis_hantozen
-			      (jis_ch,
-			       *(in + 1), '\0');
-			  if (len == 0)
-			    in += 2;
-			  else {
-			    K_IN();
-			    in += len * 2;
-			    *out++ = jis_ch[0];
-			    *out++ = jis_ch[1];
-			  }
+				if (0) {
+					HW_IN();
+					in++;
+					*out++ = *in++ & 0x7f;
+				} else {
+					guchar jis_ch[2];
+					gint len;
+
+					if (iseuchwkana1(*(in + 2)) &&
+					    iseuchwkana2(*(in + 3)))
+						len = conv_jis_hantozen
+							(jis_ch,
+							 *(in + 1), *(in + 3));
+					else
+						len = conv_jis_hantozen
+							(jis_ch,
+							 *(in + 1), '\0');
+					if (len == 0)
+						in += 2;
+					else {
+						K_IN();
+						in += len * 2;
+						*out++ = jis_ch[0];
+						*out++ = jis_ch[1];
+					}
+				}
 			} else {
 				K_OUT();
 				in++;
@@ -340,14 +356,19 @@ void conv_euctojis(gchar *outbuf, gint outlen, const gchar *inbuf)
 
 	K_OUT();
 	*out = '\0';
+	return ;
 }
 
 void conv_sjistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
 {
 	const guchar *in = inbuf;
-	guchar *out = outbuf;
+	gchar *out = outbuf;
 
-	while (*in != '\0') {
+	/*
+	 * Loop outputs up to 2 bytes in each pass and we need 1 byte
+	 * to terminate the output
+	 */
+	while (*in != '\0' && (out - outbuf) < outlen - 3) {
 		if (isascii(*in)) {
 			*out++ = *in++;
 		} else if (issjiskanji1(*in)) {
@@ -386,6 +407,7 @@ void conv_sjistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
 	}
 
 	*out = '\0';
+	return ;
 }
 
 void conv_anytoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)