]> granicus.if.org Git - php/commitdiff
- Fixed the filter extension accepting IPv4 octets with a leading 0 as that
authorGustavo André dos Santos Lopes <cataphract@php.net>
Mon, 8 Nov 2010 04:36:15 +0000 (04:36 +0000)
committerGustavo André dos Santos Lopes <cataphract@php.net>
Mon, 8 Nov 2010 04:36:15 +0000 (04:36 +0000)
  belongs to the unsupported "dotted octal" 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 ::).

ext/filter/logical_filters.c
ext/filter/tests/030.phpt

index a1e6aee8fab8fc9d58595dacc15c1cffe2ae70e2..6bf83b9cef20ae12c850b13f76c7507bbfcb5075 100644 (file)
@@ -557,9 +557,11 @@ static int _php_filter_validate_ipv4(char *str, int str_len, int *ip) /* {{{ */
        int n = 0;
 
        while (str < end) {
+               int leading_zero;
                if (*str < '0' || *str > '9') {
                        return 0;
                }
+               leading_zero = (*str == '0');
                m = 1;
                num = ((*(str++)) - '0');
                while (str < end && (*str >= '0' && *str <= '9')) {
@@ -568,6 +570,10 @@ static int _php_filter_validate_ipv4(char *str, int str_len, int *ip) /* {{{ */
                                return 0;
                        }
                }
