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

Commit 39792e5

Browse files
committed
EXPLAIN VERBOSE had a very high probability of triggering
a backend core dump, because it was concatenating a potentially long string onto another string that didn't necessarily have enough room. Shame, shame.
1 parent 8f5ff4c commit 39792e5

File tree

1 file changed

+33
-20
lines changed

1 file changed

+33
-20
lines changed

src/backend/commands/explain.c

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.25 1998/10/21 16:21:20 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.26 1998/11/08 19:38:34 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -38,6 +38,7 @@ typedef struct ExplainState
3838
} ExplainState;
3939

4040
static char *Explain_PlanToString(Plan *plan, ExplainState *es);
41+
static void printLongNotice(const char * header, const char * message);
4142
static void ExplainOneQuery(Query *query, bool verbose, CommandDest dest);
4243

4344

@@ -87,11 +88,9 @@ ExplainQuery(Query *query, bool verbose, CommandDest dest)
8788
static void
8889
ExplainOneQuery(Query *query, bool verbose, CommandDest dest)
8990
{
90-
char *s = NULL,
91-
*s2;
91+
char *s;
9292
Plan *plan;
9393
ExplainState *es;
94-
int len;
9594

9695
/* plan the queries (XXX we've ignored rewrite!!) */
9796
plan = planner(query);
@@ -111,30 +110,25 @@ ExplainOneQuery(Query *query, bool verbose, CommandDest dest)
111110
es->rtable = query->rtable;
112111

113112
if (es->printNodes)
113+
{
114114
s = nodeToString(plan);
115+
if (s)
116+
{
117+
printLongNotice("QUERY DUMP:\n\n", s);
118+
pfree(s);
119+
}
120+
}
115121

116122
if (es->printCost)
117123
{
118-
s2 = Explain_PlanToString(plan, es);
119-
if (s == NULL)
120-
s = s2;
121-
else
124+
s = Explain_PlanToString(plan, es);
125+
if (s)
122126
{
123-
strcat(s, "\n\n");
124-
strcat(s, s2);
127+
printLongNotice("QUERY PLAN:\n\n", s);
128+
pfree(s);
125129
}
126130
}
127131

128-
/* output the plan */
129-
len = strlen(s);
130-
elog(NOTICE, "QUERY PLAN:\n\n%.*s", ELOG_MAXLEN - 64, s);
131-
len -= ELOG_MAXLEN - 64;
132-
while (len > 0)
133-
{
134-
s += ELOG_MAXLEN - 64;
135-
elog(NOTICE, "%.*s", ELOG_MAXLEN - 64, s);
136-
len -= ELOG_MAXLEN - 64;
137-
}
138132
if (es->printNodes)
139133
pprint(plan); /* display in postmaster log file */
140134

@@ -361,3 +355,22 @@ Explain_PlanToString(Plan *plan, ExplainState *es)
361355

362356
return s;
363357
}
358+
359+
/*
360+
* Print a message that might exceed the size of the elog message buffer.
361+
* This is a crock ... there shouldn't be an upper limit to what you can elog().
362+
*/
363+
static void
364+
printLongNotice(const char * header, const char * message)
365+
{
366+
int len = strlen(message);
367+
368+
elog(NOTICE, "%.20s%.*s", header, ELOG_MAXLEN - 64, message);
369+
len -= ELOG_MAXLEN - 64;
370+
while (len > 0)
371+
{
372+
message += ELOG_MAXLEN - 64;
373+
elog(NOTICE, "%.*s", ELOG_MAXLEN - 64, message);
374+
len -= ELOG_MAXLEN - 64;
375+
}
376+
}

0 commit comments

Comments
 (0)