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