[ruby/strscan] Fix a bug that inconsistency of IndexError vs nil for

unknown capture group
(https://github.com/ruby/strscan/pull/143)

Fix https://github.com/ruby/strscan/pull/139

Reported by Benoit Daloze. Thanks!!!

https://github.com/ruby/strscan/commit/bc8a0d2623
This commit is contained in:
NAITOH Jun 2025-02-23 16:52:32 +09:00 committed by Hiroshi SHIBATA
parent 36ab247e4d
commit 018943ba05
Notes: git 2025-02-25 06:37:05 +00:00
2 changed files with 39 additions and 18 deletions

View File

@ -1667,19 +1667,17 @@ strscan_matched_size(VALUE self)
static int static int
name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name, const char* name_end, rb_encoding *enc) name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name, const char* name_end, rb_encoding *enc)
{ {
int num; if (RTEST(regexp)) {
int num = onig_name_to_backref_number(RREGEXP_PTR(regexp),
num = onig_name_to_backref_number(RREGEXP_PTR(regexp), (const unsigned char* )name,
(const unsigned char* )name, (const unsigned char* )name_end, regs); (const unsigned char* )name_end,
if (num >= 1) { regs);
return num; if (num >= 1) {
return num;
}
} }
else { rb_enc_raise(enc, rb_eIndexError, "undefined group name reference: %.*s",
rb_enc_raise(enc, rb_eIndexError, "undefined group name reference: %.*s", rb_long2int(name_end - name), name);
rb_long2int(name_end - name), name);
}
UNREACHABLE;
} }
/* /*
@ -1768,7 +1766,6 @@ strscan_aref(VALUE self, VALUE idx)
idx = rb_sym2str(idx); idx = rb_sym2str(idx);
/* fall through */ /* fall through */
case T_STRING: case T_STRING:
if (!RTEST(p->regex)) return Qnil;
RSTRING_GETMEM(idx, name, i); RSTRING_GETMEM(idx, name, i);
i = name_to_backref_number(&(p->regs), p->regex, name, name + i, rb_enc_get(idx)); i = name_to_backref_number(&(p->regs), p->regex, name, name + i, rb_enc_get(idx));
break; break;

View File

@ -458,7 +458,31 @@ module StringScannerTests
def test_AREF def test_AREF
s = create_string_scanner('stra strb strc') s = create_string_scanner('stra strb strc')
s.scan(/\w+/) s.scan(/\s+/)
assert_nil( s[-2])
assert_nil( s[-1])
assert_nil( s[0])
assert_nil( s[1])
assert_nil( s[:c])
assert_nil( s['c'])
s.scan("not match")
assert_nil( s[-2])
assert_nil( s[-1])
assert_nil( s[0])
assert_nil( s[1])
assert_nil( s[:c])
assert_nil( s['c'])
s.check(/\w+/)
assert_nil( s[-2])
assert_equal('stra', s[-1])
assert_equal('stra', s[0])
assert_nil( s[1])
assert_raise(IndexError) { s[:c] }
assert_raise(IndexError) { s['c'] }
s.scan("stra")
assert_nil( s[-2]) assert_nil( s[-2])
assert_equal('stra', s[-1]) assert_equal('stra', s[-1])
assert_equal('stra', s[0]) assert_equal('stra', s[0])
@ -903,11 +927,11 @@ module StringScannerTests
s = create_string_scanner('abc') s = create_string_scanner('abc')
s.get_byte s.get_byte
assert_nil(s[:c]) assert_raise(IndexError) { s[:c] }
assert_nil(s["c"]) assert_raise(IndexError) { s['c'] }
s.getch s.getch
assert_nil(s[:c]) assert_raise(IndexError) { s[:c] }
assert_nil(s["c"]) assert_raise(IndexError) { s['c'] }
end end
def test_size def test_size