+               /* don't allow a leading 0; that introduces octal numbers,
+                * which we don't support */
+               if (leading_zero && (num != 0 || m > 1))
+                       return 0;
                ip[n++] = num;
                if (n == 4) {
                        return str == end;
@@ -582,7 +588,7 @@ static int _php_filter_validate_ipv4(char *str, int str_len, int *ip) /* {{{ */
 static int _php_filter_validate_ipv6(char *str, int str_len TSRMLS_DC) /* {{{ */
 {
        int compressed = 0;
-       int blocks = 8;
+       int blocks = 0;
        int n;
        char *ipv4;
        char *end;
@@ -603,32 +609,40 @@ static int _php_filter_validate_ipv6(char *str, int str_len TSRMLS_DC) /* {{{ */
                if (!_php_filter_validate_ipv4(ipv4, (str_len - (ipv4 - str)), ip4elm)) {
                        return 0;
                }
-               str_len = (ipv4 - str) - 1;
-               if (str_len == 1) {
-                       return *str == ':';
+
+               str_len = ipv4 - str; /* length excluding ipv4 */
+               if (str_len < 2) {
+                       return 0;
+               }
+
+               if (ipv4[-2] != ':') {
+                       /* don't include : before ipv4 unless it's a :: */
+                       str_len--;
                }
-               blocks = 6;
+
+               blocks = 2;
        }
 
        end = str + str_len;
 
        while (str < end) {
                if (*str == ':') {
-                       if (--blocks == 0) {
-                               return 0;
-                       }                       
                        if (++str >= end) {
+                               /* cannot end in : without previous : */
                                return 0;
                        }
                        if (*str == ':') {
-                               if (compressed || --blocks == 0) {
+                               if (compressed) {
                                        return 0;
-                               }                       
-                               if (++str == end) {
-                                       return 1;
                                }
+                               blocks++; /* :: means 1 or more 16-bit 0 blocks */
                                compressed = 1;
+
+                               if (++str == end) {
+                                       return (blocks <= 8);
+                               }
                        } else if ((str - 1) == s) {
+                               /* dont allow leading : without another : following */
                                return 0;
                        }                               
                }
@@ -643,8 +657,10 @@ static int _php_filter_validate_ipv6(char *str, int str_len TSRMLS_DC) /* {{{ */
                if (n < 1 || n > 4) {
                        return 0;
                }
+               if (++blocks > 8)
+                       return 0;
        }
-       return (compressed || blocks == 1);
+       return ((compressed && blocks <= 8) || blocks == 8);
 }
 /* }}} */
 
index d3466f5b42c68c7832d7738753c93f8d6a5c282f..c5af15e15264853de314ef33185321c2978851bd 100644 (file)
@@ -5,35 +5,56 @@ filter_var() and IPv6
 --FILE--
 <?php
 $ipv6_test = array(
-       "::127.0.0.1"                           => true,
-       "FF01::101:127.0.1"             => false,
-       "FF01:0:0:0:101:127.0.1.1"  => false,
-       "FF01:0:0:0:237:101:127.0.1.1"  => true,
-       "FF01::101"                                     => true,
-       "A1080::8:800:200C:417A"        => false,
-       "1080::8:Z00:200C:417A"         => false,
-       "FF01::101::1"                          => false,
-       "1080::8:800:200C:417A"         => true,
-       "1080:0:0:0:8:800:200C:417A" => true,
+       "::127.0.0.1"                                   => true,
+       "FF01::101:127.0.1"                     => false,
+       "FF01:0:0:0:101:127.0.1.1"              => false,
+       "FF01:0:0:0:237:101:127.0.1.1"  => true,
+       "FF01::101"                                             => true,
+       "A1080::8:800:200C:417A"                => false,
+       "1080::8:Z00:200C:417A"                 => false,
+       "FF01::101::1"                                  => false,
+       "1080::8:800:200C:417A"                 => true,
+       "1080:0:0:0:8:800:200C:417A"    => true,
        "2001:ec8:1:1:1:1:1:1"                  => true,
        "ffff::FFFF:129.144.52.38"              => true,
        "::ffff:1.2.3.4"                                => true,
-       "0:0:0:0:0:FFFF:129.144.52.38" => true,
-       "0:0:0:0:0:0:13.1.68.3"         => true,
-       "::13.1.68.3"                           => true,
-    "::FFFF:129.144.52.38"             => true,
+       "0:0:0:0:0:FFFF:129.144.52.38"  => true,
+       "0:0:0:0:0:0:13.1.68.3"                 => true,
+    "0:0:0:0:0:0:0:13.1.68.3"          => false,
+       "::13.1.68.3"                                   => true,
+    "::FFFF:129.144.52.38"                     => true,
+    
     "1:2:3:4:5:6::129.144.52.38"       => false,
     "::1:2:3:4:5:6:129.144.52.38"      => false,
     "1:2:3::4:5:6:129.144.52.38"       => false,
-    "1:2:3:4:5:6:7:8::"                                => false,
-    "::1:2:3:4:5:6:7:8"                                => false,
+    
     "1:2:3:4::5:6:7:8"                         => false,
+    "::1:2:3:4:5:6:7"                          => true,
+    "::1:2:3:4:5:6:7:8"                                => false,
+    "1:2:3:4:5:6:7::"                          => true,
+    "1:2:3:4:5:6:7:8::"                                => false,
+    "1:2:3:4:5:6:7::8"                         => false,
+    
+    "1:2:3:4:5:6:7:8g"                         => false,
+    "1:2:3:4:5:6:7:g"                          => false,
+    "1:2:3:4:5g:6:7:8"                         => false,
+    
+    'a:b:c:d:e::1.2.3.4'                       => true,
+    '::0:a:b:c:d:e:f'                          => true,
+    '0:a:b:c:d:e:f::'                          => true,
+    ':::1.2.3.4'                                       => false,
+    '8:::1.2.3.4'                                      => false,
+    '::01.02.03.04'                                    => false,
+    '::1.00.3.4'                                       => false,
+    '0:0:0:255.255.255.255'                    => false,
+    '0:0:0::255.255.255.255'           => true,
 );
 foreach ($ipv6_test as $ip => $exp) {
        $out = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
        $out = (int) ($out === false ? 0 : 1);
        if ($exp != $out) {
-               echo "$ip failed\n";
+               echo "$ip failed (expected ", $exp?"true":"false", ", got ", 
+            $out?"true":"false", ")\n";
        }
 }