Skip to content

Commit 3ebcb07

Browse files
committed
Fuzzsupport now makes a copy of its input instead of modifying the original
1 parent dd0bc88 commit 3ebcb07

File tree

1 file changed

+57
-47
lines changed

1 file changed

+57
-47
lines changed

src/pcre2_fuzzsupport.c

Lines changed: 57 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ uint64_t random_options;
271271
pcre2_match_data *match_data = NULL;
272272
#ifdef SUPPORT_JIT
273273
pcre2_match_data *match_data_jit = NULL;
274+
PCRE2_UCHAR *newwdata = NULL;
274275
#endif
275276
pcre2_match_context *match_context = NULL;
276277
size_t match_size;
@@ -291,75 +292,83 @@ get around this, we scan the data string for large quantifiers that follow a
291292
closing parenthesis, and reduce the value of the quantifier to 10, assuming
292293
that this will make minimal difference to the detection of bugs.
293294
294-
Start the scan at the second character so there can be a lookbehind for a
295-
backslash, and end it before the end so that the next character can be checked
296-
for an opening brace. */
295+
We have to make a copy of the input because oss-fuzz complains if we overwrite
296+
the original. Start the scan at the second character so there can be a
297+
lookbehind for a backslash, and end it before the end so that the next
298+
character can be checked for an opening brace. */
297299

298-
if (size > 3) for (size_t i = 1; i < size - 2; i++)
300+
if (size > 3)
299301
{
300-
size_t j;
301-
302-
if (wdata[i] != ')' || wdata[i-1] == '\\' || wdata[i+1] != '{') continue;
303-
i++; /* Points to '{' */
302+
newwdata = malloc(size * sizeof(PCRE2_UCHAR));
303+
memcpy(newwdata, wdata, size * sizeof(PCRE2_UCHAR));
304+
wdata = newwdata;
304305

305-
/* Loop for two values a quantifier. Offset i points to brace or comma at the
306-
start of the loop.*/
307-
308-
for (int ii = 0; ii < 2; ii++)
306+
for (size_t i = 1; i < size - 2; i++)
309307
{
310-
int q = 0;
308+
size_t j;
309+
310+
if (wdata[i] != ')' || wdata[i-1] == '\\' || wdata[i+1] != '{') continue;
311+
i++; /* Points to '{' */
311312

312-
/* Ignore leading spaces */
313+
/* Loop for two values a quantifier. Offset i points to brace or comma at the
314+
start of the loop.*/
313315

314-
while (wdata[i+1] == ' ' || wdata[i+1] == '\t')
316+
for (int ii = 0; ii < 2; ii++)
315317
{
316-
i++;
317-
if (i >= size - 1) goto END_QSCAN;
318-
}
318+
int q = 0;
319319

320-
/* Scan for a number ending in brace or comma in the first iteration,
321-
optionally preceded by space. */
320+
/* Ignore leading spaces */
322321

323-
for (j = i + 1; j < size && j < i + 7; j++)
324-
{
325-
if (wdata[j] == ' ' || wdata[j] == '\t')
322+
while (wdata[i+1] == ' ' || wdata[i+1] == '\t')
326323
{
327-
do j++; while (j < size && (wdata[j] == ' ' || wdata[j] == '\t'));
328-
if (wdata[j] != '}' && wdata[j] != ',') goto OUTERLOOP;
324+
i++;
325+
if (i >= size - 1) goto END_QSCAN;
329326
}
330-
if (wdata[j] == '}' || (ii == 0 && wdata[j] == ',')) break;
331-
if (wdata[j] < '0' || wdata[j] > '9') goto OUTERLOOP;
332-
q = q * 10 + wdata[j] - '0';
333-
}
334327

335-
/* Hit ',' or '}' or read 6 digits. Six digits is a number > 65536 which is
336-
the maximum quantifier. Leave such numbers alone. */
328+
/* Scan for a number ending in brace or comma in the first iteration,
329+
optionally preceded by space. */
337330

338-
if (j >= i + 7 || q > 65535) goto OUTERLOOP;
331+
for (j = i + 1; j < size && j < i + 7; j++)
332+
{
333+
if (wdata[j] == ' ' || wdata[j] == '\t')
334+
{
335+
do j++; while (j < size && (wdata[j] == ' ' || wdata[j] == '\t'));
336+
if (wdata[j] != '}' && wdata[j] != ',') goto OUTERLOOP;
337+
}
338+
if (wdata[j] == '}' || (ii == 0 && wdata[j] == ',')) break;
339+
if (wdata[j] < '0' || wdata[j] > '9') goto OUTERLOOP;
340+
q = q * 10 + wdata[j] - '0';
341+
}
339342

340-
/* Limit the quantifier size to 10 */
343+
/* Hit ',' or '}' or read 6 digits. Six digits is a number > 65536 which is
344+
the maximum quantifier. Leave such numbers alone. */
341345

342-
if (q > 10)
343-
{
346+
if (j >= i + 7 || q > 65535) goto OUTERLOOP;
347+
348+
/* Limit the quantifier size to 10 */
349+
350+
if (q > 10)
351+
{
344352
#ifdef STANDALONE
345-
printf("Reduced quantifier value %d to 10.\n", q);
353+
printf("Reduced quantifier value %d to 10.\n", q);
346354
#endif
347-
for (size_t k = i + 1; k < j; k++) wdata[k] = '0';
348-
wdata[j - 2] = '1';
355+
for (size_t k = i + 1; k < j; k++) wdata[k] = '0';
356+
wdata[j - 2] = '1';
357+
}
358+
359+
/* Advance to end of number and break if reached closing brace (continue
360+
after comma, which is only valid in the first time round this loop). */
361+
362+
i = j;
363+
if (wdata[i] == '}') break;
349364
}
350365

351-
/* Advance to end of number and break if reached closing brace (continue
352-
after comma, which is only valid in the first time round this loop). */
366+
/* Continue along the data string */
353367

368+
OUTERLOOP:
354369
i = j;
355-
if (wdata[i] == '}') break;
370+
continue;
356371
}
357-
358-
/* Continue along the data string */
359-
360-
OUTERLOOP:
361-
i = j;
362-
continue;
363372
}
364373
END_QSCAN:
365374
#endif /* SUPPORT_JIT */
@@ -635,6 +644,7 @@ with the interpreter. */
635644
if (match_data != NULL) pcre2_match_data_free(match_data);
636645
#ifdef SUPPORT_JIT
637646
if (match_data_jit != NULL) pcre2_match_data_free(match_data_jit);
647+
free(newwdata);
638648
#endif
639649
if (match_context != NULL) pcre2_match_context_free(match_context);
640650

0 commit comments

Comments
 (0)