Skip to content

Decode IPv4-mapped IPv6 addresses in PG::TextDecoder::Inet - #772

Merged
larskanis merged 1 commit into
ged:masterfrom
mlarraz:inet-ipv4-mapped
Nov 13, 2026
Merged

larskanis merged 1 commit into
ged:masterfrom
mlarraz:inet-ipv4-mapped

Conversation

@mlarraz

@mlarraz mlarraz commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

PostgreSQL prints IPv4-mapped (and the old IPv4-compatible) IPv6 addresses in dotted form, e.g. ::ffff:192.168.1.1/128. PG::TextDecoder::Inet can't decode those, so with PG::BasicTypeMapForResults the whole result fails:

conn = PG.connect
conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn)
conn.exec("SELECT '::ffff:192.168.1.1'::inet").getvalue(0, 0)
# => TypeError: wrong data for text inet converter in tuple 0 field 0 val

The decoder picks the address family with strchr(val, '.') ? AF_INET : AF_INET6, so these values go to inet_pton(AF_INET, ...), which rejects them. The same happens for cidr (e.g. ::ffff:10.0.0.0/104). These addresses show up in columns that store client addresses, since a dual-stack socket reports IPv4 peers as ::ffff:a.b.c.d. Encoding the same IPAddr already works; only decoding fails.

This checks for ':' instead: IPv6 text always contains one and IPv4 text never does. I added a few mapped addresses to the existing inet and cidr cases in basic_type_map_for_results_spec.rb; they fail without the change and pass with it. The Windows branch of the decoder uses IPAddr.new and isn't touched, and host-bit masking (#353) is unchanged.

Reproduced with 1.5.4, 1.6.3 and master on macOS. The line dates back to when the decoder was added in 1.1.0.

I found this while reviewing the decoders with an AI assistant; I verified the repro and the fix myself.

PostgreSQL prints IPv4-mapped and IPv4-compatible IPv6 addresses in
dotted form, like ::ffff:1.2.3.4. The decoder chose AF_INET whenever
the text contained a dot, so inet_pton() rejected these values and
decoding raised TypeError.

Choose AF_INET6 when the text contains a colon instead.
@larskanis
larskanis merged commit aa8cb42 into ged:master Nov 13, 2026
33 of 35 checks passed
@larskanis

Copy link
Copy Markdown
Collaborator

Thank you, this looks good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants