Commit cf1f545b authored by Tom Lane's avatar Tom Lane

Don't use abort(3) in libpq's fe-print.c.

Causing a core dump on out-of-memory seems pretty unfriendly,
and surely is far outside the expected behavior of a general-purpose
library.  Just print an error message (as we did already) and return.
These functions unfortunately don't have an error return convention,
but code using them is probably just looking for a quick-n-dirty
print method and wouldn't bother to check anyway.

Although these functions are semi-deprecated, it still seems
appropriate to back-patch this.  In passing, also back-patch
b90e6cef, just to reduce cosmetic differences between the
branches.

Discussion: https://postgr.es/m/3122443.1624735363@sss.pgh.pa.us
parent 203c5aaa
......@@ -37,7 +37,7 @@
#include "libpq-int.h"
static void do_field(const PQprintOpt *po, const PGresult *res,
static bool do_field(const PQprintOpt *po, const PGresult *res,
const int i, const int j, const int fs_len,
char **fields,
const int nFields, const char **fieldNames,
......@@ -80,12 +80,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
unsigned char *fieldNotNum = NULL;
char *border = NULL;
char **fields = NULL;
const char **fieldNames;
const char **fieldNames = NULL;
int fieldMaxLen = 0;
int numFieldName;
int fs_len = strlen(po->fieldSep);
int total_line_length = 0;
int usePipe = 0;
bool usePipe = false;
char *pagerenv;
#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
......@@ -108,20 +108,13 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
#endif
nTups = PQntuples(res);
if (!(fieldNames = (const char **) calloc(nFields, sizeof(char *))))
fieldNames = (const char **) calloc(nFields, sizeof(char *));
fieldNotNum = (unsigned char *) calloc(nFields, 1);
fieldMax = (int *) calloc(nFields, sizeof(int));
if (!fieldNames || !fieldNotNum || !fieldMax)
{
fprintf(stderr, libpq_gettext("out of memory\n"));
abort();
}
if (!(fieldNotNum = (unsigned char *) calloc(nFields, 1)))
{
fprintf(stderr, libpq_gettext("out of memory\n"));
abort();
}
if (!(fieldMax = (int *) calloc(nFields, sizeof(int))))
{
fprintf(stderr, libpq_gettext("out of memory\n"));
abort();
goto exit;
}
for (numFieldName = 0;
po->fieldName && po->fieldName[numFieldName];
......@@ -190,7 +183,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
fout = popen(pagerenv, "w");
if (fout)
{
usePipe = 1;
usePipe = true;
#ifndef WIN32
#ifdef ENABLE_THREAD_SAFETY
if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
......@@ -207,10 +200,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
if (!po->expanded && (po->align || po->html3))
{
if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *))))
fields = (char **) calloc((size_t) nTups + 1,
nFields * sizeof(char *));
if (!fields)
{
fprintf(stderr, libpq_gettext("out of memory\n"));
abort();
goto exit;
}
}
else if (po->header && !po->html3)
......@@ -264,9 +259,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i);
}
for (j = 0; j < nFields; j++)
do_field(po, res, i, j, fs_len, fields, nFields,
fieldNames, fieldNotNum,
fieldMax, fieldMaxLen, fout);
{
if (!do_field(po, res, i, j, fs_len, fields, nFields,
fieldNames, fieldNotNum,
fieldMax, fieldMaxLen, fout))
goto exit;
}
if (po->html3 && po->expanded)
fputs("</table>\n", fout);
}
......@@ -297,18 +295,34 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
for (i = 0; i < nTups; i++)
output_row(fout, po, nFields, fields,
fieldNotNum, fieldMax, border, i);
free(fields);
if (border)
free(border);
}
if (po->header && !po->html3)
fprintf(fout, "(%d row%s)\n\n", PQntuples(res),
(PQntuples(res) == 1) ? "" : "s");
if (po->html3 && !po->expanded)
fputs("</table>\n", fout);
free(fieldMax);
free(fieldNotNum);
free((void *) fieldNames);
exit:
if (fieldMax)
free(fieldMax);
if (fieldNotNum)
free(fieldNotNum);
if (border)
free(border);
if (fields)
{
/* if calloc succeeded, this shouldn't overflow size_t */
size_t numfields = ((size_t) nTups + 1) * (size_t) nFields;
while (numfields-- > 0)
{
if (fields[numfields])
free(fields[numfields]);
}
free(fields);
}
if (fieldNames)
free((void *) fieldNames);
if (usePipe)
{
#ifdef WIN32
......@@ -329,7 +343,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
}
static void
static bool
do_field(const PQprintOpt *po, const PGresult *res,
const int i, const int j, const int fs_len,
char **fields,
......@@ -397,7 +411,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
if (!(fields[i * nFields + j] = (char *) malloc(plen + 1)))
{
fprintf(stderr, libpq_gettext("out of memory\n"));
abort();
return false;
}
strcpy(fields[i * nFields + j], pval);
}
......@@ -440,6 +454,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
}
}
}
return true;
}
......@@ -467,7 +482,7 @@ do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax,
if (!border)
{
fprintf(stderr, libpq_gettext("out of memory\n"));
abort();
return NULL;
}
p = border;
if (po->standard)
......@@ -558,8 +573,6 @@ output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
if (po->standard || field_index + 1 < nFields)
fputs(po->fieldSep, fout);
}
if (p)
free(p);
}
if (po->html3)
fputs("</tr>", fout);
......@@ -609,7 +622,7 @@ PQdisplayTuples(const PGresult *res,
if (!fLength)
{
fprintf(stderr, libpq_gettext("out of memory\n"));
abort();
return;
}
for (j = 0; j < nFields; j++)
......@@ -707,7 +720,7 @@ PQprintTuples(const PGresult *res,
if (!tborder)
{
fprintf(stderr, libpq_gettext("out of memory\n"));
abort();
return;
}
for (i = 0; i < width; i++)
tborder[i] = '-';
......
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