]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Avoid overflow in fe_utils' printTable()
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 21 Nov 2023 13:55:29 +0000 (14:55 +0100)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 21 Nov 2023 13:55:29 +0000 (14:55 +0100)
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

src/fe_utils/print.c
src/include/fe_utils/print.h

index 7af1ccb6b562bd6e75839d22b3e159c9a59168e8..5bc4ef0c3e300167a7b3884060f4ed752917bc47 100644 (file)
@@ -3172,6 +3172,8 @@ void
 printTableInit(printTableContent *const content, const printTableOpt *opt,
                           const char *title, const int ncolumns, const int nrows)
 {
+       uint64          total_cells;
+
        content->opt = opt;
        content->title = title;
        content->ncolumns = ncolumns;
@@ -3179,7 +3181,16 @@ printTableInit(printTableContent *const content, const printTableOpt *opt,
 
        content->headers = pg_malloc0((ncolumns + 1) * sizeof(*content->headers));
 
-       content->cells = pg_malloc0((ncolumns * nrows + 1) * sizeof(*content->cells));
+       total_cells = (uint64) ncolumns * nrows;
+       /* Catch possible overflow.  Using >= here allows adding 1 below */
+       if (total_cells >= SIZE_MAX / sizeof(*content->cells))
+       {
+               fprintf(stderr, _("Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n"),
+                               (long long int) total_cells,
+                               (long long int) (SIZE_MAX / sizeof(*content->cells)));
+               exit(EXIT_FAILURE);
+       }
+       content->cells = pg_malloc0((total_cells + 1) * sizeof(*content->cells));
 
        content->cellmustfree = NULL;
        content->footers = NULL;
@@ -3249,15 +3260,17 @@ void
 printTableAddCell(printTableContent *const content, char *cell,
                                  const bool translate, const bool mustfree)
 {
+       uint64          total_cells;
+
 #ifndef ENABLE_NLS
        (void) translate;                       /* unused parameter */
 #endif
 
-       if (content->cellsadded >= content->ncolumns * content->nrows)
+       total_cells = (uint64) content->ncolumns * content->nrows;
+       if (content->cellsadded >= total_cells)
        {
-               fprintf(stderr, _("Cannot add cell to table content: "
-                                                 "total cell count of %d exceeded.\n"),
-                               content->ncolumns * content->nrows);
+               fprintf(stderr, _("Cannot add cell to table content: total cell count of %lld exceeded.\n"),
+                               (long long int) total_cells);
                exit(EXIT_FAILURE);
        }
 
@@ -3273,7 +3286,7 @@ printTableAddCell(printTableContent *const content, char *cell,
        {
                if (content->cellmustfree == NULL)
                        content->cellmustfree =
-                               pg_malloc0((content->ncolumns * content->nrows + 1) * sizeof(bool));
+                               pg_malloc0((total_cells + 1) * sizeof(bool));
 
                content->cellmustfree[content->cellsadded] = true;
        }
@@ -3341,9 +3354,10 @@ printTableCleanup(printTableContent *const content)
 {
        if (content->cellmustfree)
        {
-               int                     i;
+               uint64          total_cells;
 
-               for (i = 0; i < content->nrows * content->ncolumns; i++)
+               total_cells = (uint64) content->ncolumns * content->nrows;
+               for (uint64 i = 0; i < total_cells; i++)
                {
                        if (content->cellmustfree[i])
                                free(unconstify(char *, content->cells[i]));
index 13ebb003624f35ddd0c1bd40fcf011a8079b357b..cfc26b952036adb2254e6d605eab8f6c296410cc 100644 (file)
@@ -171,7 +171,7 @@ typedef struct printTableContent
        const char **cells;                     /* NULL-terminated array of cell content
                                                                 * strings */
        const char **cell;                      /* Pointer to the last added cell */
-       long            cellsadded;             /* Number of cells added this far */
+       uint64          cellsadded;             /* Number of cells added this far */
        bool       *cellmustfree;       /* true for cells that need to be free()d */
        printTableFooter *footers;      /* Pointer to the first footer */
        printTableFooter *footer;       /* Pointer to the last added footer */