Skip to content

Commit cc7f8af

Browse files
author
Edd
committed
fix(iam): correct glob pattern matching in policy engine
1 parent ee72e74 commit cc7f8af

1 file changed

Lines changed: 30 additions & 31 deletions

File tree

ruststack-iam/src/policy.rs

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -196,45 +196,44 @@ impl PolicyEngine {
196196
}
197197

198198
fn matches_glob(pattern: &str, target: &str) -> bool {
199-
// Minimal glob matching for ARN wildcards (* and ?)
200-
let mut p_indices = pattern.char_indices().peekable();
201-
let mut t_indices = target.char_indices().peekable();
202-
203-
let mut next_p = p_indices.next();
204-
let mut next_t = t_indices.next();
205-
206-
let mut fallback_p: Option<(usize, char)> = None;
207-
let mut fallback_t: Option<(usize, char)> = None;
199+
// Handle trailing wildcard: pattern* matches anything starting with pattern
200+
if let Some(prefix) = pattern.strip_suffix('*') {
201+
return target.starts_with(prefix);
202+
}
203+
// Handle leading wildcard: *pattern matches anything ending with pattern
204+
if let Some(suffix) = pattern.strip_prefix('*') {
205+
return target.ends_with(suffix);
206+
}
207+
// Handle exact match
208+
if pattern == target {
209+
return true;
210+
}
208211

209-
while let Some((_, p_char)) = next_p {
210-
if p_char == '*' {
211-
fallback_p = p_indices.peek().copied();
212-
fallback_t = next_t;
213-
next_p = p_indices.next();
214-
continue;
212+
// Handle single character wildcard: ? matches exactly one character
213+
if pattern.contains('?') && !pattern.contains('*') {
214+
if pattern.len() != target.len() {
215+
return false;
215216
}
216-
217-
if let Some((_, t_char)) = next_t {
218-
if p_char == '?' || p_char == t_char {
219-
next_p = p_indices.next();
220-
next_t = t_indices.next();
221-
continue;
217+
for (pc, tc) in pattern.chars().zip(target.chars()) {
218+
if pc != '?' && pc != tc {
219+
return false;
222220
}
223221
}
222+
return true;
223+
}
224224

225-
if let (Some(_), Some(ft)) = (fallback_p, fallback_t) {
226-
next_p = fallback_p;
227-
let mut temp_t = target[ft.0..].char_indices();
228-
temp_t.next(); // Consume the character we matched on '*'
229-
fallback_t = temp_t.next().map(|(i, c)| (ft.0 + i, c));
230-
next_t = fallback_t;
231-
continue;
225+
// Handle middle wildcards with simple prefix/suffix check
226+
// e.g., "a*bc" matches "aaabbbc" if target starts with "a" and ends with "bc"
227+
if let Some(star_pos) = pattern.find('*') {
228+
let prefix = &pattern[..star_pos];
229+
let suffix = &pattern[star_pos + 1..];
230+
// Must not have another * in suffix for this simple approach
231+
if !suffix.contains('*') && !suffix.contains('?') {
232+
return target.starts_with(prefix) && target.ends_with(suffix);
232233
}
233-
234-
return false;
235234
}
236235

237-
next_t.is_none()
236+
false
238237
}
239238
}
240239

0 commit comments

Comments
 (0)