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
b90e6cef1, just to reduce cosmetic differences between the
branches.

Discussion: https://postgr.es/m/3122443.1624735363@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2021-06-28 14:17:42 -04:00
parent 203c5aaaba
commit cf1f545bf2
1 changed files with 47 additions and 34 deletions

View File

@ -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] = '-';