Skip to content

Commit c649123

Browse files
committed
Handle IP values with prefix in "inet" type as IPvXInterface
Currently we treat values with network prefix in `inet` values as IPvXNetwork, which is wrong.
1 parent 93f8959 commit c649123

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

codecs/__init__.pxd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,10 @@ cdef tid_decode(CodecContext settings, FRBuffer * buf)
133133

134134

135135
# Network
136-
cdef net_decode(CodecContext settings, FRBuffer * buf)
137136
cdef cidr_encode(CodecContext settings, WriteBuffer buf, obj)
137+
cdef cidr_decode(CodecContext settings, FRBuffer * buf)
138138
cdef inet_encode(CodecContext settings, WriteBuffer buf, obj)
139+
cdef inet_decode(CodecContext settings, FRBuffer * buf)
139140

140141

141142
# txid

codecs/network.pyx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ DEF PGSQL_AF_INET6 = 3 # AF_INET + 1
1515

1616

1717
_ipaddr = ipaddress.ip_address
18+
_ipiface = ipaddress.ip_interface
1819
_ipnet = ipaddress.ip_network
1920

2021

@@ -59,15 +60,19 @@ cdef inline _net_encode(WriteBuffer buf, int8_t family, uint32_t bits,
5960
buf.write_cstr(addrbytes, addrlen)
6061

6162

62-
cdef net_decode(CodecContext settings, FRBuffer *buf):
63+
cdef net_decode(CodecContext settings, FRBuffer *buf, bint as_cidr):
6364
cdef:
6465
int32_t family = <int32_t>frb_read(buf, 1)[0]
6566
uint8_t bits = <uint8_t>frb_read(buf, 1)[0]
67+
int prefix_len
6668
int32_t is_cidr = <int32_t>frb_read(buf, 1)[0]
6769
int32_t addrlen = <int32_t>frb_read(buf, 1)[0]
6870
bytes addr
6971
uint8_t max_prefix_len = _ip_max_prefix_len(family)
7072

73+
if is_cidr != as_cidr:
74+
raise ValueError('unexpected CIDR flag set in non-cidr value')
75+
7176
if family != PGSQL_AF_INET and family != PGSQL_AF_INET6:
7277
raise ValueError('invalid address family in "{}" value'.format(
7378
'cidr' if is_cidr else 'inet'
@@ -87,8 +92,13 @@ cdef net_decode(CodecContext settings, FRBuffer *buf):
8792

8893
addr = cpython.PyBytes_FromStringAndSize(frb_read(buf, addrlen), addrlen)
8994

90-
if is_cidr or bits != max_prefix_len:
91-
return _ipnet(addr).supernet(new_prefix=cpython.PyLong_FromLong(bits))
95+
if as_cidr or bits != max_prefix_len:
96+
prefix_len = cpython.PyLong_FromLong(bits)
97+
98+
if as_cidr:
99+
return _ipnet((addr, prefix_len))
100+
else:
101+
return _ipiface((addr, prefix_len))
92102
else:
93103
return _ipaddr(addr)
94104

@@ -103,6 +113,10 @@ cdef cidr_encode(CodecContext settings, WriteBuffer buf, obj):
103113
_net_encode(buf, family, ipnet.prefixlen, 1, ipnet.network_address.packed)
104114

105115

116+
cdef cidr_decode(CodecContext settings, FRBuffer *buf):
117+
return net_decode(settings, buf, True)
118+
119+
106120
cdef inet_encode(CodecContext settings, WriteBuffer buf, obj):
107121
cdef:
108122
object ipaddr
@@ -113,7 +127,13 @@ cdef inet_encode(CodecContext settings, WriteBuffer buf, obj):
113127
except ValueError:
114128
# PostgreSQL accepts *both* CIDR and host values
115129
# for the host datatype.
116-
cidr_encode(settings, buf, obj)
130+
ipaddr = _ipiface(obj)
131+
family = _ver_to_family(ipaddr.version)
132+
_net_encode(buf, family, ipaddr.network.prefixlen, 1, ipaddr.packed)
117133
else:
118134
family = _ver_to_family(ipaddr.version)
119135
_net_encode(buf, family, _ip_max_prefix_len(family), 0, ipaddr.packed)
136+
137+
138+
cdef inet_decode(CodecContext settings, FRBuffer *buf):
139+
return net_decode(settings, buf, False)

0 commit comments

Comments
 (0)