mruby-regexp: handle \b inside character class as backspace

Inside `[...]`, `\b` denotes U+0008 (backspace) -- the same as
MRI/Onigmo and PCRE.  parse_escape() was missing the case, so
the backslash was dropped and the bare letter `b` was inserted
into the class.  `[\b]` therefore matched every `b` instead of
backspace.

Add `case 'b': return '\b';` to parse_escape().  The function
is only reached from the character-class body and range
endpoints; the top-level dispatcher emits RE_WBOUND for `\b`
before falling through, so the word-boundary semantics outside
`[...]` are unchanged.

Reported by Sam Ruby in matz/spinel#632; same engine bug
affects both spinel and mruby.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-05-21 08:23:15 +09:00
parent 17d124b00d
commit 54c8427df2
2 changed files with 10 additions and 0 deletions
+2
View File
@@ -214,6 +214,8 @@ parse_escape(re_compiler *c)
case 'v': return '\v';
case 'a': return '\a';
case 'e': return 0x1b;
case 'b': return '\b'; /* backspace; only reachable inside [...] since the
top-level dispatcher emits RE_WBOUND for `\b` */
default: return ch; /* literal: \., \\, \/, \(, etc. */
}
}
+8
View File
@@ -47,6 +47,14 @@ assert("Regexp - character class") do
assert_equal "abc", md[0]
end
assert("Regexp - \\b inside character class is backspace") do
# Outside [...], \b is the word boundary assertion; inside [...]
# it must mean U+0008 (backspace), matching MRI/Onigmo.
assert_equal "Ruby", "Ruby".gsub(/[\b]/, "X")
assert_equal "aXc", "a\bc".gsub(/[\b]/, "X")
assert_equal ["\b", "\t", "\n"], "ABC\b\t\n".scan(/[\b-\n]/)
end
assert("Regexp - dot") do
re = Regexp.new("a.c")
assert_true re.match?("abc")