Skip to content

Commit 5145e45

Browse files
committed
pcre2test: make resizing buffers slightly better
Use realloc() for exponential resize of all buffers, which has the advantage of potentially not needing to copy. Add a parameter to `expand_input_buffers()` to indicate the minimum size required and allow a smarter fallback when the buffer can't be doubled.
1 parent 484e564 commit 5145e45

File tree

1 file changed

+40
-30
lines changed

1 file changed

+40
-30
lines changed

src/pcre2test.c

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3838,37 +3838,36 @@ return 0;
38383838
*************************************************/
38393839

38403840
/* This function doubles the size of the input buffer and the buffer for
3841-
keeping an 8-bit copy of patterns (pbuffer8), and copies the current buffers to
3842-
the new ones.
3841+
keeping an 8-bit copy of patterns (pbuffer8), or if that is not possible
3842+
to the size provided as a minimum (plus 1 for the terminating NUL).
38433843
3844-
Arguments: none
3845-
Returns: nothing (aborts if malloc() fails)
3844+
Arguments:
3845+
minimum size on bytes expected as a minimum
3846+
Returns: nothing (aborts if realloc() fails)
38463847
*/
38473848

38483849
static void
3849-
expand_input_buffers(void)
3850+
expand_input_buffers(size_t minimum)
38503851
{
3851-
size_t new_pbuffer8_size = 2*pbuffer8_size;
3852-
uint8_t *new_buffer = (uint8_t *)malloc(new_pbuffer8_size);
3853-
uint8_t *new_pbuffer8 = (uint8_t *)malloc(new_pbuffer8_size);
3852+
size_t buffer_size;
38543853

3855-
if (new_buffer == NULL || new_pbuffer8 == NULL)
3856-
{
3857-
fprintf(stderr, "pcre2test: malloc(%" SIZ_FORM ") failed\n",
3858-
new_pbuffer8_size);
3859-
exit(1);
3860-
}
3854+
buffer_size = (pbuffer8_size < SIZE_MAX / 2)? 2 * pbuffer8_size : minimum + 1;
38613855

3862-
memcpy(new_buffer, buffer, pbuffer8_size);
3863-
memcpy(new_pbuffer8, pbuffer8, pbuffer8_size);
3856+
PCRE2_ASSERT(buffer_size > pbuffer8_size);
38643857

3865-
pbuffer8_size = new_pbuffer8_size;
3858+
/* If realloc fails, then the old pointer address is lost, but
3859+
it will be free with the process exit that follows. */
3860+
buffer = (uint8_t *)realloc(buffer, buffer_size);
3861+
pbuffer8 = (uint8_t *)realloc(pbuffer8, buffer_size);
38663862

3867-
free(buffer);
3868-
free(pbuffer8);
3863+
if (buffer == NULL || pbuffer8 == NULL)
3864+
{
3865+
fprintf(stderr, "pcre2test: realloc(%" SIZ_FORM ") failed\n",
3866+
buffer_size);
3867+
exit(1);
3868+
}
38693869

3870-
buffer = new_buffer;
3871-
pbuffer8 = new_pbuffer8;
3870+
pbuffer8_size = buffer_size;
38723871
}
38733872

38743873

@@ -3907,7 +3906,7 @@ for (;;)
39073906
size_t dlen;
39083907
size_t rlen = (size_t)(pbuffer8_size - (here - buffer));
39093908

3910-
/* If libreadline or libedit support is required, use readline() to read a
3909+
/* If libreadline or libedit support is available, use readline() to read a
39113910
line if the input is a terminal. Note that readline() removes the trailing
39123911
newline, so we must put it back again, to be compatible with fgets(). */
39133912

@@ -3968,7 +3967,7 @@ for (;;)
39683967
{
39693968
size_t start_offset = start - buffer;
39703969
size_t here_offset = here - buffer;
3971-
expand_input_buffers();
3970+
expand_input_buffers(pbuffer8_size + 1);
39723971
start = buffer + start_offset;
39733972
here = buffer + here_offset;
39743973
}
@@ -6222,12 +6221,12 @@ else if ((pat_patctl.control & CTL_EXPAND) != 0)
62226221
expanding buffers always keeps buffer and pbuffer8 in step as far as their
62236222
size goes. */
62246223

6225-
while (pt + m > pbuffer8 + pbuffer8_size)
6224+
while (m > pbuffer8_size)
62266225
{
62276226
size_t pc_offset = pc - buffer;
62286227
size_t pp_offset = pp - buffer;
62296228
size_t pt_offset = pt - pbuffer8;
6230-
expand_input_buffers();
6229+
expand_input_buffers(m);
62316230
pc = buffer + pc_offset;
62326231
pp = buffer + pp_offset;
62336232
pt = pbuffer8 + pt_offset;
@@ -8132,18 +8131,29 @@ while ((c = *p++) != 0)
81328131
{
81338132
size_t qoffset = CAST8VAR(q) - dbuffer;
81348133
size_t rep_offset = start_rep - dbuffer;
8134+
void *tp;
8135+
81358136
while (needlen >= dbuffer_size)
81368137
{
81378138
if (dbuffer_size < SIZE_MAX / 2) dbuffer_size *= 2;
81388139
else dbuffer_size = needlen + 1;
81398140
}
8140-
dbuffer = (uint8_t *)realloc(dbuffer, dbuffer_size);
8141-
if (dbuffer == NULL)
8141+
8142+
tp = realloc(dbuffer, dbuffer_size);
8143+
if (tp == NULL && dbuffer_size > needlen + 1)
81428144
{
8143-
fprintf(stderr, "pcre2test: realloc(%" SIZ_FORM ") failed\n",
8144-
dbuffer_size);
8145-
exit(1);
8145+
dbuffer_size = needlen + 1;
8146+
tp = realloc(dbuffer, dbuffer_size);
8147+
8148+
if (tp == NULL)
8149+
{
8150+
free(dbuffer);
8151+
fprintf(stderr, "pcre2test: realloc(%" SIZ_FORM ") failed\n",
8152+
dbuffer_size);
8153+
exit(1);
8154+
}
81468155
}
8156+
dbuffer = (uint8_t *)tp;
81478157
SETCASTPTR(q, dbuffer + qoffset);
81488158
start_rep = dbuffer + rep_offset;
81498159
}

0 commit comments

Comments
 (0)