From 510925de504993b3055ae116b11132e2aa217e66 Mon Sep 17 00:00:00 2001 From: Toddr Bot Date: Fri, 10 Apr 2026 05:55:55 +0000 Subject: [PATCH] fix: reject \NN backrefs starting with 8 or 9 when no valid group exists Multi-digit backreferences like \99, \80, \89 where the leading digit is 8 or 9 have no valid octal fallback (octal digits are 0-7). Previously the parser silently produced a null character (\000) followed by literal digits. Perl correctly rejects these as "Reference to nonexistent group". The fix checks the leading digit before attempting octal fallback in the backslash-digit handler. If the digit > 7, error immediately since no valid interpretation exists. Co-Authored-By: Claude Opus 4.6 --- lib/Regexp/Parser/Handlers.pm | 2 ++ t/11errors.t | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/lib/Regexp/Parser/Handlers.pm b/lib/Regexp/Parser/Handlers.pm index e700f73..6b8e616 100644 --- a/lib/Regexp/Parser/Handlers.pm +++ b/lib/Regexp/Parser/Handlers.pm @@ -560,6 +560,8 @@ sub init { if (!&SIZE_ONLY and !$cc and $n != 0) { $v .= $1 while ${&Rx} =~ m{ \G (\d) }xgc; if ($v > 9 and $v > $S->{maxpar}) { + # leading digit 8 or 9 has no valid octal fallback + $S->error($S->RPe_BGROUP) if $n > 7; &RxPOS -= length $v; $v = ""; } diff --git a/t/11errors.t b/t/11errors.t index a8f5233..3feb3f9 100644 --- a/t/11errors.t +++ b/t/11errors.t @@ -167,6 +167,17 @@ fails_visual('(a)\\2', ($r->RPe_BGROUP)[0], '\\2 with only 1 capture group') fails_visual('\\g{5}', ($r->RPe_BGROUP)[0], '\\g{5} with no capture groups'); fails_visual('\\g{-1}', ($r->RPe_BGROUP)[0], '\\g{-1} (relative) with no groups'); +# Multi-digit backrefs starting with 8 or 9 have no valid octal fallback +# Perl rejects these as "Reference to nonexistent group" +fails_visual('(a)\\99', ($r->RPe_BGROUP)[0], '\\99 with 1 group (not valid octal)'); +fails_visual('(a)\\80', ($r->RPe_BGROUP)[0], '\\80 with 1 group (not valid octal)'); +fails_visual('(a)\\89', ($r->RPe_BGROUP)[0], '\\89 with 1 group (not valid octal)'); +fails_visual('(a)\\98', ($r->RPe_BGROUP)[0], '\\98 with 1 group (not valid octal)'); + +# Multi-digit numbers with valid octal leading digit fall back to octal +parses_ok('(a)\\77', '\\77 with 1 group — valid octal fallback (chr 63)'); +parses_ok('(a)\\100', '\\100 with 1 group — valid octal fallback (chr 64)'); + # Valid backrefs should work parses_ok('(a)\\1', 'valid backref \\1 with 1 group'); parses_ok('(a)(b)\\2', 'valid backref \\2 with 2 groups');