Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1r5BCK-00CBtP-6B for pgsql-hackers@arkaria.postgresql.org; Mon, 20 Nov 2023 20:48:48 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1r5BCI-00AZwB-2j for pgsql-hackers@arkaria.postgresql.org; Mon, 20 Nov 2023 20:48:46 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1r5BCH-00AZw3-Lt for pgsql-hackers@lists.postgresql.org; Mon, 20 Nov 2023 20:48:45 +0000 Received: from wout2-smtp.messagingengine.com ([64.147.123.25]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1r5BCE-007UUz-IA for pgsql-hackers@postgresql.org; Mon, 20 Nov 2023 20:48:45 +0000 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.west.internal (Postfix) with ESMTP id E1AAA3200C8E; Mon, 20 Nov 2023 15:48:38 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Mon, 20 Nov 2023 15:48:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1700513318; x= 1700599718; bh=b62gepHl5WPD2xsKTV0pd5SeWXqp/HRm8SoECIKBteY=; b=p g/sz78wj5MPa64C+AmOqnbKYB2g5jAMK1Y/UosIwCd3/7grBnt8WVRdFYkarkJWd VpR80u/Y4awQk49/lW7+aE5tbkyxvdJLXcxm7Jbg+8NRkpjyfbIqtguoQRf7OF1P 3ghnx+YXvxiHm6++t2fbUGjgzecH/2xUrhmqIqRuaufcJMcYxhkTo9QifQkHelBS EQFe9AtHQCgRcbJHHvp8x6ayd7t+yj5kjkezv5I7UxasFbyv4/xxQK1/8yZ3LyTf x3WDxuXm9mVaq4vWHoqXhIIHJk/oobqDUr3h97C1EsD7zyaiok0QO1iwHNLGFUb6 Gm8csMkYpZKevGp2bPXdg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrudegjedguddugecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvvefukfggtggugfgjsehmkeerredttdejnecuhfhrohhmpeetlhhv rghrohcujfgvrhhrvghrrgcuoegrlhhvhhgvrhhrvgesrghlvhhhrdhnohdqihhprdhorh hgqeenucggtffrrghtthgvrhhnpeduleekkefgtddttedtkefguddvieffleetgeejiefh teehkeevfeettdduvdfhueenucffohhmrghinhepvghnthgvrhhprhhishgvuggsrdgtoh hmnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprghl vhhhvghrrhgvsegrlhhvhhdrnhhoqdhiphdrohhrgh X-ME-Proxy: Feedback-ID: ia2694551:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 20 Nov 2023 15:48:37 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alvh.no-ip.org; s=schmee; t=1700513315; bh=1mynsw+xW4fX9L6wuSmVGDZWzHVzI7aM353uTnCX9fs=; h=Date:From:To:Cc:Subject:In-Reply-To:From; b=DCUkItme1uqQvCKV1Eayi05TFHzmk7Up11IgQZgXySX3jpQZAljP10pxBlONyozsv 4Ux3ae1V+XCFqI7fJanP7Ca5mlKc0ZxZuj9pWpdvnCRocl3X0CKvPUdxrxghpwX8Xz UY96FZYYOSjODqCvVosYy7HLZGnpFHx/dhRnloL+/swGoR1EUJmZxqa9GGSdjxmpkz JA5+DpjbVcz2+wO5euN0gnhRXj/qacHVot1QE0ra/i+47UMZezsZXc9FKNlLmhih/K kYJM+IpxFLMRNtQZQrFBf4Phrb2rQ75+/Di5EDezo2yXiQdxbvd/AkTFL4K1l7bYV3 k6SZ6k/5FeufQ== Received: by perhan.alvh.no-ip.org (Postfix, from userid 1000) id 4F6F4127; Mon, 20 Nov 2023 21:48:35 +0100 (CET) Date: Mon, 20 Nov 2023 21:48:35 +0100 From: Alvaro Herrera To: Tom Lane Cc: Michael Paquier , Hongxu Ma , Jelte Fennema , "David G. Johnston" , PostgreSQL Hackers Subject: Re: PSQL error: total cell count of XXX exceeded Message-ID: <202311202048.n2a3dsjldhne@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="foqmnayrgaqivz2e" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <2728718.1694492393@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --foqmnayrgaqivz2e Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit On 2023-Sep-12, Tom Lane wrote: > I'm more than a bit skeptical about trying to do something about this, > simply because this range of query result sizes is far past what is > practical. The OP clearly hasn't tested his patch on actually > overflowing query results, and I don't care to either. I think we're bound to hit this limit at some point in the future, and it seems easy enough to solve. I propose the attached, which is pretty much what Hongxu last submitted, with some minor changes. Having this make a difference requires some 128GB of RAM, so it's not a piece of cake, but it's an amount that can be reasonably expected to be physically installed in real machines nowadays. (I first thought we could just use pg_mul_s32_overflow during printTableInit and raise an error if that returns true, but that just postpones the problem.) -- Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/ Subversion to GIT: the shortest path to happiness I've ever heard of (Alexey Klyukin) --foqmnayrgaqivz2e Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="v5-0001-Avoid-overflow-in-fe_utils-printTable-API.patch" From 75abe5a485532cbc03db1eade2e1a6099914f98f Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 20 Nov 2023 17:35:18 +0100 Subject: [PATCH v5] Avoid overflow in fe_utils' printTable API We were using 32-bit integer arithmetic to compute the total number of cells, which can overflow when used with large resultsets. We still don't allow more than 4 billion rows, but now the total number of cells can exceed that. Author: Hongxu Ma Discussion: https://postgr.es/m/TYBP286MB0351B057B101C90D7C1239E6B4E2A@TYBP286MB0351.JPNP286.PROD.OUTLOOK.COM --- src/fe_utils/print.c | 22 ++++++++++++++-------- src/include/fe_utils/print.h | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c index 7af1ccb6b5..565cbc6d13 100644 --- a/src/fe_utils/print.c +++ b/src/fe_utils/print.c @@ -3172,6 +3172,8 @@ void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows) { + int64 total_cells; + content->opt = opt; content->title = title; content->ncolumns = ncolumns; @@ -3179,7 +3181,8 @@ 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 = (int64) ncolumns * nrows; + content->cells = pg_malloc0((total_cells + 1) * sizeof(*content->cells)); content->cellmustfree = NULL; content->footers = NULL; @@ -3249,15 +3252,17 @@ void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree) { + int64 total_cells; + #ifndef ENABLE_NLS (void) translate; /* unused parameter */ #endif - if (content->cellsadded >= content->ncolumns * content->nrows) + total_cells = (int64) 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 +3278,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 +3346,10 @@ printTableCleanup(printTableContent *const content) { if (content->cellmustfree) { - int i; + int64 total_cells; - for (i = 0; i < content->nrows * content->ncolumns; i++) + total_cells = (int64) content->ncolumns * content->nrows; + for (int64 i = 0; i < total_cells; i++) { if (content->cellmustfree[i]) free(unconstify(char *, content->cells[i])); diff --git a/src/include/fe_utils/print.h b/src/include/fe_utils/print.h index 13ebb00362..a697d0ba8d 100644 --- a/src/include/fe_utils/print.h +++ b/src/include/fe_utils/print.h @@ -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 */ + int64 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 */ -- 2.39.2 --foqmnayrgaqivz2e--