Skip to content

Commit 6f5d9bc

Browse files
committed
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 b90e6ce, just to reduce cosmetic differences between the branches. Discussion: https://postgr.es/m/3122443.1624735363@sss.pgh.pa.us
1 parent 01697e9 commit 6f5d9bc

File tree

1 file changed

+47
-34
lines changed

1 file changed

+47
-34
lines changed

src/interfaces/libpq/fe-print.c

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
#include "libpq-int.h"
3838

3939

40-
static void do_field(const PQprintOpt *po, const PGresult *res,
40+
static bool do_field(const PQprintOpt *po, const PGresult *res,
4141
const int i, const int j, const int fs_len,
4242
char **fields,
4343
const int nFields, const char **fieldNames,
@@ -80,12 +80,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
8080
unsigned char *fieldNotNum = NULL;
8181
char *border = NULL;
8282
char **fields = NULL;
83-
const char **fieldNames;
83+
const char **fieldNames = NULL;
8484
int fieldMaxLen = 0;
8585
int numFieldName;
8686
int fs_len = strlen(po->fieldSep);
8787
int total_line_length = 0;
88-
int usePipe = 0;
88+
bool usePipe = false;
8989
char *pagerenv;
9090

9191
#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
@@ -108,20 +108,13 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
108108
#endif
109109

110110
nTups = PQntuples(res);
111-
if (!(fieldNames = (const char **) calloc(nFields, sizeof(char *))))
111+
fieldNames = (const char **) calloc(nFields, sizeof(char *));
112+
fieldNotNum = (unsigned char *) calloc(nFields, 1);
113+
fieldMax = (int *) calloc(nFields, sizeof(int));
114+
if (!fieldNames || !fieldNotNum || !fieldMax)
112115
{
113116
fprintf(stderr, libpq_gettext("out of memory\n"));
114-
abort();
115-
}
116-
if (!(fieldNotNum = (unsigned char *) calloc(nFields, 1)))
117-
{
118-
fprintf(stderr, libpq_gettext("out of memory\n"));
119-
abort();
120-
}
121-
if (!(fieldMax = (int *) calloc(nFields, sizeof(int))))
122-
{
123-
fprintf(stderr, libpq_gettext("out of memory\n"));
124-
abort();
117+
goto exit;
125118
}
126119
for (numFieldName = 0;
127120
po->fieldName && po->fieldName[numFieldName];
@@ -190,7 +183,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
190183
fout = popen(pagerenv, "w");
191184
if (fout)
192185
{
193-
usePipe = 1;
186+
usePipe = true;
194187
#ifndef WIN32
195188
#ifdef ENABLE_THREAD_SAFETY
196189
if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
@@ -207,10 +200,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
207200

208201
if (!po->expanded && (po->align || po->html3))
209202
{
210-
if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *))))
203+
fields = (char **) calloc((size_t) nTups + 1,
204+
nFields * sizeof(char *));
205+
if (!fields)
211206
{
212207
fprintf(stderr, libpq_gettext("out of memory\n"));
213-
abort();
208+
goto exit;
214209
}
215210
}
216211
else if (po->header && !po->html3)
@@ -264,9 +259,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
264259
fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i);
265260
}
266261
for (j = 0; j < nFields; j++)
267-
do_field(po, res, i, j, fs_len, fields, nFields,
268-
fieldNames, fieldNotNum,
269-
fieldMax, fieldMaxLen, fout);
262+
{
263+
if (!do_field(po, res, i, j, fs_len, fields, nFields,
264+
fieldNames, fieldNotNum,
265+
fieldMax, fieldMaxLen, fout))
266+
goto exit;
267+
}
270268
if (po->html3 && po->expanded)
271269
fputs("</table>\n", fout);
272270
}
@@ -297,18 +295,34 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
297295
for (i = 0; i < nTups; i++)
298296
output_row(fout, po, nFields, fields,
299297
fieldNotNum, fieldMax, border, i);
300-
free(fields);
301-
if (border)
302-
free(border);
303298
}
304299
if (po->header && !po->html3)
305300
fprintf(fout, "(%d row%s)\n\n", PQntuples(res),
306301
(PQntuples(res) == 1) ? "" : "s");
307302
if (po->html3 && !po->expanded)
308303
fputs("</table>\n", fout);
309-
free(fieldMax);
310-
free(fieldNotNum);
311-
free((void *) fieldNames);
304+
305+
exit:
306+
if (fieldMax)
307+
free(fieldMax);
308+
if (fieldNotNum)
309+
free(fieldNotNum);
310+
if (border)
311+
free(border);
312+
if (fields)
313+
{
314+
/* if calloc succeeded, this shouldn't overflow size_t */
315+
size_t numfields = ((size_t) nTups + 1) * (size_t) nFields;
316+
317+
while (numfields-- > 0)
318+
{
319+
if (fields[numfields])
320+
free(fields[numfields]);
321+
}
322+
free(fields);
323+
}
324+
if (fieldNames)
325+
free((void *) fieldNames);
312326
if (usePipe)
313327
{
314328
#ifdef WIN32
@@ -329,7 +343,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
329343
}
330344

331345

332-
static void
346+
static bool
333347
do_field(const PQprintOpt *po, const PGresult *res,
334348
const int i, const int j, const int fs_len,
335349
char **fields,
@@ -397,7 +411,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
397411
if (!(fields[i * nFields + j] = (char *) malloc(plen + 1)))
398412
{
399413
fprintf(stderr, libpq_gettext("out of memory\n"));
400-
abort();
414+
return false;
401415
}
402416
strcpy(fields[i * nFields + j], pval);
403417
}
@@ -440,6 +454,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
440454
}
441455
}
442456
}
457+
return true;
443458
}
444459

445460

@@ -467,7 +482,7 @@ do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax,
467482
if (!border)
468483
{
469484
fprintf(stderr, libpq_gettext("out of memory\n"));
470-
abort();
485+
return NULL;
471486
}
472487
p = border;
473488
if (po->standard)
@@ -558,8 +573,6 @@ output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
558573
if (po->standard || field_index + 1 < nFields)
559574
fputs(po->fieldSep, fout);
560575
}
561-
if (p)
562-
free(p);
563576
}
564577
if (po->html3)
565578
fputs("</tr>", fout);
@@ -609,7 +622,7 @@ PQdisplayTuples(const PGresult *res,
609622
if (!fLength)
610623
{
611624
fprintf(stderr, libpq_gettext("out of memory\n"));
612-
abort();
625+
return;
613626
}
614627

615628
for (j = 0; j < nFields; j++)
@@ -707,7 +720,7 @@ PQprintTuples(const PGresult *res,
707720
if (!tborder)
708721
{
709722
fprintf(stderr, libpq_gettext("out of memory\n"));
710-
abort();
723+
return;
711724
}
712725
for (i = 0; i < width; i++)
713726
tborder[i] = '-';

0 commit comments

Comments
 (0)