Commit 1b0f58a9 authored by Tom Lane's avatar Tom Lane

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.
parent db31adda
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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) ...@@ -1568,8 +1568,6 @@ map_sql_value_to_xml_value(Datum value, Oid type)
{ {
StringInfoData buf; StringInfoData buf;
initStringInfo(&buf);
if (type_is_array(type)) if (type_is_array(type))
{ {
ArrayType *array; ArrayType *array;
...@@ -1591,6 +1589,8 @@ map_sql_value_to_xml_value(Datum value, Oid type) ...@@ -1591,6 +1589,8 @@ map_sql_value_to_xml_value(Datum value, Oid type)
&elem_values, &elem_nulls, &elem_values, &elem_nulls,
&num_elems); &num_elems);
initStringInfo(&buf);
for (i = 0; i < num_elems; i++) for (i = 0; i < num_elems; i++)
{ {
if (elem_nulls[i]) if (elem_nulls[i])
...@@ -1604,6 +1604,8 @@ map_sql_value_to_xml_value(Datum value, Oid type) ...@@ -1604,6 +1604,8 @@ map_sql_value_to_xml_value(Datum value, Oid type)
pfree(elem_values); pfree(elem_values);
pfree(elem_nulls); pfree(elem_nulls);
return buf.data;
} }
else else
{ {
...@@ -1687,62 +1689,73 @@ map_sql_value_to_xml_value(Datum value, Oid type) ...@@ -1687,62 +1689,73 @@ map_sql_value_to_xml_value(Datum value, Oid type)
return pstrdup(buf); 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); getTypeOutputInfo(type, &typeOut, &isvarlena);
str = OidOutputFunctionCall(typeOut, value); str = OidOutputFunctionCall(typeOut, value);
/* ... exactly as-is for XML */
if (type == XMLOID) if (type == XMLOID)
return str; return str;
#ifdef USE_LIBXML /* otherwise, translate special characters as needed */
if (type == BYTEAOID) initStringInfo(&buf);
{
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 */
for (p = str; *p; p += pg_mblen(p)) for (p = str; *p; p++)
{ {
switch (*p) switch (*p)
{ {
case '&': case '&':
appendStringInfo(&buf, "&amp;"); appendStringInfoString(&buf, "&amp;");
break; break;
case '<': case '<':
appendStringInfo(&buf, "&lt;"); appendStringInfoString(&buf, "&lt;");
break; break;
case '>': case '>':
appendStringInfo(&buf, "&gt;"); appendStringInfoString(&buf, "&gt;");
break; break;
case '\r': case '\r':
appendStringInfo(&buf, "&#x0d;"); appendStringInfoString(&buf, "&#x0d;");
break; break;
default: default:
appendBinaryStringInfo(&buf, p, pg_mblen(p)); appendStringInfoCharMacro(&buf, *p);
break; break;
} }
} }
}
return buf.data; return buf.data;
}
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment