From 5590d5fe99d88c1a9d47852e6be36aa590401f01 Mon Sep 17 00:00:00 2001
From: Tatsuo Ishii <ishii@postgresql.org>
Date: Mon, 19 Nov 2001 06:48:39 +0000
Subject: [PATCH] Fix nasty bugs in pg_convert() and pg_convert2().

    o they sometimes returns a result garbage string appended.
    o they do not work if client encoding is different from server
      encoding
---
 src/backend/utils/mb/mbutils.c | 49 +++++++++++++++++++++++++++-------
 1 file changed, 40 insertions(+), 9 deletions(-)

diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index 645b9f3260a..f7bc6fdac38 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -3,7 +3,7 @@
  * client encoding and server internal encoding.
  * (currently mule internal code (mic) is used)
  * Tatsuo Ishii
- * $Id: mbutils.c,v 1.25 2001/10/25 05:49:51 momjian Exp $
+ * $Id: mbutils.c,v 1.26 2001/11/19 06:48:39 ishii Exp $
  */
 #include "postgres.h"
 
@@ -220,6 +220,8 @@ pg_convert(PG_FUNCTION_ARGS)
 	from_mic_converter dest;
 	unsigned char *result;
 	text	   *retval;
+	unsigned char *str;
+	int len;
 
 	if (encoding < 0)
 		elog(ERROR, "Invalid encoding name %s", NameStr(*s));
@@ -231,14 +233,28 @@ pg_convert(PG_FUNCTION_ARGS)
 		elog(ERROR, "Conversion from %s to %s is not possible", NameStr(*s), encoding_name);
 	}
 
-	result = pg_do_encoding_conversion(VARDATA(string), VARSIZE(string) - VARHDRSZ,
-									   src, dest);
+	/* make sure that source string is null terminated */
+	len = VARSIZE(string) - VARHDRSZ;
+	str = palloc(len + 1);
+	memcpy(str, VARDATA(string), len);
+	*(str + len) = '\0';
+
+	result = pg_do_encoding_conversion(str, len, src, dest);
 	if (result == NULL)
 		elog(ERROR, "Encoding conversion failed");
 
-	retval = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(result)));
-	if (result != (unsigned char *) VARDATA(string))
+	/* build text data type structre. we cannot use textin() here,
+	   since textin assumes that input string encoding is same as
+	   database encoding.  */
+	len = strlen(result) + VARHDRSZ;
+	retval = palloc(len);
+	VARATT_SIZEP(retval) = len;
+	memcpy(VARDATA(retval), result, len - VARHDRSZ);
+	
+	/* free memory allocated by pg_do_encoding_conversion */
+	if (result != str)
 		pfree(result);
+        pfree(str);
 
 	/* free memory if allocated by the toaster */
 	PG_FREE_IF_COPY(string, 0);
@@ -263,6 +279,8 @@ pg_convert2(PG_FUNCTION_ARGS)
 	from_mic_converter dest;
 	unsigned char *result;
 	text	   *retval;
+	unsigned char *str;
+	int len;
 
 	if (src_encoding < 0)
 		elog(ERROR, "Invalid source encoding name %s", src_encoding_name);
@@ -275,14 +293,27 @@ pg_convert2(PG_FUNCTION_ARGS)
 			 src_encoding_name, dest_encoding_name);
 	}
 
-	result = pg_do_encoding_conversion(VARDATA(string), VARSIZE(string) - VARHDRSZ,
-									   src, dest);
+	/* make sure that source string is null terminated */
+	len = VARSIZE(string) - VARHDRSZ;
+	str = palloc(len + 1);
+	memcpy(str, VARDATA(string), len);
+	*(str + len) = '\0';
+
+	result = pg_do_encoding_conversion(str, len, src, dest);
 	if (result == NULL)
 		elog(ERROR, "Encoding conversion failed");
 
-	retval = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(result)));
-	if (result != (unsigned char *) VARDATA(string))
+	/* build text data type structre. we cannot use textin() here,
+	   since textin assumes that input string encoding is same as
+	   database encoding.  */
+	len = strlen(result) + VARHDRSZ;
+	retval = palloc(len);
+	VARATT_SIZEP(retval) = len;
+	memcpy(VARDATA(retval), result, len - VARHDRSZ);
+
+	if (result != str)
 		pfree(result);
+        pfree(str);
 
 	/* free memory if allocated by the toaster */
 	PG_FREE_IF_COPY(string, 0);
-- 
GitLab