php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #50117 IPv6 validation errors
Submitted: 2009-11-09 00:09 UTC Modified: 2010-11-08 05:39 UTC
Votes:4
Avg. Score:5.0 ± 0.0
Reproduced:4 of 4 (100.0%)
Same Version:4 (100.0%)
Same OS:1 (25.0%)
From: crisp at xs4all dot nl Assigned: cataphract
Status: Closed Package: Filter related
PHP Version: 5.*, 6 OS: *
Private report: No CVE-ID:
 [2009-11-09 00:09 UTC] 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


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-11-09 20:53 UTC] 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 23:38 UTC] 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
 [2010-11-03 14:08 UTC] dominic at sayers dot cc
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
 [2010-11-03 14:12 UTC] dominic at sayers dot cc
Oops. Example 5 is of course invalid. My mind invented a :: when there wasn't one.
 [2010-11-08 05:36 UTC] cataphract@php.net
Automatic comment from SVN on behalf of cataphract
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=305186
Log: - Fixed the filter extension accepting IPv4 octets with a leading 0 as that
  belongs to the unsupported &quot;dotted octal&quot; representation.
- Fixed bug #53236 (problems in the validation of IPv6 addresses with leading
  and trailing :: in the filter extension).
- Fixed bug #50117 (problems in the validation of IPv6 addresses with IPv4
  addresses and ::).
 [2010-11-08 05:39 UTC] cataphract@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: cataphract
 [2010-11-08 05:39 UTC] cataphract@php.net
Fixed for PHP 5.3 and trunk.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 24 21:01:55 2014 UTC