From 1b0f58a9ce29f36733a07c81aa4e05a016fc2a85 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 9 Oct 2008 15:49:04 +0000 Subject: [PATCH] Fix crash in bytea-to-XML mapping when the source value is toasted. Report and fix by Michael McMaster. Some minor code beautification by me, also avoid memory leaks in the special-case paths. --- src/backend/utils/adt/xml.c | 81 +++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 1a05349028..4ef1f97ea7 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.77 2008/09/16 00:49:41 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.78 2008/10/09 15:49:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1568,8 +1568,6 @@ map_sql_value_to_xml_value(Datum value, Oid type) { StringInfoData buf; - initStringInfo(&buf); - if (type_is_array(type)) { ArrayType *array; @@ -1591,6 +1589,8 @@ map_sql_value_to_xml_value(Datum value, Oid type) &elem_values, &elem_nulls, &num_elems); + initStringInfo(&buf); + for (i = 0; i < num_elems; i++) { if (elem_nulls[i]) @@ -1604,6 +1604,8 @@ map_sql_value_to_xml_value(Datum value, Oid type) pfree(elem_values); pfree(elem_nulls); + + return buf.data; } else { @@ -1687,62 +1689,73 @@ map_sql_value_to_xml_value(Datum value, Oid type) return pstrdup(buf); } + +#ifdef USE_LIBXML + case BYTEAOID: + { + bytea *bstr = DatumGetByteaPP(value); + xmlBufferPtr buf; + xmlTextWriterPtr writer; + char *result; + + xml_init(); + + buf = xmlBufferCreate(); + writer = xmlNewTextWriterMemory(buf, 0); + + if (xmlbinary == XMLBINARY_BASE64) + xmlTextWriterWriteBase64(writer, VARDATA_ANY(bstr), + 0, VARSIZE_ANY_EXHDR(bstr)); + else + xmlTextWriterWriteBinHex(writer, VARDATA_ANY(bstr), + 0, VARSIZE_ANY_EXHDR(bstr)); + + xmlFreeTextWriter(writer); + result = pstrdup((const char *) xmlBufferContent(buf)); + xmlBufferFree(buf); + return result; + } +#endif /* USE_LIBXML */ + } + /* + * otherwise, just use the type's native text representation + */ getTypeOutputInfo(type, &typeOut, &isvarlena); str = OidOutputFunctionCall(typeOut, value); + /* ... exactly as-is for XML */ if (type == XMLOID) return str; -#ifdef USE_LIBXML - if (type == BYTEAOID) - { - xmlBufferPtr buf; - xmlTextWriterPtr writer; - char *result; - - xml_init(); - - buf = xmlBufferCreate(); - writer = xmlNewTextWriterMemory(buf, 0); - - if (xmlbinary == XMLBINARY_BASE64) - xmlTextWriterWriteBase64(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ); - else - xmlTextWriterWriteBinHex(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ); - - xmlFreeTextWriter(writer); - result = pstrdup((const char *) xmlBufferContent(buf)); - xmlBufferFree(buf); - return result; - } -#endif /* USE_LIBXML */ + /* otherwise, translate special characters as needed */ + initStringInfo(&buf); - for (p = str; *p; p += pg_mblen(p)) + for (p = str; *p; p++) { switch (*p) { case '&': - appendStringInfo(&buf, "&"); + appendStringInfoString(&buf, "&"); break; case '<': - appendStringInfo(&buf, "<"); + appendStringInfoString(&buf, "<"); break; case '>': - appendStringInfo(&buf, ">"); + appendStringInfoString(&buf, ">"); break; case '\r': - appendStringInfo(&buf, " "); + appendStringInfoString(&buf, " "); break; default: - appendBinaryStringInfo(&buf, p, pg_mblen(p)); + appendStringInfoCharMacro(&buf, *p); break; } } - } - return buf.data; + return buf.data; + } } -- 2.40.0