Commit f1f59786 authored by Tom Lane's avatar Tom Lane

Fix possible buffer overrun in \d command: substr(..., 128) produces

a result of at most 128 chars, but that could be more than 128 bytes.
Also ensure we don't try to pfree uninitialized pointers during error
cleanup.
parent e2ad5816
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000-2002 by PostgreSQL Global Development Group * Copyright 2000-2002 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.72 2002/12/12 21:02:24 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.73 2002/12/21 01:07:07 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "describe.h" #include "describe.h"
...@@ -44,6 +44,16 @@ xmalloc(size_t size) ...@@ -44,6 +44,16 @@ xmalloc(size_t size)
return tmp; return tmp;
} }
static void *
xmalloczero(size_t size)
{
void *tmp;
tmp = xmalloc(size);
memset(tmp, 0, size);
return tmp;
}
/*---------------- /*----------------
* Handlers for various slash commands displaying some sort of list * Handlers for various slash commands displaying some sort of list
...@@ -635,7 +645,9 @@ describeOneTableDetails(const char *schemaname, ...@@ -635,7 +645,9 @@ describeOneTableDetails(const char *schemaname,
char **footers = NULL; char **footers = NULL;
char **ptr; char **ptr;
PQExpBufferData title; PQExpBufferData title;
unsigned int cols = 0; PQExpBufferData tmpbuf;
int cols = 0;
int numrows = 0;
struct struct
{ {
bool hasindex; bool hasindex;
...@@ -644,12 +656,14 @@ describeOneTableDetails(const char *schemaname, ...@@ -644,12 +656,14 @@ describeOneTableDetails(const char *schemaname,
int16 triggers; int16 triggers;
bool hasrules; bool hasrules;
} tableinfo; } tableinfo;
bool show_modifiers = false;
bool retval; bool retval;
retval = false; retval = false;
initPQExpBuffer(&buf); initPQExpBuffer(&buf);
initPQExpBuffer(&title); initPQExpBuffer(&title);
initPQExpBuffer(&tmpbuf);
/* Get general table info */ /* Get general table info */
printfPQExpBuffer(&buf, printfPQExpBuffer(&buf,
...@@ -683,6 +697,7 @@ describeOneTableDetails(const char *schemaname, ...@@ -683,6 +697,7 @@ describeOneTableDetails(const char *schemaname,
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v') if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
{ {
show_modifiers = true;
cols++; cols++;
headers[cols - 1] = _("Modifiers"); headers[cols - 1] = _("Modifiers");
} }
...@@ -715,6 +730,7 @@ describeOneTableDetails(const char *schemaname, ...@@ -715,6 +730,7 @@ describeOneTableDetails(const char *schemaname,
res = PSQLexec(buf.data, false); res = PSQLexec(buf.data, false);
if (!res) if (!res)
goto error_return; goto error_return;
numrows = PQntuples(res);
/* Check if table is a view */ /* Check if table is a view */
if (tableinfo.relkind == 'v') if (tableinfo.relkind == 'v')
...@@ -733,10 +749,10 @@ describeOneTableDetails(const char *schemaname, ...@@ -733,10 +749,10 @@ describeOneTableDetails(const char *schemaname,
} }
/* Generate table cells to be printed */ /* Generate table cells to be printed */
cells = xmalloc((PQntuples(res) * cols + 1) * sizeof(*cells)); /* note: initialize all cells[] to NULL in case of error exit */
cells[PQntuples(res) * cols] = NULL; /* end of list */ cells = xmalloczero((numrows * cols + 1) * sizeof(*cells));
for (i = 0; i < PQntuples(res); i++) for (i = 0; i < numrows; i++)
{ {
/* Name */ /* Name */
cells[i * cols + 0] = PQgetvalue(res, i, 0); /* don't free this cells[i * cols + 0] = PQgetvalue(res, i, 0); /* don't free this
...@@ -747,12 +763,11 @@ describeOneTableDetails(const char *schemaname, ...@@ -747,12 +763,11 @@ describeOneTableDetails(const char *schemaname,
/* Extra: not null and default */ /* Extra: not null and default */
/* (I'm cutting off the 'default' string at 128) */ /* (I'm cutting off the 'default' string at 128) */
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v') if (show_modifiers)
{ {
cells[i * cols + 2] = xmalloc(128 + 128); resetPQExpBuffer(&tmpbuf);
cells[i * cols + 2][0] = '\0';
if (strcmp(PQgetvalue(res, i, 2), "t") == 0) if (strcmp(PQgetvalue(res, i, 2), "t") == 0)
strcat(cells[i * cols + 2], "not null"); appendPQExpBufferStr(&tmpbuf, "not null");
/* handle "default" here */ /* handle "default" here */
if (strcmp(PQgetvalue(res, i, 3), "t") == 0) if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
...@@ -766,13 +781,16 @@ describeOneTableDetails(const char *schemaname, ...@@ -766,13 +781,16 @@ describeOneTableDetails(const char *schemaname,
result = PSQLexec(buf.data, false); result = PSQLexec(buf.data, false);
if (cells[i * cols + 2][0]) if (tmpbuf.len > 0)
strcat(cells[i * cols + 2], " "); appendPQExpBufferStr(&tmpbuf, " ");
strcat(cells[i * cols + 2], "default ");
strcat(cells[i * cols + 2], result ? PQgetvalue(result, 0, 0) : "?"); appendPQExpBuffer(&tmpbuf, "default %s",
result ? PQgetvalue(result, 0, 0) : "?");
PQclear(result); PQclear(result);
} }
cells[i * cols + 2] = xstrdup(tmpbuf.data);
} }
/* Description */ /* Description */
...@@ -841,15 +859,12 @@ describeOneTableDetails(const char *schemaname, ...@@ -841,15 +859,12 @@ describeOneTableDetails(const char *schemaname,
} }
else else
{ {
PQExpBufferData tmpbuf;
char *indisunique = PQgetvalue(result, 0, 0); char *indisunique = PQgetvalue(result, 0, 0);
char *indisprimary = PQgetvalue(result, 0, 1); char *indisprimary = PQgetvalue(result, 0, 1);
char *indamname = PQgetvalue(result, 0, 2); char *indamname = PQgetvalue(result, 0, 2);
char *indtable = PQgetvalue(result, 0, 3); char *indtable = PQgetvalue(result, 0, 3);
char *indpred = PQgetvalue(result, 0, 4); char *indpred = PQgetvalue(result, 0, 4);
initPQExpBuffer(&tmpbuf);
if (strcmp(indisprimary, "t") == 0) if (strcmp(indisprimary, "t") == 0)
printfPQExpBuffer(&tmpbuf, _("primary key, ")); printfPQExpBuffer(&tmpbuf, _("primary key, "));
else if (strcmp(indisunique, "t") == 0) else if (strcmp(indisunique, "t") == 0)
...@@ -865,10 +880,9 @@ describeOneTableDetails(const char *schemaname, ...@@ -865,10 +880,9 @@ describeOneTableDetails(const char *schemaname,
if (strlen(indpred)) if (strlen(indpred))
appendPQExpBuffer(&tmpbuf, ", predicate %s", indpred); appendPQExpBuffer(&tmpbuf, ", predicate %s", indpred);
footers = xmalloc(2 * sizeof(*footers)); footers = xmalloczero(2 * sizeof(*footers));
footers[0] = xstrdup(tmpbuf.data); footers[0] = xstrdup(tmpbuf.data);
footers[1] = NULL; footers[1] = NULL;
termPQExpBuffer(&tmpbuf);
} }
PQclear(result); PQclear(result);
...@@ -895,7 +909,7 @@ describeOneTableDetails(const char *schemaname, ...@@ -895,7 +909,7 @@ describeOneTableDetails(const char *schemaname,
} }
/* Footer information about a view */ /* Footer information about a view */
footers = xmalloc((rule_count + 2) * sizeof(*footers)); footers = xmalloczero((rule_count + 2) * sizeof(*footers));
footers[count_footers] = xmalloc(64 + strlen(view_def)); footers[count_footers] = xmalloc(64 + strlen(view_def));
snprintf(footers[count_footers], 64 + strlen(view_def), snprintf(footers[count_footers], 64 + strlen(view_def),
_("View definition: %s"), view_def); _("View definition: %s"), view_def);
...@@ -1018,7 +1032,7 @@ describeOneTableDetails(const char *schemaname, ...@@ -1018,7 +1032,7 @@ describeOneTableDetails(const char *schemaname,
foreignkey_count = PQntuples(result5); foreignkey_count = PQntuples(result5);
} }
footers = xmalloc((index_count + check_count + rule_count + trigger_count + foreignkey_count + 1) footers = xmalloczero((index_count + check_count + rule_count + trigger_count + foreignkey_count + 1)
* sizeof(*footers)); * sizeof(*footers));
/* print indexes */ /* print indexes */
...@@ -1148,12 +1162,15 @@ error_return: ...@@ -1148,12 +1162,15 @@ error_return:
/* clean up */ /* clean up */
termPQExpBuffer(&buf); termPQExpBuffer(&buf);
termPQExpBuffer(&title); termPQExpBuffer(&title);
termPQExpBuffer(&tmpbuf);
if (cells) if (cells)
{ {
for (i = 0; i < PQntuples(res); i++) for (i = 0; i < numrows; i++)
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v') {
if (show_modifiers)
free(cells[i * cols + 2]); free(cells[i * cols + 2]);
}
free(cells); free(cells);
} }
......
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