Skip to content

Commit 5590d5f

Browse files
committed
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
1 parent 09a2b4f commit 5590d5f

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

src/backend/utils/mb/mbutils.c

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* client encoding and server internal encoding.
44
* (currently mule internal code (mic) is used)
55
* Tatsuo Ishii
6-
* $Id: mbutils.c,v 1.25 2001/10/25 05:49:51 momjian Exp $
6+
* $Id: mbutils.c,v 1.26 2001/11/19 06:48:39 ishii Exp $
77
*/
88
#include "postgres.h"
99

@@ -220,6 +220,8 @@ pg_convert(PG_FUNCTION_ARGS)
220220
from_mic_converter dest;
221221
unsigned char *result;
222222
text *retval;
223+
unsigned char *str;
224+
int len;
223225

224226
if (encoding < 0)
225227
elog(ERROR, "Invalid encoding name %s", NameStr(*s));
@@ -231,14 +233,28 @@ pg_convert(PG_FUNCTION_ARGS)
231233
elog(ERROR, "Conversion from %s to %s is not possible", NameStr(*s), encoding_name);
232234
}
233235

234-
result = pg_do_encoding_conversion(VARDATA(string), VARSIZE(string) - VARHDRSZ,
235-
src, dest);
236+
/* make sure that source string is null terminated */
237+
len = VARSIZE(string) - VARHDRSZ;
238+
str = palloc(len + 1);
239+
memcpy(str, VARDATA(string), len);
240+
*(str + len) = '\0';
241+
242+
result = pg_do_encoding_conversion(str, len, src, dest);
236243
if (result == NULL)
237244
elog(ERROR, "Encoding conversion failed");
238245

239-
retval = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(result)));
240-
if (result != (unsigned char *) VARDATA(string))
246+
/* build text data type structre. we cannot use textin() here,
247+
since textin assumes that input string encoding is same as
248+
database encoding. */
249+
len = strlen(result) + VARHDRSZ;
250+
retval = palloc(len);
251+
VARATT_SIZEP(retval) = len;
252+
memcpy(VARDATA(retval), result, len - VARHDRSZ);
253+
254+
/* free memory allocated by pg_do_encoding_conversion */
255+
if (result != str)
241256
pfree(result);
257+
pfree(str);
242258

243259
/* free memory if allocated by the toaster */
244260
PG_FREE_IF_COPY(string, 0);
@@ -263,6 +279,8 @@ pg_convert2(PG_FUNCTION_ARGS)
263279
from_mic_converter dest;
264280
unsigned char *result;
265281
text *retval;
282+
unsigned char *str;
283+
int len;
266284

267285
if (src_encoding < 0)
268286
elog(ERROR, "Invalid source encoding name %s", src_encoding_name);
@@ -275,14 +293,27 @@ pg_convert2(PG_FUNCTION_ARGS)
275293
src_encoding_name, dest_encoding_name);
276294
}
277295

278-
result = pg_do_encoding_conversion(VARDATA(string), VARSIZE(string) - VARHDRSZ,
279-
src, dest);
296+
/* make sure that source string is null terminated */
297+
len = VARSIZE(string) - VARHDRSZ;
298+
str = palloc(len + 1);
299+
memcpy(str, VARDATA(string), len);
300+
*(str + len) = '\0';
301+
302+
result = pg_do_encoding_conversion(str, len, src, dest);
280303
if (result == NULL)
281304
elog(ERROR, "Encoding conversion failed");
282305

283-
retval = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(result)));
284-
if (result != (unsigned char *) VARDATA(string))
306+
/* build text data type structre. we cannot use textin() here,
307+
since textin assumes that input string encoding is same as
308+
database encoding. */
309+
len = strlen(result) + VARHDRSZ;
310+
retval = palloc(len);
311+
VARATT_SIZEP(retval) = len;
312+
memcpy(VARDATA(retval), result, len - VARHDRSZ);
313+
314+
if (result != str)
285315
pfree(result);
316+
pfree(str);
286317

287318
/* free memory if allocated by the toaster */
288319
PG_FREE_IF_COPY(string, 0);

0 commit comments

Comments
 (0)