Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b54be47

Browse filesBrowse 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 21257a8 commit b54be47
Copy full SHA for b54be47

File tree

Expand file treeCollapse file tree

1 file changed

+49
-36
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+49
-36
lines changed

‎src/interfaces/libpq/fe-print.c

Copy file name to clipboardExpand all lines: src/interfaces/libpq/fe-print.c
+49-36Lines changed: 49 additions & 36 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];
@@ -184,7 +177,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
184177
fout = popen(pagerenv, "w");
185178
if (fout)
186179
{
187-
usePipe = 1;
180+
usePipe = true;
188181
#ifndef WIN32
189182
#ifdef ENABLE_THREAD_SAFETY
190183
if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
@@ -201,10 +194,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
201194

202195
if (!po->expanded && (po->align || po->html3))
203196
{
204-
if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *))))
197+
fields = (char **) calloc((size_t) nTups + 1,
198+
nFields * sizeof(char *));
199+
if (!fields)
205200
{
206201
fprintf(stderr, libpq_gettext("out of memory\n"));
207-
abort();
202+
goto exit;
208203
}
209204
}
210205
else if (po->header && !po->html3)
@@ -258,9 +253,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
258253
fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i);
259254
}
260255
for (j = 0; j < nFields; j++)
261-
do_field(po, res, i, j, fs_len, fields, nFields,
262-
fieldNames, fieldNotNum,
263-
fieldMax, fieldMaxLen, fout);
256+
{
257+
if (!do_field(po, res, i, j, fs_len, fields, nFields,
258+
fieldNames, fieldNotNum,
259+
fieldMax, fieldMaxLen, fout))
260+
goto exit;
261+
}
264262
if (po->html3 && po->expanded)
265263
fputs("</table>\n", fout);
266264
}
@@ -291,16 +289,34 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
291289
for (i = 0; i < nTups; i++)
292290
output_row(fout, po, nFields, fields,
293291
fieldNotNum, fieldMax, border, i);
294-
free(fields);
295-
if (border)
296-
free(border);
297292
}
298293
if (po->header && !po->html3)
299294
fprintf(fout, "(%d row%s)\n\n", PQntuples(res),
300295
(PQntuples(res) == 1) ? "" : "s");
301-
free(fieldMax);
302-
free(fieldNotNum);
303-
free((void *) fieldNames);
296+
if (po->html3 && !po->expanded)
297+
fputs("</table>\n", fout);
298+
299+
exit:
300+
if (fieldMax)
301+
free(fieldMax);
302+
if (fieldNotNum)
303+
free(fieldNotNum);
304+
if (border)
305+
free(border);
306+
if (fields)
307+
{
308+
/* if calloc succeeded, this shouldn't overflow size_t */
309+
size_t numfields = ((size_t) nTups + 1) * (size_t) nFields;
310+
311+
while (numfields-- > 0)
312+
{
313+
if (fields[numfields])
314+
free(fields[numfields]);
315+
}
316+
free(fields);
317+
}
318+
if (fieldNames)
319+
free((void *) fieldNames);
304320
if (usePipe)
305321
{
306322
#ifdef WIN32
@@ -317,13 +333,11 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
317333
#endif /* ENABLE_THREAD_SAFETY */
318334
#endif /* WIN32 */
319335
}
320-
if (po->html3 && !po->expanded)
321-
fputs("</table>\n", fout);
322336
}
323337
}
324338

325339

326-
static void
340+
static bool
327341
do_field(const PQprintOpt *po, const PGresult *res,
328342
const int i, const int j, const int fs_len,
329343
char **fields,
@@ -391,7 +405,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
391405
if (!(fields[i * nFields + j] = (char *) malloc(plen + 1)))
392406
{
393407
fprintf(stderr, libpq_gettext("out of memory\n"));
394-
abort();
408+
return false;
395409
}
396410
strcpy(fields[i * nFields + j], pval);
397411
}
@@ -434,6 +448,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
434448
}
435449
}
436450
}
451+
return true;
437452
}
438453

439454

@@ -461,7 +476,7 @@ do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax,
461476
if (!border)
462477
{
463478
fprintf(stderr, libpq_gettext("out of memory\n"));
464-
abort();
479+
return NULL;
465480
}
466481
p = border;
467482
if (po->standard)
@@ -552,8 +567,6 @@ output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
552567
if (po->standard || field_index + 1 < nFields)
553568
fputs(po->fieldSep, fout);
554569
}
555-
if (p)
556-
free(p);
557570
}
558571
if (po->html3)
559572
fputs("</tr>", fout);
@@ -603,7 +616,7 @@ PQdisplayTuples(const PGresult *res,
603616
if (!fLength)
604617
{
605618
fprintf(stderr, libpq_gettext("out of memory\n"));
606-
abort();
619+
return;
607620
}
608621

609622
for (j = 0; j < nFields; j++)
@@ -701,7 +714,7 @@ PQprintTuples(const PGresult *res,
701714
if (!tborder)
702715
{
703716
fprintf(stderr, libpq_gettext("out of memory\n"));
704-
abort();
717+
return;
705718
}
706719
for (i = 0; i < width; i++)
707720
tborder[i] = '-';

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.