Skip to content

Commit 24ea53d

Browse files
committed
Avoid overflow in fe_utils' printTable()
The original code would miscalculate the total number of cells when the table to print has more than ~4 billion cells, leading to an unnecessary error. Repair by changing some computations to be 64-bits wide. Add some necessary overflow checks. Author: Hongxu Ma <interma@outlook.com> Discussion: https://postgr.es/m/TYBP286MB0351B057B101C90D7C1239E6B4E2A@TYBP286MB0351.JPNP286.PROD.OUTLOOK.COM
1 parent e83aa9f commit 24ea53d

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

src/fe_utils/print.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3172,14 +3172,25 @@ void
31723172
printTableInit(printTableContent *const content, const printTableOpt *opt,
31733173
const char *title, const int ncolumns, const int nrows)
31743174
{
3175+
uint64 total_cells;
3176+
31753177
content->opt = opt;
31763178
content->title = title;
31773179
content->ncolumns = ncolumns;
31783180
content->nrows = nrows;
31793181

31803182
content->headers = pg_malloc0((ncolumns + 1) * sizeof(*content->headers));
31813183

3182-
content->cells = pg_malloc0((ncolumns * nrows + 1) * sizeof(*content->cells));
3184+
total_cells = (uint64) ncolumns * nrows;
3185+
/* Catch possible overflow. Using >= here allows adding 1 below */
3186+
if (total_cells >= SIZE_MAX / sizeof(*content->cells))
3187+
{
3188+
fprintf(stderr, _("Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n"),
3189+
(long long int) total_cells,
3190+
(long long int) (SIZE_MAX / sizeof(*content->cells)));
3191+
exit(EXIT_FAILURE);
3192+
}
3193+
content->cells = pg_malloc0((total_cells + 1) * sizeof(*content->cells));
31833194

31843195
content->cellmustfree = NULL;
31853196
content->footers = NULL;
@@ -3249,15 +3260,17 @@ void
32493260
printTableAddCell(printTableContent *const content, char *cell,
32503261
const bool translate, const bool mustfree)
32513262
{
3263+
uint64 total_cells;
3264+
32523265
#ifndef ENABLE_NLS
32533266
(void) translate; /* unused parameter */
32543267
#endif
32553268

3256-
if (content->cellsadded >= content->ncolumns * content->nrows)
3269+
total_cells = (uint64) content->ncolumns * content->nrows;
3270+
if (content->cellsadded >= total_cells)
32573271
{
3258-
fprintf(stderr, _("Cannot add cell to table content: "
3259-
"total cell count of %d exceeded.\n"),
3260-
content->ncolumns * content->nrows);
3272+
fprintf(stderr, _("Cannot add cell to table content: total cell count of %lld exceeded.\n"),
3273+
(long long int) total_cells);
32613274
exit(EXIT_FAILURE);
32623275
}
32633276

@@ -3273,7 +3286,7 @@ printTableAddCell(printTableContent *const content, char *cell,
32733286
{
32743287
if (content->cellmustfree == NULL)
32753288
content->cellmustfree =
3276-
pg_malloc0((content->ncolumns * content->nrows + 1) * sizeof(bool));
3289+
pg_malloc0((total_cells + 1) * sizeof(bool));
32773290

32783291
content->cellmustfree[content->cellsadded] = true;
32793292
}
@@ -3341,9 +3354,10 @@ printTableCleanup(printTableContent *const content)
33413354
{
33423355
if (content->cellmustfree)
33433356
{
3344-
int i;
3357+
uint64 total_cells;
33453358

3346-
for (i = 0; i < content->nrows * content->ncolumns; i++)
3359+
total_cells = (uint64) content->ncolumns * content->nrows;
3360+
for (uint64 i = 0; i < total_cells; i++)
33473361
{
33483362
if (content->cellmustfree[i])
33493363
free(unconstify(char *, content->cells[i]));

src/include/fe_utils/print.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ typedef struct printTableContent
171171
const char **cells; /* NULL-terminated array of cell content
172172
* strings */
173173
const char **cell; /* Pointer to the last added cell */
174-
long cellsadded; /* Number of cells added this far */
174+
uint64 cellsadded; /* Number of cells added this far */
175175
bool *cellmustfree; /* true for cells that need to be free()d */
176176
printTableFooter *footers; /* Pointer to the first footer */
177177
printTableFooter *footer; /* Pointer to the last added footer */

0 commit comments

Comments
 (0)