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

Commit 240d56f

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 3fd3347 commit 240d56f

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
@@ -38,7 +38,7 @@
3838

3939
#define PQmblenBounded(s, e) strnlen(s, PQmblen(s, e))
4040

41-
static void do_field(const PQprintOpt *po, const PGresult *res,
41+
static bool do_field(const PQprintOpt *po, const PGresult *res,
4242
const int i, const int j, const int fs_len,
4343
char **fields,
4444
const int nFields, const char **fieldNames,
@@ -81,12 +81,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
8181
unsigned char *fieldNotNum = NULL;
8282
char *border = NULL;
8383
char **fields = NULL;
84-
const char **fieldNames;
84+
const char **fieldNames = NULL;
8585
int fieldMaxLen = 0;
8686
int numFieldName;
8787
int fs_len = strlen(po->fieldSep);
8888
int total_line_length = 0;
89-
int usePipe = 0;
89+
bool usePipe = false;
9090
char *pagerenv;
9191

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

111111
nTups = PQntuples(res);
112-
if (!(fieldNames = (const char **) calloc(nFields, sizeof(char *))))
112+
fieldNames = (const char **) calloc(nFields, sizeof(char *));
113+
fieldNotNum = (unsigned char *) calloc(nFields, 1);
114+
fieldMax = (int *) calloc(nFields, sizeof(int));
115+
if (!fieldNames || !fieldNotNum || !fieldMax)
113116
{
114117
fprintf(stderr, libpq_gettext("out of memory\n"));
115-
abort();
116-
}
117-
if (!(fieldNotNum = (unsigned char *) calloc(nFields, 1)))
118-
{
119-
fprintf(stderr, libpq_gettext("out of memory\n"));
120-
abort();
121-
}
122-
if (!(fieldMax = (int *) calloc(nFields, sizeof(int))))
123-
{
124-
fprintf(stderr, libpq_gettext("out of memory\n"));
125-
abort();
118+
goto exit;
126119
}
127120
for (numFieldName = 0;
128121
po->fieldName && po->fieldName[numFieldName];
@@ -191,7 +184,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
191184
fout = popen(pagerenv, "w");
192185
if (fout)
193186
{
194-
usePipe = 1;
187+
usePipe = true;
195188
#ifndef WIN32
196189
#ifdef ENABLE_THREAD_SAFETY
197190
if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
@@ -208,10 +201,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
208201

209202
if (!po->expanded && (po->align || po->html3))
210203
{
211-
if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *))))
204+
fields = (char **) calloc((size_t) nTups + 1,
205+
nFields * sizeof(char *));
206+
if (!fields)
212207
{
213208
fprintf(stderr, libpq_gettext("out of memory\n"));
214-
abort();
209+
goto exit;
215210
}
216211
}
217212
else if (po->header && !po->html3)
@@ -265,9 +260,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
265260
fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i);
266261
}
267262
for (j = 0; j < nFields; j++)
268-
do_field(po, res, i, j, fs_len, fields, nFields,
269-
fieldNames, fieldNotNum,
270-
fieldMax, fieldMaxLen, fout);
263+
{
264+
if (!do_field(po, res, i, j, fs_len, fields, nFields,
265+
fieldNames, fieldNotNum,
266+
fieldMax, fieldMaxLen, fout))
267+
goto exit;
268+
}
271269
if (po->html3 && po->expanded)
272270
fputs("</table>\n", fout);
273271
}
@@ -298,18 +296,34 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
298296
for (i = 0; i < nTups; i++)
299297
output_row(fout, po, nFields, fields,
300298
fieldNotNum, fieldMax, border, i);
301-
free(fields);
302-
if (border)
303-
free(border);
304299
}
305300
if (po->header && !po->html3)
306301
fprintf(fout, "(%d row%s)\n\n", PQntuples(res),
307302
(PQntuples(res) == 1) ? "" : "s");
308303
if (po->html3 && !po->expanded)
309304
fputs("</table>\n", fout);
310-
free(fieldMax);
311-
free(fieldNotNum);
312-
free((void *) fieldNames);
305+
306+
exit:
307+
if (fieldMax)
308+
free(fieldMax);
309+
if (fieldNotNum)
310+
free(fieldNotNum);
311+
if (border)
312+
free(border);
313+
if (fields)
314+
{
315+
/* if calloc succeeded, this shouldn't overflow size_t */
316+
size_t numfields = ((size_t) nTups + 1) * (size_t) nFields;
317+
318+
while (numfields-- > 0)
319+
{
320+
if (fields[numfields])
321+
free(fields[numfields]);
322+
}
323+
free(fields);
324+
}
325+
if (fieldNames)
326+
free((void *) fieldNames);
313327
if (usePipe)
314328
{
315329
#ifdef WIN32
@@ -330,7 +344,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
330344
}
331345

332346

333-
static void
347+
static bool
334348
do_field(const PQprintOpt *po, const PGresult *res,
335349
const int i, const int j, const int fs_len,
336350
char **fields,
@@ -398,7 +412,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
398412
if (!(fields[i * nFields + j] = (char *) malloc(plen + 1)))
399413
{
400414
fprintf(stderr, libpq_gettext("out of memory\n"));
401-
abort();
415+
return false;
402416
}
403417
strcpy(fields[i * nFields + j], pval);
404418
}
@@ -441,6 +455,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
441455
}
442456
}
443457
}
458+
return true;
444459
}
445460

446461

@@ -468,7 +483,7 @@ do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax,
468483
if (!border)
469484
{
470485
fprintf(stderr, libpq_gettext("out of memory\n"));
471-
abort();
486+
return NULL;
472487
}
473488
p = border;
474489
if (po->standard)
@@ -559,8 +574,6 @@ output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
559574
if (po->standard || field_index + 1 < nFields)
560575
fputs(po->fieldSep, fout);
561576
}
562-
if (p)
563-
free(p);
564577
}
565578
if (po->html3)
566579
fputs("</tr>", fout);
@@ -610,7 +623,7 @@ PQdisplayTuples(const PGresult *res,
610623
if (!fLength)
611624
{
612625
fprintf(stderr, libpq_gettext("out of memory\n"));
613-
abort();
626+
return;
614627
}
615628

616629
for (j = 0; j < nFields; j++)
@@ -708,7 +721,7 @@ PQprintTuples(const PGresult *res,
708721
if (!tborder)
709722
{
710723
fprintf(stderr, libpq_gettext("out of memory\n"));
711-
abort();
724+
return;
712725
}
713726
for (i = 0; i < width; i++)
714727
tborder[i] = '-';

0 commit comments

Comments
 (0)