From cffa072244376ef51dd0c8490f0f317282baaef1 Mon Sep 17 00:00:00 2001 From: Toddr Bot Date: Tue, 14 Apr 2026 05:15:04 +0000 Subject: [PATCH] fix: reject quantifiers exceeding Perl's REG_INFTY limit Perl rejects {n,m} quantifiers where n or m exceed 2147483646 (0x7FFFFFFE, the internal REG_INFTY constant). The parser was silently accepting these, producing nodes with arbitrarily large values that don't correspond to valid Perl regex behavior. Add RPe_QUANTBIG error code and validate both min and max values in the { handler before checking n > m ordering. Co-Authored-By: Claude Opus 4.6 --- README | 3 +++ lib/Regexp/Parser.pm | 4 ++++ lib/Regexp/Parser/Diagnostics.pm | 1 + lib/Regexp/Parser/Handlers.pm | 3 +++ t/11errors.t | 10 ++++++++++ 5 files changed, 21 insertions(+) diff --git a/README b/README index dfc5d78..13d44de 100644 --- a/README +++ b/README @@ -305,6 +305,9 @@ ERROR HANDLING RPe_IRANGE (-28) Invalid [] range "%s-%s" + RPe_QUANTBIG (-29) + Quantifier in {,} bigger than %s + EXTENSIONS Here are some ideas for extensions (sub-classes) for this module. Some of them may be absorbed into the core functionality of Regexp::Parser in diff --git a/lib/Regexp/Parser.pm b/lib/Regexp/Parser.pm index 9412df5..6a2ded0 100644 --- a/lib/Regexp/Parser.pm +++ b/lib/Regexp/Parser.pm @@ -706,6 +706,10 @@ False [] range "%s-%s" Invalid [] range "%s-%s" +=item RPe_QUANTBIG (-29) + +Quantifier in {,} bigger than %s + =back =head1 EXTENSIONS diff --git a/lib/Regexp/Parser/Diagnostics.pm b/lib/Regexp/Parser/Diagnostics.pm index 971cfd3..6454859 100644 --- a/lib/Regexp/Parser/Diagnostics.pm +++ b/lib/Regexp/Parser/Diagnostics.pm @@ -34,5 +34,6 @@ use constant RPe_OUTPOS => --$ENUM, 'POSIX syntax [%s %s] belongs inside charact use constant RPe_EMPTYB => --$ENUM, 'Empty \%s{}'; use constant RPe_FRANGE => --$ENUM, 'False [] range "%s-%s"'; use constant RPe_IRANGE => --$ENUM, 'Invalid [] range "%s-%s"'; +use constant RPe_QUANTBIG => --$ENUM, 'Quantifier in {,} bigger than %s'; 1; diff --git a/lib/Regexp/Parser/Handlers.pm b/lib/Regexp/Parser/Handlers.pm index e700f73..7e2acd0 100644 --- a/lib/Regexp/Parser/Handlers.pm +++ b/lib/Regexp/Parser/Handlers.pm @@ -495,6 +495,9 @@ sub init { my ($min, $range, $max) = ($1, $2, $3); $max = $min unless $range; push @{ $S->{next} }, qw< minmod >; + my $REG_INFTY = 2147483646; # 0x7FFFFFFE, Perl's internal limit + $S->error($S->RPe_QUANTBIG, $REG_INFTY) if $min > $REG_INFTY; + $S->error($S->RPe_QUANTBIG, $REG_INFTY) if length($max) and $max > $REG_INFTY; $S->error($S->RPe_BCURLY) if length($max) and $min > $max; return $S->object(quant => $min, $max); } diff --git a/t/11errors.t b/t/11errors.t index a8f5233..d9d5d10 100644 --- a/t/11errors.t +++ b/t/11errors.t @@ -100,6 +100,16 @@ fails_regex('a{5,3}', ($r->RPe_BCURLY)[0], '{n,m} with n > m'); fails_regex('a{10,0}', ($r->RPe_BCURLY)[0], '{10,0} with n > m'); fails_regex('a{100,1}', ($r->RPe_BCURLY)[0], '{100,1} with n > m'); +# {n,m} with values exceeding Perl's REG_INFTY (2147483646) +fails_regex('a{2147483647}', ($r->RPe_QUANTBIG)[0], '{n} exceeds REG_INFTY'); +fails_regex('a{2147483647,}', ($r->RPe_QUANTBIG)[0], '{n,} exceeds REG_INFTY'); +fails_regex('a{0,2147483647}', ($r->RPe_QUANTBIG)[0], '{0,m} exceeds REG_INFTY'); +fails_regex('a{999999999999}', ($r->RPe_QUANTBIG)[0], '{huge number}'); +fails_regex('a{3,999999999999}', ($r->RPe_QUANTBIG)[0], '{n,huge number}'); +parses_ok('a{2147483646}', '{n} at REG_INFTY is valid'); +parses_ok('a{0,2147483646}', '{0,m} at REG_INFTY is valid'); +parses_ok('a{2147483646,}', '{n,} at REG_INFTY is valid'); + # Quantifier follows nothing — deferred to visual pass fails_visual('*', ($r->RPe_EQUANT)[0], 'bare * quantifier'); fails_visual('+', ($r->RPe_EQUANT)[0], 'bare + quantifier');