Skip to content

Commit bb152a4

Browse files
committed
don't call Perl_fbm_instr() with negative length
RT #131575 re_intuit_start() could calculate a maximum end position less than the current start position. This used to get rejected by fbm_intr(), until v5.23.3-110-g147f21b, which made fbm_intr() faster and removed unnecessary checks. This commits fixes re_intuit_start(), and adds an assert to fbm_intr().
1 parent 9a4e033 commit bb152a4

File tree

3 files changed

+25
-7
lines changed

3 files changed

+25
-7
lines changed

regexec.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,16 @@ static const char* const non_utf8_target_but_utf8_required
126126
(U8*)(off >= 0 ? reginfo->strend : reginfo->strbeg)) \
127127
: (U8*)(pos + off))
128128

129-
#define HOPBACKc(pos, off) \
130-
(char*)(reginfo->is_utf8_target \
131-
? reghopmaybe3((U8*)pos, (SSize_t)0-off, (U8*)(reginfo->strbeg)) \
132-
: (pos - off >= reginfo->strbeg) \
133-
? (U8*)pos - off \
129+
/* like HOPMAYBE3 but backwards. lim must be +ve. Returns NULL on overshoot */
130+
#define HOPBACK3(pos, off, lim) \
131+
(reginfo->is_utf8_target \
132+
? reghopmaybe3((U8*)pos, (SSize_t)0-off, (U8*)(lim)) \
133+
: (pos - off >= lim) \
134+
? (U8*)pos - off \
134135
: NULL)
135136

137+
#define HOPBACKc(pos, off) ((char*)HOPBACK3(pos, off, reginfo->strbeg))
138+
136139
#define HOP3(pos,off,lim) (reginfo->is_utf8_target ? reghop3((U8*)(pos), off, (U8*)(lim)) : (U8*)(pos + off))
137140
#define HOP3c(pos,off,lim) ((char*)HOP3(pos,off,lim))
138141

@@ -884,7 +887,9 @@ Perl_re_intuit_start(pTHX_
884887
(IV)prog->check_end_shift);
885888
});
886889

887-
end_point = HOP3(strend, -end_shift, strbeg);
890+
end_point = HOPBACK3(strend, end_shift, rx_origin);
891+
if (!end_point)
892+
goto fail_finish;
888893
start_point = HOPMAYBE3(rx_origin, start_shift, end_point);
889894
if (!start_point)
890895
goto fail_finish;

t/re/pat.t

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ BEGIN {
2323
skip_all('no re module') unless defined &DynaLoader::boot_DynaLoader;
2424
skip_all_without_unicode_tables();
2525

26-
plan tests => 836; # Update this when adding/deleting tests.
26+
plan tests => 837; # Update this when adding/deleting tests.
2727

2828
run_tests() unless caller;
2929

@@ -1906,6 +1906,17 @@ EOP
19061906
# [perl #129281] buffer write overflow, detected by ASAN, valgrind
19071907
fresh_perl_is('/0(?0)|^*0(?0)|^*(^*())0|/', '', {}, "don't bump whilem_c too much");
19081908
}
1909+
1910+
{
1911+
# RT #131575 intuit skipping back from the end to find the highest
1912+
# possible start point, was potentially hopping back beyond pos()
1913+
# and crashing by calling fbm_instr with a negative length
1914+
1915+
my $text = "=t=\x{5000}";
1916+
pos($text) = 3;
1917+
ok(scalar($text !~ m{(~*=[a-z]=)}g), "RT #131575");
1918+
}
1919+
19091920
} # End of sub run_tests
19101921

19111922
1;

util.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,8 @@ Perl_fbm_instr(pTHX_ unsigned char *big, unsigned char *bigend, SV *littlestr, U
816816

817817
PERL_ARGS_ASSERT_FBM_INSTR;
818818

819+
assert(bigend >= big);
820+
819821
if ((STRLEN)(bigend - big) < littlelen) {
820822
if ( tail
821823
&& ((STRLEN)(bigend - big) == littlelen - 1)

0 commit comments

Comments
 (0)