[MDEV-28283] type_inet.type_inet6 differ IS_IPV4_COMPAT(BINARY a) vs IS_IPV4_COMPAT(a) Created: 2022-04-11  Updated: 2023-03-03

Status: Open
Project: MariaDB Server
Component/s: Data types
Affects Version/s: 10.6
Fix Version/s: 10.6

Type: Bug Priority: Major
Reporter: Daniel Black Assignee: Alexander Barkov
Resolution: Unresolved Votes: 0
Labels: None


 Description   

IS_IPV4_COMPAT is called 8 times in type_inet.type_inet6. 4 initially without casting varchar to binary, and then 4 casting to binary:

mysql-test/mtr --gdb='b Inet6::is_v4compat; r;p *this;c;p *this;c; p *this;c; p *this;c; p *this;c; p *this;' type_inet.type_inet6

 
Thread 6 "mariadbd" hit Breakpoint 1, Inet6::is_v4compat (this=0x7ffff1add130) at /home/dan/repos/mariadb-server-10.6/plugin/type_inet/sql_type_inet.h:222
222	    return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) m_buffer);
$1 = {m_buffer = '\000' <repeats 12 times>, "\300\250\000\001"}
 
Thread 6 "mariadbd" hit Breakpoint 1, Inet6::is_v4compat (this=0x7ffff1add130) at /home/dan/repos/mariadb-server-10.6/plugin/type_inet/sql_type_inet.h:222
222	    return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) m_buffer);
$2 = {m_buffer = '\000' <repeats 12 times>, "\300\250\no"}
 
Thread 6 "mariadbd" hit Breakpoint 1, Inet6::is_v4compat (this=0x7ffff1add130) at /home/dan/repos/mariadb-server-10.6/plugin/type_inet/sql_type_inet.h:222
222	    return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) m_buffer);
$3 = {m_buffer = "\000\000\000\000\000\000\000\000\000\000\377\377\n\n\000\001"}
 
Thread 6 "mariadbd" hit Breakpoint 1, Inet6::is_v4compat (this=0x7ffff1add130) at /home/dan/repos/mariadb-server-10.6/plugin/type_inet/sql_type_inet.h:222
222	    return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) m_buffer);
$4 = {m_buffer = "\000\000\000\000\000\000\000\000\000\000\377\377\300\250\000\001"}
 
Thread 6 "mariadbd" hit Breakpoint 1, Inet6::is_v4compat (this=0x7ffff1add130) at /home/dan/repos/mariadb-server-10.6/plugin/type_inet/sql_type_inet.h:222
222	    return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) m_buffer);
$5 = {m_buffer = "::192.168.10.111"}
 
Thread 6 "mariadbd" hit Breakpoint 1, Inet6::is_v4compat (this=0x7ffff1add130) at /home/dan/repos/mariadb-server-10.6/plugin/type_inet/sql_type_inet.h:222
222	    return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) m_buffer);
$6 = {m_buffer = "::ffff:10.10.0.1"}

The first 4 seem to encode the buffer correctly. The next 2 (not 4), have a text representation in the m_buffer. Given Inet6::is_v4compat is implemented with IN6_IS_ADDR_V4COMPAT, the existence of a text encoded IP in the buffer is incorrect.

From the type_inet.type_inet6.result, are the results meant to be the same:

SELECT id, length(a), a, IS_IPV4_COMPAT(a) FROM t1 ORDER BY id;
id      length(a)       a       IS_IPV4_COMPAT(a)
1       13      ::192.168.0.1   1
2       16      ::192.168.10.111        1
3       16      ::ffff:10.10.0.1        0
4       18      ::ffff:192.168.0.1      0
...
SELECT id, length(a), a, IS_IPV4_COMPAT(BINARY a) FROM t1 ORDER BY id;
id      length(a)       a       IS_IPV4_COMPAT(BINARY a)
1       13      ::192.168.0.1   0
2       16      ::192.168.10.111        0
3       16      ::ffff:10.10.0.1        0
4       18      ::ffff:192.168.0.1      0
Warnings:
Warning 1292    Incorrect inet6 value: '::192.168.0.1'
Warning 1292    Incorrect inet6 value: '::ffff:192.168.0.1'

Same difference on IS_IPV4_MAPPED.



 Comments   
Comment by Alexander Barkov [ 2022-04-27 ]

The results seem to be correct. When you do IS_IPV4_COMPAT(BINARY a), the function treats its input as a binary IPV6 representation.

This scripts demonstrates:

SELECT c1, LENGTH(c1),
 CAST(CAST(c1 AS BINARY) AS INET6) AS c2,
 IS_IPV4_COMPAT(BINARY c1)
FROM (values ('c1'),
('::192.168.0.1'),
('::192.168.10.111'),
('::ffff:10.10.0.1'),
('::ffff:192.168.0.1')) t1 WHERE c1 LIKE '::%';

+--------------------+------------+-----------------------------------------+---------------------------+
| c1                 | LENGTH(c1) | c2                                      | IS_IPV4_COMPAT(BINARY c1) |
+--------------------+------------+-----------------------------------------+---------------------------+
| ::192.168.0.1      |         13 | NULL                                    |                         0 |
| ::192.168.10.111   |         16 | 3a3a:3139:322e:3136:382e:3130:2e31:3131 |                         0 |
| ::ffff:10.10.0.1   |         16 | 3a3a:6666:6666:3a31:302e:3130:2e30:2e31 |                         0 |
| ::ffff:192.168.0.1 |         18 | NULL                                    |                         0 |
+--------------------+------------+-----------------------------------------+---------------------------+
4 rows in set, 4 warnings (0.002 sec)

  • The first and the last values are not INET6 binary representations at all - they are not 16 bytes. Hence warnings. IS_IPV4_COMPAT() returns 0 (not NULL) for them, historically.
  • The second and the third are not INET4-compatible.
Comment by Alexander Barkov [ 2022-04-27 ]

Notice the comment in the test:

--echo # This is not a text notation: it is a binary input only looking like text notation
SELECT id, length(a), a, IS_IPV4_MAPPED(BINARY a) FROM t1 ORDER BY id;
SELECT id, length(a), a, IS_IPV4_COMPAT(BINARY a) FROM t1 ORDER BY id;

Generated at Thu Feb 08 09:59:31 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.