diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 5cb761773d..7cfca13fea 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.86 2009/04/08 21:51:38 petere Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.87 2009/05/12 20:17:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -236,8 +236,6 @@ xml_out_internal(xmltype *x, pg_enc target_encoding) } appendStringInfoString(&buf, str + len); - if (version) - xmlFree(version); pfree(str); return buf.data; @@ -455,7 +453,7 @@ xmlconcat(List *args) if (!version) global_version_no_value = true; else if (!global_version) - global_version = xmlStrdup(version); + global_version = version; else if (xmlStrcmp(version, global_version) != 0) global_version_no_value = true; @@ -918,6 +916,24 @@ xml_init(void) || xmlIsCombiningQ(c) \ || xmlIsExtender_ch(c)) +/* pnstrdup, but deal with xmlChar not char; len is measured in xmlChars */ +static xmlChar * +xml_pnstrdup(const xmlChar *str, size_t len) +{ + xmlChar *result; + + result = (xmlChar *) palloc((len + 1) * sizeof(xmlChar)); + memcpy(result, str, len * sizeof(xmlChar)); + result[len] = 0; + return result; +} + +/* + * str is the null-terminated input string. Remaining arguments are + * output arguments; each can be NULL if value is not wanted. + * version and encoding are returned as locally-palloc'd strings. + * Result is 0 if OK, an error code if not. + */ static int parse_xml_decl(const xmlChar * str, size_t *lenp, xmlChar ** version, xmlChar ** encoding, int *standalone) @@ -930,6 +946,7 @@ parse_xml_decl(const xmlChar * str, size_t *lenp, xml_init(); + /* Initialize output arguments to "not present" */ if (version) *version = NULL; if (encoding) @@ -971,7 +988,7 @@ parse_xml_decl(const xmlChar * str, size_t *lenp, return XML_ERR_VERSION_MISSING; if (version) - *version = xmlStrndup(p + 1, q - p - 1); + *version = xml_pnstrdup(p + 1, q - p - 1); p = q + 1; } else @@ -999,7 +1016,7 @@ parse_xml_decl(const xmlChar * str, size_t *lenp, return XML_ERR_MISSING_ENCODING; if (encoding) - *encoding = xmlStrndup(p + 1, q - p - 1); + *encoding = xml_pnstrdup(p + 1, q - p - 1); p = q + 1; } else @@ -1172,8 +1189,6 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, xmlChar *version = NULL; int standalone = -1; - doc = xmlNewDoc(NULL); - res_code = parse_xml_decl(utf8string, &count, &version, NULL, &standalone); if (res_code != 0) @@ -1181,15 +1196,16 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, "invalid XML content: invalid XML declaration", res_code); + doc = xmlNewDoc(version); + Assert(doc->encoding == NULL); + doc->encoding = xmlStrdup((const xmlChar *) "UTF-8"); + doc->standalone = standalone; + res_code = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, utf8string + count, NULL); if (res_code != 0) xml_ereport(ERROR, ERRCODE_INVALID_XML_CONTENT, "invalid XML content"); - - doc->version = xmlStrdup(version); - doc->encoding = xmlStrdup((xmlChar *) "UTF-8"); - doc->standalone = standalone; } xmlFreeParserCtxt(ctxt);