aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/xml.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-10-09 15:49:04 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-10-09 15:49:04 +0000
commit1b0f58a9ce29f36733a07c81aa4e05a016fc2a85 (patch)
treef2f97f6f4c13726a582e49f434276cee31f4f4bf /src/backend/utils/adt/xml.c
parentdb31addaae1664b2e9028421d8a545f2c0ef2746 (diff)
downloadpostgresql-1b0f58a9ce29f36733a07c81aa4e05a016fc2a85.tar.gz
postgresql-1b0f58a9ce29f36733a07c81aa4e05a016fc2a85.zip
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.
Diffstat (limited to 'src/backend/utils/adt/xml.c')
-rw-r--r--src/backend/utils/adt/xml.c81
1 files changed, 47 insertions, 34 deletions
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 1a053490289..4ef1f97ea78 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, "&amp;");
+ appendStringInfoString(&buf, "&amp;");
break;
case '<':
- appendStringInfo(&buf, "&lt;");
+ appendStringInfoString(&buf, "&lt;");
break;
case '>':
- appendStringInfo(&buf, "&gt;");
+ appendStringInfoString(&buf, "&gt;");
break;
case '\r':
- appendStringInfo(&buf, "&#x0d;");
+ appendStringInfoString(&buf, "&#x0d;");
break;
default:
- appendBinaryStringInfo(&buf, p, pg_mblen(p));
+ appendStringInfoCharMacro(&buf, *p);
break;
}
}
- }
- return buf.data;
+ return buf.data;
+ }
}