Skip to content

Commit ba0a3ff

Browse files
PhilipHazelNWilson
authored andcommitted
Fix issue #275
Cherry-picked from 803a64f.
1 parent bfb55a6 commit ba0a3ff

File tree

3 files changed

+28
-19
lines changed

3 files changed

+28
-19
lines changed

src/pcre2_match.c

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,6 @@ heapframe *P = NULL;
597597

598598
heapframe *frames_top; /* End of frames vector */
599599
heapframe *assert_accept_frame = NULL; /* For passing back a frame with captures */
600-
PCRE2_SIZE heapframes_size; /* Usable size of frames vector */
601600
PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */
602601

603602
/* Local variables that do not need to be preserved over calls to RRMATCH(). */
@@ -635,13 +634,10 @@ copied when a new frame is created. */
635634

636635
frame_copy_size = frame_size - offsetof(heapframe, eptr);
637636

638-
/* Set up the first frame and the end of the frames vector. We set the local
639-
heapframes_size to the usuable amount of the vector, that is, a whole number of
640-
frames. */
637+
/* Set up the first frame and the end of the frames vector. */
641638

642639
F = match_data->heapframes;
643-
heapframes_size = (match_data->heapframes_size / frame_size) * frame_size;
644-
frames_top = (heapframe *)((char *)F + heapframes_size);
640+
frames_top = (heapframe *)((char *)F + match_data->heapframes_size);
645641

646642
Frdepth = 0; /* "Recursion" depth */
647643
Fcapture_last = 0; /* Number of most recent capture */
@@ -662,10 +658,11 @@ backtracking point. */
662658
doubling the size, but constrained by the heap limit (which is in KiB). */
663659

664660
N = (heapframe *)((char *)F + frame_size);
665-
if (N >= frames_top)
661+
if ((heapframe *)((char *)N + frame_size) >= frames_top)
666662
{
667663
heapframe *new;
668664
PCRE2_SIZE newsize;
665+
PCRE2_SIZE usedsize = (char *)N - (char *)(match_data->heapframes);
669666

670667
if (match_data->heapframes_size >= PCRE2_SIZE_MAX / 2)
671668
{
@@ -679,7 +676,8 @@ if (N >= frames_top)
679676
if (newsize / 1024 >= mb->heap_limit)
680677
{
681678
PCRE2_SIZE old_size = match_data->heapframes_size / 1024;
682-
if (mb->heap_limit <= old_size) return PCRE2_ERROR_HEAPLIMIT;
679+
if (mb->heap_limit <= old_size)
680+
return PCRE2_ERROR_HEAPLIMIT;
683681
else
684682
{
685683
PCRE2_SIZE max_delta = 1024 * (mb->heap_limit - old_size);
@@ -689,19 +687,21 @@ if (N >= frames_top)
689687
}
690688
}
691689

690+
/* With a heap limit set, the permitted additional size may not be enough for
691+
another frame, so do a final check. */
692+
693+
if (newsize - usedsize < frame_size) return PCRE2_ERROR_HEAPLIMIT;
692694
new = match_data->memctl.malloc(newsize, match_data->memctl.memory_data);
693695
if (new == NULL) return PCRE2_ERROR_NOMEMORY;
694-
memcpy(new, match_data->heapframes, heapframes_size);
696+
memcpy(new, match_data->heapframes, usedsize);
695697

696-
F = (heapframe *)((char *)new + ((char *)F - (char *)match_data->heapframes));
697-
N = (heapframe *)((char *)F + frame_size);
698+
N = (heapframe *)((char *)new + usedsize);
699+
F = (heapframe *)((char *)N - frame_size);
698700

699701
match_data->memctl.free(match_data->heapframes, match_data->memctl.memory_data);
700702
match_data->heapframes = new;
701703
match_data->heapframes_size = newsize;
702-
703-
heapframes_size = (newsize / frame_size) * frame_size;
704-
frames_top = (heapframe *)((char *)new + heapframes_size);
704+
frames_top = (heapframe *)((char *)new + newsize);
705705
}
706706

707707
#ifdef DEBUG_SHOW_RMATCH
@@ -6842,8 +6842,7 @@ mb->match_limit_depth = (mcontext->depth_limit < re->limit_depth)?
68426842
/* If a pattern has very many capturing parentheses, the frame size may be very
68436843
large. Set the initial frame vector size to ensure that there are at least 10
68446844
available frames, but enforce a minimum of START_FRAMES_SIZE. If this is
6845-
greater than the heap limit, get as large a vector as possible. Always round
6846-
the size to a multiple of the frame size. */
6845+
greater than the heap limit, get as large a vector as possible. */
68476846

68486847
heapframes_size = frame_size * 10;
68496848
if (heapframes_size < START_FRAMES_SIZE) heapframes_size = START_FRAMES_SIZE;
@@ -7301,7 +7300,6 @@ for(;;)
73017300
mb->match_call_count = 0;
73027301
mb->end_offset_top = 0;
73037302
mb->skip_arg_count = 0;
7304-
73057303
rc = match(start_match, mb->start_code, re->top_bracket, frame_size,
73067304
match_data, mb);
73077305

testdata/testinput15

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66

77
# (2) Other tests that must not be run with JIT.
88

9-
# This test is first so that it doesn't inherit a large enough heap frame
9+
# These tests are first so that they don't inherit a large enough heap frame
1010
# vector from a previous test.
1111

1212
/(*LIMIT_HEAP=21)\[(a)]{60}/expand
1313
\[a]{60}
1414

15+
"(*LIMIT_HEAP=21)()((?))()()()()()()()()()()()()()()()()()()()()()()()(())()()()()()()()()()()()()()()()()()()()()()(())()()()()()()()()()()()()()"
16+
xx
17+
18+
# -----------------------------------------------------------------------
19+
1520
/(a+)*zz/I
1621
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazzbbbbbb\=find_limits_noheap
1722
aaaaaaaaaaaaaz\=find_limits_noheap

testdata/testoutput15

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@
66

77
# (2) Other tests that must not be run with JIT.
88

9-
# This test is first so that it doesn't inherit a large enough heap frame
9+
# These tests are first so that they don't inherit a large enough heap frame
1010
# vector from a previous test.
1111

1212
/(*LIMIT_HEAP=21)\[(a)]{60}/expand
1313
\[a]{60}
1414
Failed: error -63: heap limit exceeded
1515

16+
"(*LIMIT_HEAP=21)()((?))()()()()()()()()()()()()()()()()()()()()()()()(())()()()()()()()()()()()()()()()()()()()()()(())()()()()()()()()()()()()()"
17+
xx
18+
Failed: error -63: heap limit exceeded
19+
20+
# -----------------------------------------------------------------------
21+
1622
/(a+)*zz/I
1723
Capture group count = 1
1824
Starting code units: a z

0 commit comments

Comments
 (0)