From b8528f006c5b83f6fb49169b10239b1de395161c Mon Sep 17 00:00:00 2001 From: Mykhailo Chalyi Date: Thu, 26 Mar 2026 17:18:07 +0000 Subject: [PATCH] fix(interpreter): treat invalid glob bracket expressions as literals When [[ "$x" == "[]" ]] is evaluated, the incomplete bracket expression [] is now treated as literal characters instead of failing to match. Previously, invalid bracket expressions caused match_bracket_expr to return None, which was treated as a non-match. Closes #837 --- crates/bashkit/src/interpreter/glob.rs | 19 +++++++++++++-- .../tests/spec_cases/bash/conditional.test.sh | 23 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/crates/bashkit/src/interpreter/glob.rs b/crates/bashkit/src/interpreter/glob.rs index f849a0ff..5ed7b280 100644 --- a/crates/bashkit/src/interpreter/glob.rs +++ b/crates/bashkit/src/interpreter/glob.rs @@ -244,6 +244,9 @@ impl Interpreter { } } (Some('['), Some(v)) => { + // Save state before consuming '[' — if bracket expr is + // invalid (e.g. "[]"), we fall back to literal '[' match. + let saved_pattern = pattern_chars.clone(); pattern_chars.next(); // consume '[' let match_char = if nocase { v.to_ascii_lowercase() } else { v }; if let Some(matched) = @@ -255,8 +258,20 @@ impl Interpreter { return false; } } else { - // Invalid bracket expression, treat '[' as literal - return false; + // Invalid bracket expression — treat '[' as literal + pattern_chars = saved_pattern; + pattern_chars.next(); // consume '[' as literal + let p = '['; + let match_ok = if nocase { + p.eq_ignore_ascii_case(&v) + } else { + p == v + }; + if match_ok { + value_chars.next(); + } else { + return false; + } } } (Some('['), None) => return false, diff --git a/crates/bashkit/tests/spec_cases/bash/conditional.test.sh b/crates/bashkit/tests/spec_cases/bash/conditional.test.sh index 017b7aca..4aaea282 100644 --- a/crates/bashkit/tests/spec_cases/bash/conditional.test.sh +++ b/crates/bashkit/tests/spec_cases/bash/conditional.test.sh @@ -181,3 +181,26 @@ correct ### expect yes ### end + +### cond_bracket_literal_match +# Issue #837: [] should be treated as literal when it's an invalid glob +x="[]" +if [[ "$x" == "[]" ]]; then echo match; else echo "no match"; fi +### expect +match +### end + +### cond_single_bracket_literal +# Literal [ comparison +x="[" +[[ "$x" == "[" ]] && echo match || echo "no match" +### expect +match +### end + +### cond_valid_glob_bracket +# Valid glob [a] should still work as pattern +[[ "a" == [a] ]] && echo match || echo "no match" +### expect +match +### end