@@ -3874,44 +3874,83 @@ return 0;
38743874}
38753875#endif /* SUPPORT_PCRE2_32 */
38763876
3877+ /* A helper to realloc() a buffer to a desired or fallback sizes. */
38773878
3879+ static void *
3880+ realloc_buffer (void * source , size_t fallback , size_t * size )
3881+ {
3882+ void * p ;
3883+
3884+ p = realloc (source , * size );
3885+ if (p == NULL )
3886+ {
3887+ p = realloc (source , fallback );
3888+ if (p == NULL )
3889+ {
3890+ * size = 0 ;
3891+ return NULL ;
3892+ }
3893+ * size = fallback ;
3894+ }
3895+ return p ;
3896+ }
38783897
38793898/*************************************************
38803899* Expand input buffers *
38813900*************************************************/
38823901
38833902/* This function doubles the size of the input buffer and the buffer for
3884- keeping an 8-bit copy of patterns (pbuffer8), and copies the current buffers to
3885- the new ones .
3903+ keeping an 8-bit copy of patterns (pbuffer8) until it is larger than the
3904+ minimum, or to the minimum if it can't be doubled .
38863905
3887- Arguments: none
3888- Returns: nothing (aborts if malloc() fails)
3906+ Arguments:
3907+ minimum size on bytes expected as a minimum
3908+ Returns: nothing (aborts if any realloc() fails)
38893909*/
38903910
38913911static void
3892- expand_input_buffers (void )
3912+ expand_input_buffers (size_t minimum )
38933913{
3894- size_t new_pbuffer8_size = 2 * pbuffer8_size ;
3895- uint8_t * new_buffer = (uint8_t * )malloc (new_pbuffer8_size );
3896- uint8_t * new_pbuffer8 = (uint8_t * )malloc (new_pbuffer8_size );
3914+ size_t buffer_size , allowed_size ;
3915+ void * p ;
38973916
3898- if (new_buffer == NULL || new_pbuffer8 == NULL )
3917+ PCRE2_ASSERT (minimum > pbuffer8_size );
3918+ if (minimum >= SIZE_MAX / 2 || pbuffer8_size >= SIZE_MAX / 2 )
3919+ buffer_size = minimum ;
3920+ else
38993921 {
3900- fprintf (stderr , "pcre2test: malloc(%" SIZ_FORM ") failed\n" ,
3901- new_pbuffer8_size );
3902- exit (1 );
3922+ buffer_size = pbuffer8_size ;
3923+ while (buffer_size < minimum ) buffer_size *= 2 ;
39033924 }
39043925
3905- memcpy ( new_buffer , buffer , pbuffer8_size );
3906- memcpy ( new_pbuffer8 , pbuffer8 , pbuffer8_size ) ;
3926+ p = realloc_buffer ( buffer , minimum , & buffer_size );
3927+ if ( p == NULL ) goto DIE ;
39073928
3908- pbuffer8_size = new_pbuffer8_size ;
3929+ allowed_size = buffer_size ;
3930+ buffer = p ;
39093931
3910- free ( buffer );
3911- free ( pbuffer8 ) ;
3932+ p = realloc_buffer ( pbuffer8 , minimum , & buffer_size );
3933+ if ( p == NULL ) goto DIE ;
39123934
3913- buffer = new_buffer ;
3914- pbuffer8 = new_pbuffer8 ;
3935+ if (allowed_size != buffer_size )
3936+ {
3937+ void * q = realloc (buffer , buffer_size );
3938+ if (q == NULL )
3939+ {
3940+ fprintf (stderr , "pcre2test: realloc(%" SIZ_FORM ") failed\n" ,
3941+ buffer_size );
3942+ exit (1 );
3943+ }
3944+ buffer = q ;
3945+ }
3946+ else pbuffer8 = p ;
3947+
3948+ pbuffer8_size = buffer_size ;
3949+ return ;
3950+ DIE :
3951+ fprintf (stderr , "pcre2test: realloc(%" SIZ_FORM ") failed\n" ,
3952+ minimum );
3953+ exit (1 );
39153954}
39163955
39173956
@@ -3950,7 +3989,7 @@ for (;;)
39503989 size_t dlen ;
39513990 size_t rlen = (size_t )(pbuffer8_size - (here - buffer ));
39523991
3953- /* If libreadline or libedit support is required , use readline() to read a
3992+ /* If libreadline or libedit support is available , use readline() to read a
39543993 line if the input is a terminal. Note that readline() removes the trailing
39553994 newline, so we must put it back again, to be compatible with fgets(). */
39563995
@@ -4011,7 +4050,7 @@ for (;;)
40114050 {
40124051 size_t start_offset = start - buffer ;
40134052 size_t here_offset = here - buffer ;
4014- expand_input_buffers ();
4053+ expand_input_buffers (pbuffer8_size + 1 );
40154054 start = buffer + start_offset ;
40164055 here = buffer + here_offset ;
40174056 }
@@ -6202,14 +6241,14 @@ if ((pat_patctl.control & CTL_HEXPAT) != 0)
62026241else if ((pat_patctl .control & CTL_EXPAND ) != 0 )
62036242 {
62046243 uint8_t * pp , * pt ;
6244+ size_t needlen = 0 ;
62056245
62066246 pt = pbuffer8 ;
62076247 for (pp = buffer + 1 ; * pp != 0 ; pp ++ )
62086248 {
62096249 uint8_t * pc = pp ;
62106250 uint32_t count = 1 ;
62116251 size_t length = 1 ;
6212- size_t m = 1 ;
62136252
62146253 /* Check for replication syntax; if not found, the defaults just set will
62156254 prevail and `length` characters will be copied once. */
@@ -6252,7 +6291,7 @@ else if ((pat_patctl.control & CTL_EXPAND) != 0)
62526291 pc -= 2 ;
62536292 length = pe - pc ;
62546293 }
6255- m = length * count ;
6294+ needlen + = length * count ;
62566295 pp = pe ;
62576296
62586297 /* The main loop increments pp, so if we are already at the end of
@@ -6264,12 +6303,12 @@ else if ((pat_patctl.control & CTL_EXPAND) != 0)
62646303 expanding buffers always keeps buffer and pbuffer8 in step as far as their
62656304 size goes. */
62666305
6267- while ( pt + m > pbuffer8 + pbuffer8_size )
6306+ if ( needlen > pbuffer8_size )
62686307 {
62696308 size_t pc_offset = pc - buffer ;
62706309 size_t pp_offset = pp - buffer ;
62716310 size_t pt_offset = pt - pbuffer8 ;
6272- expand_input_buffers ();
6311+ expand_input_buffers (needlen );
62736312 pc = buffer + pc_offset ;
62746313 pp = buffer + pp_offset ;
62756314 pt = pbuffer8 + pt_offset ;
@@ -8099,17 +8138,17 @@ if (dbuffer != NULL)
80998138 }
81008139#endif
81018140
8102- /* Allocate a buffer to hold the data line; len+ 1 is an upper bound on
8141+ /* Allocate a buffer to hold the data line; len + 1 is an upper bound on
81038142the number of code units that will be needed (though the buffer may have to be
81048143extended if replication is involved). */
81058144
8106- needlen = (len + 1 ) * code_unit_size ;
8107- if (dbuffer == NULL || needlen >= dbuffer_size )
8145+ needlen = (len + 1 ) * code_unit_size ;
8146+ if (dbuffer == NULL || needlen > dbuffer_size )
81088147 {
8109- while (needlen >= dbuffer_size )
8148+ while (needlen > dbuffer_size )
81108149 {
81118150 if (dbuffer_size < SIZE_MAX /2 ) dbuffer_size *= 2 ;
8112- else dbuffer_size = needlen + 1 ;
8151+ else dbuffer_size = needlen ;
81138152 }
81148153 dbuffer = (uint8_t * )realloc (dbuffer , dbuffer_size );
81158154 if (dbuffer == NULL )
@@ -8146,7 +8185,7 @@ while ((c = *p++) != 0)
81468185
81478186 errno = 0 ;
81488187 li = strtol ((const char * )p , & endptr , 10 );
8149- if (!isdigit (* p ) || errno != 0 || li < 1 || S32OVERFLOW (li ))
8188+ if (!isdigit (* p ) || li < 1 || S32OVERFLOWE (li ))
81508189 {
81518190 fprintf (outfile , "** Replication count missing or invalid (1..INT_MAX)\n" );
81528191 return PR_OK ;
@@ -8170,22 +8209,26 @@ while ((c = *p++) != 0)
81708209 }
81718210 needlen += replen * i ;
81728211
8173- if (needlen >= dbuffer_size )
8212+ if (needlen > dbuffer_size )
81748213 {
81758214 size_t qoffset = CAST8VAR (q ) - dbuffer ;
81768215 size_t rep_offset = start_rep - dbuffer ;
8177- while (needlen >= dbuffer_size )
8216+ void * tp ;
8217+
8218+ while (needlen > dbuffer_size )
81788219 {
81798220 if (dbuffer_size < SIZE_MAX / 2 ) dbuffer_size *= 2 ;
8180- else dbuffer_size = needlen + 1 ;
8221+ else dbuffer_size = needlen ;
81818222 }
8182- dbuffer = (uint8_t * )realloc (dbuffer , dbuffer_size );
8183- if (dbuffer == NULL )
8223+
8224+ tp = realloc_buffer (dbuffer , needlen , & dbuffer_size );
8225+ if (tp == NULL )
81848226 {
81858227 fprintf (stderr , "pcre2test: realloc(%" SIZ_FORM ") failed\n" ,
8186- dbuffer_size );
8228+ needlen );
81878229 exit (1 );
81888230 }
8231+ dbuffer = (uint8_t * )tp ;
81898232 SETCASTPTR (q , dbuffer + qoffset );
81908233 start_rep = dbuffer + rep_offset ;
81918234 }
0 commit comments