Edit report at http://bugs.php.net/bug.php?id=50117&edit=1

 ID:                 50117
 Comment by:         dominic at sayers dot cc
 Reported by:        crisp at xs4all dot nl
 Summary:            IPv6 validation errors
 Status:             Open
 Type:               Bug
 Package:            Filter related
 Operating System:   *
 PHP Version:        5.*, 6
 Block user comment: N

 New Comment:

The authority on text representation of IPv6 addresses is RFC 4291 (I
think). 

This authority is accepted by the authors of RFC 5952 who quote RFC 3986
only in 

the context of associating port numbers with IPv6 addresses.



The first three examples given are valid according to RFC 4291, but in a
form 

deprecated by RFC 5952. The Robustness Principle suggests we should
accept them 

from others but not generate IPv6 addresses in this form ourselves.
Therefore 

validating these addresses depends on the context - are we checking to
see if we 

can possibly use them or are we checking to see we are generating
absolutely 

spotless addresses ourselves?



The 4th & 5th examples given are also valid according to RFC 4291. In
fact this 

RFC contains an example in exactly the same format in 

http://tools.ietf.org/html/rfc4291#section-2.2



As it stands all 5 examples are valid according to RFC 4291 but none of
them 

complies with RFC 5952.



The RFC 5952 recommendation for them would be



a:b:c:d:e:0:1.2.3.4

::a:b:c:d:e:f

0:a:b:c:d:e:f:0

::1.2.3.4

::255.255.255.255


Previous Comments:
------------------------------------------------------------------------
[2009-11-09 23:38:34] crisp at xs4all dot nl

I checked the sourcecode for the IPv6 validation and being based on
tokenization instead of using regular expressions I think I can offer
some guidance. I don't know C very well, but this is how I'd do it in
PHP itself:



function validateIPv6($IP)

{

        $len = strlen($IP);

        $octets = 8;

        $compressed = false;



        $i = 0;

        $c = $IP[0];

        while ($i < $len)

        {

                if ($c == ':')

                {

                        $i++;

                        if ($i < $len)

                        {

                                $c = $IP[$i];

                                if ($c == ':')

                                {

                                        if (!$compressed)

                                        {

                                                $octets--;

                                                $compressed = true;

                                                $i++;

                                        }

                                        else

                                        {

                                                return false;

                                        }

                                }

                                elseif ($i == 1)

                                {

                                        return false;

                                }

                        }

                        else

                        {

                                return false;

                        }

                }



                if ($i < $len)

                {

                        $n = 0;



                        do

                        {

                                $c = $IP[$i];



                                if (    ($c >= '0' && $c <= '9')

                                        || ($c >= 'a' && $c <= 'f')

                                        || ($c >= 'A' && $c <= 'F')

                                )

                                {

                                        $n++;

                                        $i++;

                                }

                                elseif ($c == ':')

                                {

                                        if ($n < 1 || $n > 4)

                                                return false;



                                        break;

                                }

                                elseif ($c == '.' && validateIPv4(substr($IP, 
$i - $n)))

                                {

                                        $octets--;

                                        break;

                                }

                                else

                                {

                                        return false;

                                }

                        }

                        while ($i < $len);



                        $octets--;

                }

        }



        return ($octets == 0 || ($compressed && $octets > 0));

}



offcourse validateIPv4() should be fixed as well (not allow leading
zeros), and you might want to add early bail-outs like when the string
doesn't have any ':' characters, but I'll leave that all up to you

------------------------------------------------------------------------
[2009-11-09 20:53:02] crisp at xs4all dot nl

Using 5.3.2-dev almost the same results:



valid addresses marked as invalid:

a:b:c:d:e::1.2.3.4

::0:a:b:c:d:e:f

0:a:b:c:d:e:f::



invalid address marked as valid:

::01.02.03.04



So basically it resolves just one of the cases and is still far from
RFC-compliant

------------------------------------------------------------------------
[2009-11-09 00:09:57] crisp at xs4all dot nl

Description:
------------
The following valid IPv6 addresses are being marked as 'invalid':



a:b:c:d:e::1.2.3.4

::0:a:b:c:d:e:f

0:a:b:c:d:e:f::



The following invalid IPv6 addresses are being marked as 'valid':



::01.02.03.04

0:0:0:255.255.255.255



please refer to the ABNF in
http://rfc-ref.org/RFC-TEXTS/3986/chapter11.html

Reproduce code:
---------------
function validateIPv6($IP)

{

        return filter_var($IP, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);

}



substitute $IP with the IPv6 addresses mentioned above



------------------------------------------------------------------------



-- 
Edit this bug report at http://bugs.php.net/bug.php?id=50117&edit=1

Reply via email to