mirror of
https://github.com/postgres/postgres.git
synced 2025-05-08 07:21:33 +03:00
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.
This commit is contained in:
parent
db31addaae
commit
1b0f58a9ce
@ -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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
&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)
|
|||||||
|
|
||||||
pfree(elem_values);
|
pfree(elem_values);
|
||||||
pfree(elem_nulls);
|
pfree(elem_nulls);
|
||||||
|
|
||||||
|
return buf.data;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1687,17 +1689,11 @@ map_sql_value_to_xml_value(Datum value, Oid type)
|
|||||||
|
|
||||||
return pstrdup(buf);
|
return pstrdup(buf);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
getTypeOutputInfo(type, &typeOut, &isvarlena);
|
|
||||||
str = OidOutputFunctionCall(typeOut, value);
|
|
||||||
|
|
||||||
if (type == XMLOID)
|
|
||||||
return str;
|
|
||||||
|
|
||||||
#ifdef USE_LIBXML
|
#ifdef USE_LIBXML
|
||||||
if (type == BYTEAOID)
|
case BYTEAOID:
|
||||||
{
|
{
|
||||||
|
bytea *bstr = DatumGetByteaPP(value);
|
||||||
xmlBufferPtr buf;
|
xmlBufferPtr buf;
|
||||||
xmlTextWriterPtr writer;
|
xmlTextWriterPtr writer;
|
||||||
char *result;
|
char *result;
|
||||||
@ -1708,9 +1704,11 @@ map_sql_value_to_xml_value(Datum value, Oid type)
|
|||||||
writer = xmlNewTextWriterMemory(buf, 0);
|
writer = xmlNewTextWriterMemory(buf, 0);
|
||||||
|
|
||||||
if (xmlbinary == XMLBINARY_BASE64)
|
if (xmlbinary == XMLBINARY_BASE64)
|
||||||
xmlTextWriterWriteBase64(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ);
|
xmlTextWriterWriteBase64(writer, VARDATA_ANY(bstr),
|
||||||
|
0, VARSIZE_ANY_EXHDR(bstr));
|
||||||
else
|
else
|
||||||
xmlTextWriterWriteBinHex(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ);
|
xmlTextWriterWriteBinHex(writer, VARDATA_ANY(bstr),
|
||||||
|
0, VARSIZE_ANY_EXHDR(bstr));
|
||||||
|
|
||||||
xmlFreeTextWriter(writer);
|
xmlFreeTextWriter(writer);
|
||||||
result = pstrdup((const char *) xmlBufferContent(buf));
|
result = pstrdup((const char *) xmlBufferContent(buf));
|
||||||
@ -1719,31 +1717,46 @@ map_sql_value_to_xml_value(Datum value, Oid type)
|
|||||||
}
|
}
|
||||||
#endif /* USE_LIBXML */
|
#endif /* USE_LIBXML */
|
||||||
|
|
||||||
for (p = str; *p; p += pg_mblen(p))
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/* otherwise, translate special characters as needed */
|
||||||
|
initStringInfo(&buf);
|
||||||
|
|
||||||
|
for (p = str; *p; p++)
|
||||||
{
|
{
|
||||||
switch (*p)
|
switch (*p)
|
||||||
{
|
{
|
||||||
case '&':
|
case '&':
|
||||||
appendStringInfo(&buf, "&");
|
appendStringInfoString(&buf, "&");
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
appendStringInfo(&buf, "<");
|
appendStringInfoString(&buf, "<");
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
appendStringInfo(&buf, ">");
|
appendStringInfoString(&buf, ">");
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
appendStringInfo(&buf, "
");
|
appendStringInfoString(&buf, "
");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
appendBinaryStringInfo(&buf, p, pg_mblen(p));
|
appendStringInfoCharMacro(&buf, *p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return buf.data;
|
return buf.data;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
Loading…
x
Reference in New Issue
Block a user