Bug #2310 INET_ATON() handles short-form addresses incorrectly
Submitted: 7 Jan 2004 9:50 Modified: 19 Jan 2004 9:10
Reporter: Jim Winstead Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:4.0.16 OS:Linux (Debian Linux)
Assigned to: Victor Vagin CPU Architecture:Any

[7 Jan 2004 9:50] Jim Winstead
Description:
The INET_ATON() function does not handle addresses of the form 'a.b' and 'a.b.c' correctly.

From the inet_aton() man page on a Linux system:

INTERNET ADDRESSES
     Values specified using the `.' notation take one of the following forms:

           a.b.c.d
           a.b.c
           a.b
           a

     When four parts are specified, each is interpreted as a byte of data and
     assigned, from left to right, to the four bytes of an Internet address.
     Note that when an Internet address is viewed as a 32-bit integer quantity
     on the VAX the bytes referred to above appear as ``d.c.b.a''.  That is,
     VAX bytes are ordered from right to left.

     When a three part address is specified, the last part is interpreted as a
     16-bit quantity and placed in the right-most two bytes of the network
     address.  This makes the three part address format convenient for speci-
     fying Class B network addresses as ``128.net.host''.

     When a two part address is supplied, the last part is interpreted as a
     24-bit quantity and placed in the right most three bytes of the network
     address.  This makes the two part address format convenient for specify-
     ing Class A network addresses as ``net.host''.

     When only one part is given, the value is stored directly in the network
     address without any byte rearrangement.

How to repeat:
mysql> select hex(inet_aton('127.1'));
+-------------------------+
| hex(inet_aton('127.1')) |
+-------------------------+
| 7F01                    |
+-------------------------+

should return 7f000001

mysql> select hex(inet_aton('127.1.1'));
+---------------------------+
| hex(inet_aton('127.1.1')) |
+---------------------------+
| 7F0101                    |
+---------------------------+

should return 7f010001
[13 Jan 2004 2:48] Victor Vagin
Please verify your request more precisely ..
Are there any stadards about it?
Aren't any old users using old behaviour?
Wouldn't it be better to rewrite the manual?

I'm leaving the final decision to monty

Anyway, I've written a patch and if you wish you can use it by yourself:

===== mysql-test/r/func_misc.result 1.9 vs edited =====
*** /tmp/func_misc.result-1.9-13215	Thu Jul  3 16:48:46 2003
--- edited/mysql-test/r/func_misc.result	Tue Jan 13 18:13:11 2004
***************
*** 6,15 ****
  NULL
  select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255");
  inet_aton("255.255.255.255.255")	inet_aton("255.255.1.255")	inet_aton("0.1.255")
! 1099511627775	4294902271	511
  select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511);
  inet_ntoa(1099511627775)	inet_ntoa(4294902271)	inet_ntoa(511)
  NULL	255.255.1.255	0.0.1.255
  select length(format('nan', 2)) > 0;
  length(format('nan', 2)) > 0
  1
--- 6,24 ----
  NULL
  select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255");
  inet_aton("255.255.255.255.255")	inet_aton("255.255.1.255")	inet_aton("0.1.255")
! 1099511627775	4294902271	65791
  select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511);
  inet_ntoa(1099511627775)	inet_ntoa(4294902271)	inet_ntoa(511)
  NULL	255.255.1.255	0.0.1.255
+ select hex(inet_aton('127'));
+ hex(inet_aton('127'))
+ 7F
+ select hex(inet_aton('127.1'));
+ hex(inet_aton('127.1'))
+ 7F000001
+ select hex(inet_aton('127.1.1'));
+ hex(inet_aton('127.1.1'))
+ 7F010001
  select length(format('nan', 2)) > 0;
  length(format('nan', 2)) > 0
  1
===== mysql-test/t/func_misc.test 1.7 vs edited =====
*** /tmp/func_misc.test-1.7-13215	Thu Jul  3 16:48:46 2003
--- edited/mysql-test/t/func_misc.test	Tue Jan 13 18:07:18 2004
***************
*** 8,13 ****
--- 8,17 ----
  select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255");
  select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511);
  
+ select hex(inet_aton('127'));
+ select hex(inet_aton('127.1'));
+ select hex(inet_aton('127.1.1'));
+ 
  #
  # Test for core dump with nan
  #
===== sql/item_func.cc 1.105 vs edited =====
*** /tmp/item_func.cc-1.105-13215	Wed Dec 10 23:26:29 2003
--- edited/sql/item_func.cc	Tue Jan 13 18:12:43 2004
***************
*** 2132,2137 ****
--- 2132,2138 ----
    const char *p,* end;
    char c = '.'; // we mark c to indicate invalid IP in case length is 0
    char buff[36];
+   int dot_count= 0;
  
    String *s,tmp(buff,sizeof(buff));
    if (!(s = args[0]->val_str(&tmp)))		// If null value
***************
*** 2150,2155 ****
--- 2151,2157 ----
      }
      else if (c == '.')
      {
+       dot_count++;
        result= (result << 8) + (ulonglong) byte_result;
        byte_result = 0;
      }
***************
*** 2157,2163 ****
--- 2159,2172 ----
        goto err;					// Invalid character
    }
    if (c != '.')					// IP number can't end on '.'
+   {
+     switch (dot_count)
+     {
+     case 1: result<<= 8;
+     case 2: result<<= 8;
+     }
      return (result << 8) + (ulonglong) byte_result;
+   }
  
  err:
    null_value=1;
[13 Jan 2004 7:40] Victor Vagin
I couldn't find in internet any RFC or other standard (except a lot of manuals) which describe this notation.

However I've made sure that most likely all the unix system support this syntax via libc (http://www.opengroup.org/onlinepubs/007908799/xns/inet_addr.html)..

actaully:

vva@eagle:~/work/BUG_2296 > ping 127.1
PING 127.1 (127.0.0.1): 56 data bytes
......

vva@eagle:~/work/BUG_2296 > ping 127.1.1
PING 127.1.1 (127.1.0.1): 56 data bytes
......

vva@eagle:~/work/BUG_2296 > ping 127
PING 127 (0.0.0.127): 56 data bytes
......
[19 Jan 2004 9:10] Victor Vagin
Thank you for your bug report. This issue has been committed to our
source repository of that product and will be incorporated into the
next release.

If necessary, you can access the source repository and build the latest
available version, including the bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html

Additional info:

Bug was fixed in mysql-4.1