Re: BUG #19673: inetmi_int8 Signed Integer Overflow Returns Wrong IPv6 Address

From: Kirill Reshke <reshkekirill(at)gmail(dot)com>
To: 1950233439(at)qq(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #19673: inetmi_int8 Signed Integer Overflow Returns Wrong IPv6 Address
Date: 2026-10-29 13:49:04
Message-ID: CALdSSPgDgvuUCsGqmGibjW-3DfN88+kOHHK_gfYRP9R+vtx45A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

On Thu, 10 Sept 2026 at 17:11, PG Bug reporting form
<noreply(at)postgresql(dot)org> wrote:
>
> The following bug has been logged on the website:
>
> Bug reference: 19673
> Logged by: Tianyu Shi
> Email address: 1950233439(at)qq(dot)com
> PostgreSQL version: 19beta3
> Operating system: Ubuntu22.04
> Description:
>
> ### Summary
>
> In `inetmi_int8()` (`src/backend/utils/adt/network.c`, line 1946), the
> expression `-addend` triggers signed integer overflow (C11 undefined
> behavior) when `addend == INT64_MIN`. On x86-64, the CPU wraps the negation
> back to `INT64_MIN`, causing the function to compute `ip - 2^63` instead of
> the correct `ip + 2^63`. For IPv6 addresses, the overflow-detection path in
> `internal_inetpl()` does not catch this case, so the function silently
> returns a completely wrong address rather than raising an error.
> Applications that use `inet - int8` to compute IPv6 subnet boundaries may
> therefore derive incorrect range endpoints, potentially causing
> access-control decisions to accept or reject the wrong addresses.
>
> ### PoC
>
> Any unprivileged user can trigger the bug with a single SQL statement using
> the `inet - int8` operator and `INT64_MIN` as the subtrahend.
>
> ```sql
> -- Connect as any normal (non-superuser) role.
> -- INT64_MIN must be passed as a string cast to avoid parse-time overflow.
>
> -- Trigger: should compute 8000::1 + 2^63 = 8000::8000:0:0:1, but silently
> returns a lower address.
> SELECT '8000::1'::inet - '-9223372036854775808'::int8 AS trigger_result;
>
> -- Roundtrip invariant: (X - INT64_MIN) + INT64_MIN must equal X.
> SELECT
> '8000::1'::inet
> AS original,
> '8000::1'::inet - '-9223372036854775808'::int8
> AS minus_int64min,
> ('8000::1'::inet - '-9223372036854775808'::int8) +
> '-9223372036854775808'::int8 AS roundtrip,
> (('8000::1'::inet - '-9223372036854775808'::int8) +
> '-9223372036854775808'::int8)
> = '8000::1'::inet
> AS roundtrip_correct;
>
> -- Direction invariant: subtracting a negative must increase the address.
> SELECT
> '8000::1'::inet AS
> original,
> '8000::1'::inet - '-9223372036854775808'::int8 AS
> result,
> ('8000::1'::inet - '-9223372036854775808'::int8) > '8000::1'::inet AS
> direction_increased;
> ```
>
> ### Result
>
> Expected: `'8000::1'::inet - INT64_MIN` = `ip + 2^63` = `8000::8000:0:0:1`
> (address increases).
> Actual: the function returns `7fff:ffff:ffff:ffff:8000::1`, which is *less*
> than the original address — the arithmetic went in the wrong direction with
> no error raised.
>
> All three semantic invariants are violated:
>
> ```
> original | minus_int64min | roundtrip |
> roundtrip_correct
> ----------+-----------------------------+------------------------+-------------------
> 8000::1 | 7fff:ffff:ffff:ffff:8000::1 | 7fff:ffff:ffff:ffff::1 | f
>
> original | result | direction_increased
> ----------+-----------------------------+---------------------
> 8000::1 | 7fff:ffff:ffff:ffff:8000::1 | f
> ```
>
> `roundtrip_correct = f` and `direction_increased = f` confirm that
> `inetmi_int8()` computed `ip - 2^63` instead of `ip + 2^63` due to the
> signed integer overflow of `-INT64_MIN` on x86-64.
>
>

Hi!
There are additional erroneous cases.

For the full range of the IPv6 address space the true mathematical
difference is 2^128-1. However its byte reprization is all 0xFF
which looks like the sign truncated result. Operator silently returns
-1 / 1:

SELECT inet 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' - inet '::';
?column?
----------
-1
SELECT inet '::' - inet 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff';
?column?
----------
1

expected is 22003 (result is out of range) in both

I didn't go with any patch for this, but in case anyone do, that's
something we need to handle too

--
Best regards,
Kirill Reshke

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Dilip Kumar 2026-10-29 14:23:43 Re: BUG #19791: ALTER COLUMN TYPE fails on an INCLUDE column of an index used by a foreign key
Previous Message Jeevan Chalke 2026-10-29 13:24:02 Re: BUG #19384: Server crash at textout