| 146 | } |
| 147 | |
| 148 | static bool glob_match(const char *pat, const char *str, |
| 149 | int *budget) { // NOLINT(misc-no-recursion) |
| 150 | if (--*budget <= 0) { |
| 151 | return false; /* budget exhausted — see GI_MATCH_MAX_STEPS */ |
| 152 | } |
| 153 | while (*pat && *str) { |
| 154 | if (pat[0] == '*' && pat[GI_CHAR_IDX1] == '*') { |
| 155 | return glob_match_doublestar(pat, str, budget); |
| 156 | } |
| 157 | |
| 158 | if (*pat == '*') { |
| 159 | return glob_match_star(pat + SKIP_ONE, str, budget); |
| 160 | } |
| 161 | |
| 162 | if (*pat == '?') { |
| 163 | if (*str == '/') { |
| 164 | return false; |
| 165 | } |
| 166 | pat++; |
| 167 | str++; |
| 168 | continue; |
| 169 | } |
| 170 | |
| 171 | if (*pat == '[') { |
| 172 | const char *new_pat = NULL; |
| 173 | if (!glob_match_charclass(pat + SKIP_ONE, *str, &new_pat)) { |
| 174 | return false; |
| 175 | } |
| 176 | pat = new_pat; |
| 177 | str++; |
| 178 | continue; |
| 179 | } |
| 180 | |
| 181 | if (*pat != *str) { |
| 182 | return false; |
| 183 | } |
| 184 | pat++; |
| 185 | str++; |
| 186 | } |
| 187 | |
| 188 | while (*pat == '*') { |
| 189 | pat++; |
| 190 | } |
| 191 | return *pat == '\0' && *str == '\0'; |
| 192 | } |
| 193 | |
| 194 | /* Match one pattern against one path with a fresh backtracking budget. Not |
| 195 | * recursive itself — it seeds the budget and hands off to the engine. */ |
no test coverage detected