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 ;
@@ -613,7 +613,7 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
613
613
t = e - 1 ;
614
614
615
615
/* An IPv6 enclosed by square brackets is a valid hostname */
616
- if (* s == '[' && * t == ']' && _php_filter_validate_ipv6 ((s + 1 ), l - 2 )) {
616
+ if (* s == '[' && * t == ']' && _php_filter_validate_ipv6 ((s + 1 ), l - 2 , NULL )) {
617
617
php_url_free (url );
618
618
return ;
619
619
}
@@ -753,11 +753,11 @@ static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{
753
753
}
754
754
/* }}} */
755
755
756
- static int _php_filter_validate_ipv6 (char * str , size_t str_len ) /* {{{ */
756
+ static int _php_filter_validate_ipv6 (char * str , size_t str_len , int ip [ 8 ] ) /* {{{ */
757
757
{
758
- int compressed = 0 ;
758
+ int compressed_pos = -1 ;
759
759
int blocks = 0 ;
760
- int n ;
760
+ int num , n , i ;
761
761
char * ipv4 ;
762
762
char * end ;
763
763
int ip4elm [4 ];
@@ -800,35 +800,67 @@ static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */
800
800
return 0 ;
801
801
}
802
802
if (* str == ':' ) {
803
- if (compressed ) {
803
+ if (compressed_pos >= 0 ) {
804
804
return 0 ;
805
805
}
806
- blocks ++ ; /* :: means 1 or more 16-bit 0 blocks */
807
- compressed = 1 ;
808
-
806
+ if (ip && blocks < 8 ) {
807
+ ip [blocks ] = -1 ;
808
+ }
809
+ compressed_pos = blocks ++ ; /* :: means 1 or more 16-bit 0 blocks */
809
810
if (++ str == end ) {
810
- return (blocks <= 8 );
811
+ if (blocks > 8 ) {
812
+ return 0 ;
813
+ }
814
+ goto fixup_ip ;
811
815
}
812
816
} else if ((str - 1 ) == s ) {
813
817
/* don't allow leading : without another : following */
814
818
return 0 ;
815
819
}
816
820
}
817
- n = 0 ;
818
- while ((str < end ) &&
819
- ((* str >= '0' && * str <= '9' ) ||
820
- (* str >= 'a' && * str <= 'f' ) ||
821
- (* str >= 'A' && * str <= 'F' ))) {
821
+ num = n = 0 ;
822
+ while (str < end ) {
823
+ if (* str >= '0' && * str <= '9' ) {
824
+ num = 16 * num + (* str - '0' );
825
+ } else if (* str >= 'a' && * str <= 'f' ) {
826
+ num = 16 * num + (* str - 'a' ) + 10 ;
827
+ } else if (* str >= 'A' && * str <= 'F' ) {
828
+ num = 16 * num + (* str - 'A' ) + 10 ;
829
+ } else {
830
+ break ;
831
+ }
822
832
n ++ ;
823
833
str ++ ;
824
834
}
835
+ if (ip && blocks < 8 ) {
836
+ ip [blocks ] = num ;
837
+ }
825
838
if (n < 1 || n > 4 ) {
826
839
return 0 ;
827
840
}
828
841
if (++ blocks > 8 )
829
842
return 0 ;
830
843
}
831
- return ((compressed && blocks <= 8 ) || blocks == 8 );
844
+
845
+ fixup_ip :
846
+ if (ip && ipv4 ) {
847
+ for (i = 0 ; i < 5 ; i ++ ) {
848
+ ip [i ] = 0 ;
849
+ }
850
+ ip [i ++ ] = 0xffff ;
851
+ ip [i ++ ] = 256 * ip4elm [0 ] + ip4elm [1 ];
852
+ ip [i ++ ] = 256 * ip4elm [2 ] + ip4elm [3 ];
853
+ } else if (ip && compressed_pos >= 0 && blocks <= 8 ) {
854
+ int offset = 8 - blocks ;
855
+ for (i = 7 ; i > compressed_pos + offset ; i -- ) {
856
+ ip [i ] = ip [i - offset ];
857
+ }
858
+ for (i = compressed_pos + offset ; i >= compressed_pos ; i -- ) {
859
+ ip [i ] = 0 ;
860
+ }
861
+ }
862
+
863
+ return (compressed_pos >= 0 && blocks <= 8 ) || blocks == 8 ;
832
864
}
833
865
/* }}} */
834
866
@@ -839,7 +871,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
839
871
* allow_ipv4 and allow_ipv6 flags flag are used, then the first dot or
840
872
* colon determine the format */
841
873
842
- int ip [4 ];
874
+ int ip [8 ];
843
875
int mode ;
844
876
845
877
if (memchr (Z_STRVAL_P (value ), ':' , Z_STRLEN_P (value ))) {
@@ -890,52 +922,28 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
890
922
case FORMAT_IPV6 :
891
923
{
892
924
int res = 0 ;
893
- res = _php_filter_validate_ipv6 (Z_STRVAL_P (value ), Z_STRLEN_P (value ));
925
+ res = _php_filter_validate_ipv6 (Z_STRVAL_P (value ), Z_STRLEN_P (value ), ip );
894
926
if (res < 1 ) {
895
927
RETURN_VALIDATION_FAILED
896
928
}
897
929
/* Check flags */
898
930
if (flags & FILTER_FLAG_NO_PRIV_RANGE ) {
899
- if (Z_STRLEN_P ( value ) >=2 && (! strncasecmp ( "FC" , Z_STRVAL_P ( value ), 2 ) || ! strncasecmp ( "FD" , Z_STRVAL_P ( value ), 2 )) ) {
931
+ if (ip [ 0 ] >= 0xfc00 && ip [ 0 ] <= 0xfdff ) {
900
932
RETURN_VALIDATION_FAILED
901
933
}
902
934
}
903
935
if (flags & FILTER_FLAG_NO_RES_RANGE ) {
904
- switch (Z_STRLEN_P (value )) {
905
- case 1 : case 0 :
906
- break ;
907
- case 2 :
908
- if (zend_string_equals_literal (Z_STR_P (value ), "::" )) {
909
- RETURN_VALIDATION_FAILED
910
- }
911
- break ;
912
- case 3 :
913
- if (zend_string_equals_literal (Z_STR_P (value ), "::1" ) || zend_string_equals_literal (Z_STR_P (value ), "5f:" )) {
914
- RETURN_VALIDATION_FAILED
915
- }
916
- break ;
917
- default :
918
- if (Z_STRLEN_P (value ) >= 5 ) {
919
- if (
920
- !strncasecmp ("fe8" , Z_STRVAL_P (value ), 3 ) ||
921
- !strncasecmp ("fe9" , Z_STRVAL_P (value ), 3 ) ||
922
- !strncasecmp ("fea" , Z_STRVAL_P (value ), 3 ) ||
923
- !strncasecmp ("feb" , Z_STRVAL_P (value ), 3 )
936
+ if ((ip [0 ] == 0 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] == 0
937
+ && ip [4 ] == 0 && ip [5 ] == 0 && ip [6 ] == 0 && (ip [7 ] == 0 || ip [7 ] == 1 ))
938
+ || (ip [0 ] == 0x5f )
939
+ || (ip [0 ] >= 0xfe80 && ip [0 ] <= 0xfebf )
940
+ || ((ip [0 ] == 0x2001 && ip [1 ] == 0x0db8 ) || (ip [1 ] >= 0x0010 && ip [1 ] <= 0x001f ))
941
+ || (ip [0 ] == 0x3ff3 )
924
942
) {
925
943
RETURN_VALIDATION_FAILED
926
944
}
927
945
}
928
- if (
929
- (Z_STRLEN_P (value ) >= 9 && !strncasecmp ("2001:0db8" , Z_STRVAL_P (value ), 9 )) ||
930
- (Z_STRLEN_P (value ) >= 2 && !strncasecmp ("5f" , Z_STRVAL_P (value ), 2 )) ||
931
- (Z_STRLEN_P (value ) >= 4 && !strncasecmp ("3ff3" , Z_STRVAL_P (value ), 4 )) ||
932
- (Z_STRLEN_P (value ) >= 8 && !strncasecmp ("2001:001" , Z_STRVAL_P (value ), 8 ))
933
- ) {
934
- RETURN_VALIDATION_FAILED
935
946
}
936
- }
937
- }
938
- }
939
947
break ;
940
948
}
941
949
}
0 commit comments