mruby-regexp: bounds-check group index in RE_BACKREF

The RE_BACKREF execution path read `captures[group * 2]` and
`captures[group * 2 + 1]` without verifying that the group
index fit in the allocated captures array. A pattern like
`/\1/` (no capture group, but a backreference to group 1) is
accepted by the compiler and lands in execution with `ncap = 2`
(only group 0 slots) and an instruction asking for group 1 --
a 4-byte read past the end of the allocation.

Reported by ClusterFuzz testcase
clusterfuzz-testcase-minimized-mruby_fuzzer-5474946829844480.

Add `if (group * 2 + 1 >= ncap) return FALSE;` ahead of the
captures access, mirroring the bounds guard already present in
RE_SAVE. The compiler's permissive `\<digit>` handling stays
unchanged; the runtime now treats a reference to a non-existent
group as a non-match rather than UB.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-05-19 10:40:45 +09:00
parent 5bb4a15086
commit db2845aae0
+1
View File
@@ -492,6 +492,7 @@ bt_match(const mrb_regexp_pattern *pat, const char *str, const char *str_end,
case RE_BACKREF:
{
int group = inst.a;
if (group * 2 + 1 >= ncap) return FALSE;
int gs = captures[group * 2];
int ge = captures[group * 2 + 1];
if (gs < 0 || ge < 0) return FALSE;