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.96) (envelope-from ) id 1x4ddY-007IBo-1j for pgsql-bugs@arkaria.postgresql.org; Thu, 10 Sep 2026 12:12:16 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1x4ddX-005XZX-1d for pgsql-bugs@arkaria.postgresql.org; Thu, 10 Sep 2026 12:12:15 +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.96) (envelope-from ) id 1x3a3v-001t3K-35 for pgsql-bugs@lists.postgresql.org; Mon, 07 Sep 2026 14:11:07 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x3a3t-00000003PwK-3WYA for pgsql-bugs@lists.postgresql.org; Mon, 07 Sep 2026 14:11:07 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=R5T5S6stW0ThTGOE+rEiCq42uB34abmZjtdYx93Agv4=; b=liWbL7iQ2h9JdaEBEBjERqo/7U lAFrqyvV0EohZFbgemWNJO7pARHFsZXup0oJUX4eEIhctUF3iELUHpKGdhpBorQ7VFNCDopp8P6sv 8/ihoI/Gfqv7ZjGlscrAzvJOuSgfgX5AjeZjeaq/hPqtKTIspjDiLEvP+zhJ5qM8ELbztqg++sqWs ZPa0qzB22RJve2yGoo6tbNbDfSkizmlh9fPR2fOw6cAqG8BLNDkVz6ZB0tHrgVYT4ywYlvy+/kTO1 8Y4ZbOgOD4rUVXr2XIrQK7ziRihA0uM9FJH+MEI2OPYDPEo3JmvafpZOlD76ZkZUPRwK3CENTlFdE HXsho40w==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x3a3s-00DTSe-1d for pgsql-bugs@lists.postgresql.org; Mon, 07 Sep 2026 14:11:04 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1x3a3r-00000000g1X-1p8W for pgsql-bugs@lists.postgresql.org; Mon, 07 Sep 2026 14:11:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19672: int8shl/int8shr Undefined Behavior on Out-of-Range Shift Amounts To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: 1950233439@qq.com Reply-To: 1950233439@qq.com, pgsql-bugs@lists.postgresql.org Date: Mon, 07 Sep 2026 14:10:42 +0000 Message-ID: <19672-33e7d9d1be2229ea@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19672 Logged by: Tianyu Shi Email address: 1950233439@qq.com PostgreSQL version: 19beta3 Operating system: Ubuntu22.04 Description: =20 ### Summary `int8shl()` and `int8shr()` in `src/backend/utils/adt/int8.c` (lines 1255=E2=80=931270) apply `arg1 << arg2` and `arg1 >> arg2` directly on `int= 64` without validating the shift amount `arg2`. Under C11 =C2=A76.5.7, shifting= by a negative count, by a count =E2=89=A5 64, or left-shifting a signed value in= to overflow are all undefined behavior. Every other bigint arithmetic operator in PostgreSQL (`+`, `-`, `*`, unary `-`) raises `ERROR: bigint out of range` on overflow, making the shift operators the sole exception and creating a semantic inconsistency that can silently corrupt permission bitmasks or financial calculations. ### PoC Pure SQL =E2=80=94 any authenticated database user can trigger the issue wi= thout special privileges. ```sql -- Shift count >=3D bit width: returns 1 instead of 0 or ERROR SELECT 1::bigint << 64; -- Negative shift count: returns INT64_MIN instead of ERROR SELECT 1::bigint << -1; -- Left-shift MAX_INT64 by 1: silently returns -2 instead of raising "bigint out of range" SELECT 9223372036854775807::bigint << 1; -- Differential: multiplication raises a proper error for the same value SELECT 9223372036854775807::bigint * 2; -- ERROR: bigint out of range -- Negative right-shift: returns 0 instead of ERROR SELECT 1::bigint >> -1; -- Right-shift count >=3D bit width: returns 1 instead of 0 or ERROR SELECT 1::bigint >> 64; ``` ```bash # Initialize and start a UBSAN-instrumented PostgreSQL instance ./build/bin/initdb -D pgdata --no-locale -E UTF8 mkdir -p ./build/run ./build/bin/pg_ctl -D pgdata -l pgdata/postgres.log \ -o "-p 55433 -k ./build/run" start # Run the PoC queries (Test 4 will error; that is expected) ./build/bin/psql -h ./build/run -p 55433 postgres <<'EOF' SELECT 1::bigint << 64; SELECT 1::bigint << -1; SELECT 9223372036854775807::bigint << 1; SELECT 9223372036854775807::bigint * 2; SELECT 1::bigint >> -1; SELECT 1::bigint >> 64; EOF # Inspect server log for UBSAN output grep -E "runtime error|UndefinedBehaviorSanitizer|SUMMARY" pgdata/postgres.log ./build/bin/pg_ctl -D pgdata stop ``` ### Result UndefinedBehaviorSanitizer fired in the PostgreSQL server log at both shift sites: `int8.c:1260:2: runtime error: shift exponent 64 is too large for 64-bit type 'int64' (aka 'long')` and `int8.c:1269:2: runtime error: shift exponent -1 is negative`. The SQL output confirms wrong values: `1::bigint << 64` returns `1` (expected `0` or error), `1::bigint << -1` returns `-9223372036854775808` (expected error), and `9223372036854775807::bigint << 1` returns `-2` (expected `ERROR: bigint out of range`). The differential confirms the inconsistency: `9223372036854775807::bigint * 2` correctly raises `ERROR: bigint out of range`, while the semantically equivalent left-shift silently wraps.