Fix incorrect /\(dir\)/ pattern match.
@@ -3718,58 +3718,39 @@ | ||
3718 | 3718 | { |
3719 | 3719 | const char *f_delimiter; |
3720 | 3720 | const char *p_delimiter; |
3721 | - char recursive_end; | |
3722 | 3721 | while (*f && *p) { |
3723 | - f_delimiter = strchr(f, '/'); | |
3722 | + f_delimiter = strchr(f + 1, '/'); | |
3724 | 3723 | if (!f_delimiter) |
3725 | 3724 | f_delimiter = f + strlen(f); |
3726 | - p_delimiter = strchr(p, '/'); | |
3725 | + p_delimiter = strchr(p + 1, '/'); | |
3727 | 3726 | if (!p_delimiter) |
3728 | 3727 | p_delimiter = p + strlen(p); |
3729 | - if (*p == '\\') { | |
3730 | - if (*(p + 1) == '{') { | |
3731 | - recursive_end = '}'; | |
3732 | - goto recursive; | |
3728 | + if (*p == '/' && *(p + 1) == '\\') { | |
3729 | + if (*(p + 2) == '(') { | |
3730 | + /* Check zero repetition. */ | |
3731 | + if (cs_path_matches_pattern2(f, p_delimiter)) | |
3732 | + return true; | |
3733 | + /* Check one or more repetition. */ | |
3734 | + goto repetition; | |
3733 | 3735 | } |
3734 | - if (*(p + 1) == '(') { | |
3735 | - recursive_end = ')'; | |
3736 | - goto recursive; | |
3737 | - } | |
3736 | + if (*(p + 2) == '{') | |
3737 | + goto repetition; | |
3738 | 3738 | } |
3739 | + if ((*f == '/' || *p == '/') && *f++ != *p++) | |
3740 | + return false; | |
3739 | 3741 | if (!cs_file_matches_pattern(f, f_delimiter, p, p_delimiter)) |
3740 | 3742 | return false; |
3741 | 3743 | f = f_delimiter; |
3742 | - if (*f) | |
3743 | - f++; | |
3744 | 3744 | p = p_delimiter; |
3745 | - if (*p) | |
3746 | - p++; | |
3747 | 3745 | } |
3748 | 3746 | /* Ignore trailing "\*" and "\@" in @pattern. */ |
3749 | - while (*p == '\\' && | |
3750 | - (*(p + 1) == '*' || *(p + 1) == '@')) | |
3747 | + while (*p == '\\' && (*(p + 1) == '*' || *(p + 1) == '@')) | |
3751 | 3748 | p += 2; |
3752 | 3749 | return !*f && !*p; |
3753 | -recursive: | |
3754 | - /* | |
3755 | - * The "\{" or "\(" pattern is permitted only after '/' character. | |
3756 | - * This guarantees that below "*(p - 1)" is safe. | |
3757 | - * Also, the "\}" or "\)" pattern is permitted only before '/' | |
3758 | - * character so that "\{" + "\}" or "\(" + "\)" pair will not break | |
3759 | - * the "\-" operator. | |
3760 | - */ | |
3761 | - if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' || | |
3762 | - *(p_delimiter - 1) != recursive_end || *(p_delimiter - 2) != '\\') | |
3763 | - return false; /* Bad pattern. */ | |
3764 | - if (recursive_end == ')') { | |
3765 | - /* Check zero repetition. */ | |
3766 | - if (cs_path_matches_pattern2(f, p_delimiter + 1)) | |
3767 | - return true; | |
3768 | - /* Fall back to one or more repetition. */ | |
3769 | - } | |
3750 | +repetition: | |
3770 | 3751 | do { |
3771 | 3752 | /* Compare current component with pattern. */ |
3772 | - if (!cs_file_matches_pattern(f, f_delimiter, p + 2, | |
3753 | + if (!cs_file_matches_pattern(f + 1, f_delimiter, p + 3, | |
3773 | 3754 | p_delimiter - 2)) |
3774 | 3755 | break; |
3775 | 3756 | /* Proceed to next component. */ |
@@ -3776,11 +3757,10 @@ | ||
3776 | 3757 | f = f_delimiter; |
3777 | 3758 | if (!*f) |
3778 | 3759 | break; |
3779 | - f++; | |
3780 | 3760 | /* Continue comparison. */ |
3781 | - if (cs_path_matches_pattern2(f, p_delimiter + 1)) | |
3761 | + if (cs_path_matches_pattern2(f, p_delimiter)) | |
3782 | 3762 | return true; |
3783 | - f_delimiter = strchr(f, '/'); | |
3763 | + f_delimiter = strchr(f + 1, '/'); | |
3784 | 3764 | } while (f_delimiter); |
3785 | 3765 | return false; /* Not matched. */ |
3786 | 3766 | } |
@@ -3823,23 +3803,11 @@ | ||
3823 | 3803 | if (len == pattern->total_len) |
3824 | 3804 | return !cs_pathcmp(filename, pattern); |
3825 | 3805 | /* Compare the initial length without patterns. */ |
3826 | - if (strncmp(f, p, len)) | |
3827 | - return false; | |
3828 | - f += len; | |
3829 | - p += len; | |
3830 | - /* Compare the last component first. */ | |
3831 | - { | |
3832 | - const char *f2 = strrchr(f, '/'); | |
3833 | - const char *p2 = strrchr(p, '/'); | |
3834 | - if (!f2++) | |
3835 | - f2 = f; | |
3836 | - if (!p2++) | |
3837 | - p2 = p; | |
3838 | - if (!cs_file_matches_pattern(f2, filename->name | |
3839 | - + filename->total_len, | |
3840 | - p2, pattern->name | |
3841 | - + pattern->total_len)) | |
3806 | + if (len) { | |
3807 | + if (strncmp(f, p, len)) | |
3842 | 3808 | return false; |
3809 | + f += len - 1; | |
3810 | + p += len - 1; | |
3843 | 3811 | } |
3844 | 3812 | return cs_path_matches_pattern2(f, p); |
3845 | 3813 | } |
@@ -3060,58 +3060,39 @@ | ||
3060 | 3060 | { |
3061 | 3061 | const char *f_delimiter; |
3062 | 3062 | const char *p_delimiter; |
3063 | - char recursive_end; | |
3064 | 3063 | while (*f && *p) { |
3065 | - f_delimiter = strchr(f, '/'); | |
3064 | + f_delimiter = strchr(f + 1, '/'); | |
3066 | 3065 | if (!f_delimiter) |
3067 | 3066 | f_delimiter = f + strlen(f); |
3068 | - p_delimiter = strchr(p, '/'); | |
3067 | + p_delimiter = strchr(p + 1, '/'); | |
3069 | 3068 | if (!p_delimiter) |
3070 | 3069 | p_delimiter = p + strlen(p); |
3071 | - if (*p == '\\') { | |
3072 | - if (*(p + 1) == '{') { | |
3073 | - recursive_end = '}'; | |
3074 | - goto recursive; | |
3070 | + if (*p == '/' && *(p + 1) == '\\') { | |
3071 | + if (*(p + 2) == '(') { | |
3072 | + /* Check zero repetition. */ | |
3073 | + if (cs_path_matches_pattern2(f, p_delimiter)) | |
3074 | + return true; | |
3075 | + /* Check one or more repetition. */ | |
3076 | + goto repetition; | |
3075 | 3077 | } |
3076 | - if (*(p + 1) == '(') { | |
3077 | - recursive_end = ')'; | |
3078 | - goto recursive; | |
3079 | - } | |
3078 | + if (*(p + 2) == '{') | |
3079 | + goto repetition; | |
3080 | 3080 | } |
3081 | + if ((*f == '/' || *p == '/') && *f++ != *p++) | |
3082 | + return false; | |
3081 | 3083 | if (!cs_file_matches_pattern(f, f_delimiter, p, p_delimiter)) |
3082 | 3084 | return false; |
3083 | 3085 | f = f_delimiter; |
3084 | - if (*f) | |
3085 | - f++; | |
3086 | 3086 | p = p_delimiter; |
3087 | - if (*p) | |
3088 | - p++; | |
3089 | 3087 | } |
3090 | 3088 | /* Ignore trailing "\*" and "\@" in @pattern. */ |
3091 | - while (*p == '\\' && | |
3092 | - (*(p + 1) == '*' || *(p + 1) == '@')) | |
3089 | + while (*p == '\\' && (*(p + 1) == '*' || *(p + 1) == '@')) | |
3093 | 3090 | p += 2; |
3094 | 3091 | return !*f && !*p; |
3095 | -recursive: | |
3096 | - /* | |
3097 | - * The "\{" or "\(" pattern is permitted only after '/' character. | |
3098 | - * This guarantees that below "*(p - 1)" is safe. | |
3099 | - * Also, the "\}" or "\)" pattern is permitted only before '/' | |
3100 | - * character so that "\{" + "\}" or "\(" + "\)" pair will not break | |
3101 | - * the "\-" operator. | |
3102 | - */ | |
3103 | - if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' || | |
3104 | - *(p_delimiter - 1) != recursive_end || *(p_delimiter - 2) != '\\') | |
3105 | - return false; /* Bad pattern. */ | |
3106 | - if (recursive_end == ')') { | |
3107 | - /* Check zero repetition. */ | |
3108 | - if (cs_path_matches_pattern2(f, p_delimiter + 1)) | |
3109 | - return true; | |
3110 | - /* Fall back to one or more repetition. */ | |
3111 | - } | |
3092 | +repetition: | |
3112 | 3093 | do { |
3113 | 3094 | /* Compare current component with pattern. */ |
3114 | - if (!cs_file_matches_pattern(f, f_delimiter, p + 2, | |
3095 | + if (!cs_file_matches_pattern(f + 1, f_delimiter, p + 3, | |
3115 | 3096 | p_delimiter - 2)) |
3116 | 3097 | break; |
3117 | 3098 | /* Proceed to next component. */ |
@@ -3118,11 +3099,10 @@ | ||
3118 | 3099 | f = f_delimiter; |
3119 | 3100 | if (!*f) |
3120 | 3101 | break; |
3121 | - f++; | |
3122 | 3102 | /* Continue comparison. */ |
3123 | - if (cs_path_matches_pattern2(f, p_delimiter + 1)) | |
3103 | + if (cs_path_matches_pattern2(f, p_delimiter)) | |
3124 | 3104 | return true; |
3125 | - f_delimiter = strchr(f, '/'); | |
3105 | + f_delimiter = strchr(f + 1, '/'); | |
3126 | 3106 | } while (f_delimiter); |
3127 | 3107 | return false; /* Not matched. */ |
3128 | 3108 | } |
@@ -3165,23 +3145,11 @@ | ||
3165 | 3145 | if (len == pattern->total_len) |
3166 | 3146 | return !cs_pathcmp(filename, pattern); |
3167 | 3147 | /* Compare the initial length without patterns. */ |
3168 | - if (strncmp(f, p, len)) | |
3169 | - return false; | |
3170 | - f += len; | |
3171 | - p += len; | |
3172 | - /* Compare the last component first. */ | |
3173 | - { | |
3174 | - const char *f2 = strrchr(f, '/'); | |
3175 | - const char *p2 = strrchr(p, '/'); | |
3176 | - if (!f2++) | |
3177 | - f2 = f; | |
3178 | - if (!p2++) | |
3179 | - p2 = p; | |
3180 | - if (!cs_file_matches_pattern(f2, filename->name | |
3181 | - + filename->total_len, | |
3182 | - p2, pattern->name | |
3183 | - + pattern->total_len)) | |
3148 | + if (len) { | |
3149 | + if (strncmp(f, p, len)) | |
3184 | 3150 | return false; |
3151 | + f += len - 1; | |
3152 | + p += len - 1; | |
3185 | 3153 | } |
3186 | 3154 | return cs_path_matches_pattern2(f, p); |
3187 | 3155 | } |