Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 709e461

Browse files
committed
Fix EXPLAIN so that it doesn't emit invalid XML in corner cases.
With track_io_timing = on, EXPLAIN (ANALYZE, BUFFERS) will emit fields named like "I/O Read Time". The slash makes that invalid as an XML element name, so that adding FORMAT XML would produce invalid XML. We already have code in there to translate spaces to dashes, so let's generalize that to convert anything that isn't a valid XML name character, viz letters, digits, hyphens, underscores, and periods. We could just reject slashes, which would run a bit faster. But the fact that this went unnoticed for so long doesn't give me a warm feeling that we'd notice the next creative violation, so let's make it a permanent fix. Reported by Markus Winand, though this isn't his initial patch proposal. Back-patch to 9.2 where track_io_timing was added. The problem is only latent in 9.1, so I don't feel a need to fix it there. Discussion: <E0BF6A45-68E8-45E6-918F-741FB332C6BB@winand.at>
1 parent 5e21b68 commit 709e461

File tree

1 file changed

+5
-3
lines changed

1 file changed

+5
-3
lines changed

src/backend/commands/explain.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3312,21 +3312,23 @@ ExplainSeparatePlans(ExplainState *es)
33123312
* Optionally, OR in X_NOWHITESPACE to suppress the whitespace we'd normally
33133313
* add.
33143314
*
3315-
* XML tag names can't contain white space, so we replace any spaces in
3316-
* "tagname" with dashes.
3315+
* XML restricts tag names more than our other output formats, eg they can't
3316+
* contain white space or slashes. Replace invalid characters with dashes,
3317+
* so that for example "I/O Read Time" becomes "I-O-Read-Time".
33173318
*/
33183319
static void
33193320
ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
33203321
{
33213322
const char *s;
3323+
const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";
33223324

33233325
if ((flags & X_NOWHITESPACE) == 0)
33243326
appendStringInfoSpaces(es->str, 2 * es->indent);
33253327
appendStringInfoCharMacro(es->str, '<');
33263328
if ((flags & X_CLOSING) != 0)
33273329
appendStringInfoCharMacro(es->str, '/');
33283330
for (s = tagname; *s; s++)
3329-
appendStringInfoCharMacro(es->str, (*s == ' ') ? '-' : *s);
3331+
appendStringInfoChar(es->str, strchr(valid, *s) ? *s : '-');
33303332
if ((flags & X_CLOSE_IMMEDIATE) != 0)
33313333
appendStringInfoString(es->str, " /");
33323334
appendStringInfoCharMacro(es->str, '>');

0 commit comments

Comments
 (0)