89
89
#define FORMAT_IPV4 4
90
90
#define FORMAT_IPV6 6
91
91
92
- static int _php_filter_validate_ipv6 (char * str , size_t str_len );
92
+ static int _php_filter_validate_ipv6 (char * str , size_t str_len , int ip [ 8 ] );
93
93
94
94
static int php_filter_parse_int (const char * str , size_t str_len , zend_long * ret ) { /* {{{ */
95
95
zend_long ctx_value ;
@@ -605,7 +605,7 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
605
605
t = e - 1 ;
606
606
607
607
/* An IPv6 enclosed by square brackets is a valid hostname */
608
- if (* s == '[' && * t == ']' && _php_filter_validate_ipv6 ((s + 1 ), l - 2 )) {
608
+ if (* s == '[' && * t == ']' && _php_filter_validate_ipv6 ((s + 1 ), l - 2 , NULL )) {
609
609
php_url_free (url );
610
610
return ;
611
611
}
@@ -745,11 +745,11 @@ static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{
745
745
}
746
746
/* }}} */
747
747
748
- static int _php_filter_validate_ipv6 (char * str , size_t str_len ) /* {{{ */
748
+ static int _php_filter_validate_ipv6 (char * str , size_t str_len , int ip [ 8 ] ) /* {{{ */
749
749
{
750
- int compressed = 0 ;
750
+ int compressed_pos = -1 ;
751
751
int blocks = 0 ;
752
- int n ;
752
+ int num , n , i ;
753
753
char * ipv4 ;
754
754
char * end ;
755
755
int ip4elm [4 ];
@@ -792,35 +792,67 @@ static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */
792
792
return 0 ;
793
793
}
794
794
if (* str == ':' ) {
795
- if (compressed ) {
795
+ if (compressed_pos >= 0 ) {
796
796
return 0 ;
797
797
}
798
- blocks ++ ; /* :: means 1 or more 16-bit 0 blocks */
799
- compressed = 1 ;
800
-
798
+ if (ip && blocks < 8 ) {
799
+ ip [blocks ] = -1 ;
800
+ }
801
+ compressed_pos = blocks ++ ; /* :: means 1 or more 16-bit 0 blocks */
801
802
if (++ str == end ) {
802
- return (blocks <= 8 );
803
+ if (blocks > 8 ) {
804
+ return 0 ;
805
+ }
806
+ goto fixup_ip ;
803
807
}
804
808
} else if ((str - 1 ) == s ) {
805
809
/* don't allow leading : without another : following */
806
810
return 0 ;
807
811
}
808
812
}
809
- n = 0 ;
810
- while ((str < end ) &&
811
- ((* str >= '0' && * str <= '9' ) ||
812
- (* str >= 'a' && * str <= 'f' ) ||
813
- (* str >= 'A' && * str <= 'F' ))) {
813
+ num = n = 0 ;
814
+ while (str < end ) {
815
+ if (* str >= '0' && * str <= '9' ) {
816
+ num = 16 * num + (* str - '0' );
817
+ } else if (* str >= 'a' && * str <= 'f' ) {
818
+ num = 16 * num + (* str - 'a' ) + 10 ;
819
+ } else if (* str >= 'A' && * str <= 'F' ) {
820
+ num = 16 * num + (* str - 'A' ) + 10 ;
821
+ } else {
822
+ break ;
823
+ }
814
824
n ++ ;
815
825
str ++ ;
816
826
}
827
+ if (ip && blocks < 8 ) {
828
+ ip [blocks ] = num ;
829
+ }
817
830
if (n < 1 || n > 4 ) {
818
831
return 0 ;
819
832
}
820
833
if (++ blocks > 8 )
821
834
return 0 ;
822
835
}
823
- return ((compressed && blocks <= 8 ) || blocks == 8 );
836
+
837
+ fixup_ip :
838
+ if (ip && ipv4 ) {
839
+ for (i = 0 ; i < 5 ; i ++ ) {
840
+ ip [i ] = 0 ;
841
+ }
842
+ ip [i ++ ] = 0xffff ;
843
+ ip [i ++ ] = 256 * ip4elm [0 ] + ip4elm [1 ];
844
+ ip [i ++ ] = 256 * ip4elm [2 ] + ip4elm [3 ];
845
+ } else if (ip && compressed_pos >= 0 && blocks <= 8 ) {
846
+ int offset = 8 - blocks ;
847
+ for (i = 7 ; i > compressed_pos + offset ; i -- ) {
848
+ ip [i ] = ip [i - offset ];
849
+ }
850
+ for (i = compressed_pos + offset ; i >= compressed_pos ; i -- ) {
851
+ ip [i ] = 0 ;
852
+ }
853
+ }
854
+
855
+ return (compressed_pos >= 0 && blocks <= 8 ) || blocks == 8 ;
824
856
}
825
857
/* }}} */
826
858
@@ -831,7 +863,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
831
863
* allow_ipv4 and allow_ipv6 flags flag are used, then the first dot or
832
864
* colon determine the format */
833
865
834
- int ip [4 ];
866
+ int ip [8 ];
835
867
int mode ;
836
868
837
869
if (memchr (Z_STRVAL_P (value ), ':' , Z_STRLEN_P (value ))) {
@@ -882,49 +914,25 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
882
914
case FORMAT_IPV6 :
883
915
{
884
916
int res = 0 ;
885
- res = _php_filter_validate_ipv6 (Z_STRVAL_P (value ), Z_STRLEN_P (value ));
917
+ res = _php_filter_validate_ipv6 (Z_STRVAL_P (value ), Z_STRLEN_P (value ), ip );
886
918
if (res < 1 ) {
887
919
RETURN_VALIDATION_FAILED
888
920
}
889
921
/* Check flags */
890
922
if (flags & FILTER_FLAG_NO_PRIV_RANGE ) {
891
- if (Z_STRLEN_P ( value ) >=2 && (! strncasecmp ( "FC" , Z_STRVAL_P ( value ), 2 ) || ! strncasecmp ( "FD" , Z_STRVAL_P ( value ), 2 )) ) {
923
+ if (ip [ 0 ] >= 0xfc00 && ip [ 0 ] <= 0xfdff ) {
892
924
RETURN_VALIDATION_FAILED
893
925
}
894
926
}
895
927
if (flags & FILTER_FLAG_NO_RES_RANGE ) {
896
- switch (Z_STRLEN_P (value )) {
897
- case 1 : case 0 :
898
- break ;
899
- case 2 :
900
- if (!strcmp ("::" , Z_STRVAL_P (value ))) {
901
- RETURN_VALIDATION_FAILED
902
- }
903
- break ;
904
- case 3 :
905
- if (!strcmp ("::1" , Z_STRVAL_P (value )) || !strcmp ("5f:" , Z_STRVAL_P (value ))) {
906
- RETURN_VALIDATION_FAILED
907
- }
908
- break ;
909
- default :
910
- if (Z_STRLEN_P (value ) >= 5 ) {
911
- if (
912
- !strncasecmp ("fe8" , Z_STRVAL_P (value ), 3 ) ||
913
- !strncasecmp ("fe9" , Z_STRVAL_P (value ), 3 ) ||
914
- !strncasecmp ("fea" , Z_STRVAL_P (value ), 3 ) ||
915
- !strncasecmp ("feb" , Z_STRVAL_P (value ), 3 )
916
- ) {
917
- RETURN_VALIDATION_FAILED
918
- }
919
- }
920
- if (
921
- (Z_STRLEN_P (value ) >= 9 && !strncasecmp ("2001:0db8" , Z_STRVAL_P (value ), 9 )) ||
922
- (Z_STRLEN_P (value ) >= 2 && !strncasecmp ("5f" , Z_STRVAL_P (value ), 2 )) ||
923
- (Z_STRLEN_P (value ) >= 4 && !strncasecmp ("3ff3" , Z_STRVAL_P (value ), 4 )) ||
924
- (Z_STRLEN_P (value ) >= 8 && !strncasecmp ("2001:001" , Z_STRVAL_P (value ), 8 ))
925
- ) {
926
- RETURN_VALIDATION_FAILED
927
- }
928
+ if ((ip [0 ] == 0 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] == 0
929
+ && ip [4 ] == 0 && ip [5 ] == 0 && ip [6 ] == 0 && (ip [7 ] == 0 || ip [7 ] == 1 ))
930
+ || (ip [0 ] == 0x5f )
931
+ || (ip [0 ] >= 0xfe80 && ip [0 ] <= 0xfebf )
932
+ || ((ip [0 ] == 0x2001 && ip [1 ] == 0x0db8 ) || (ip [1 ] >= 0x0010 && ip [1 ] <= 0x001f ))
933
+ || (ip [0 ] == 0x3ff3 )
934
+ ) {
935
+ RETURN_VALIDATION_FAILED
928
936
}
929
937
}
930
938
}
0 commit comments