Harden pcre2test against ridiculously large values in modifiers and command
line arguments.
This commit is contained in:
parent
925146d8cc
commit
b34dbecb75
|
@ -383,6 +383,9 @@ was found by the LLVM fuzzer.
|
||||||
110. Implemented PCRE2_SUBSTITUTE_UNSET_EMPTY, and updated pcre2test to make it
|
110. Implemented PCRE2_SUBSTITUTE_UNSET_EMPTY, and updated pcre2test to make it
|
||||||
possible to test it.
|
possible to test it.
|
||||||
|
|
||||||
|
111. "Harden" pcre2test against ridiculously large values in modifiers and
|
||||||
|
command line arguments.
|
||||||
|
|
||||||
|
|
||||||
Version 10.20 30-June-2015
|
Version 10.20 30-June-2015
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
|
@ -2973,33 +2973,6 @@ return 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************
|
|
||||||
* Read number from string *
|
|
||||||
*************************************************/
|
|
||||||
|
|
||||||
/* We don't use strtoul() because SunOS4 doesn't have it. Rather than mess
|
|
||||||
around with conditional compilation, just do the job by hand. It is only used
|
|
||||||
for unpicking arguments, so just keep it simple.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
str string to be converted
|
|
||||||
endptr where to put the end pointer
|
|
||||||
|
|
||||||
Returns: the unsigned long
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
get_value(const char *str, const char **endptr)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
while(*str != 0 && isspace(*str)) str++;
|
|
||||||
while (isdigit(*str)) result = result * 10 + (int)(*str++ - '0');
|
|
||||||
*endptr = str;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
* Scan the main modifier list *
|
* Scan the main modifier list *
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
@ -3149,6 +3122,8 @@ static BOOL
|
||||||
decode_modifiers(uint8_t *p, int ctx, patctl *pctl, datctl *dctl)
|
decode_modifiers(uint8_t *p, int ctx, patctl *pctl, datctl *dctl)
|
||||||
{
|
{
|
||||||
uint8_t *ep, *pp;
|
uint8_t *ep, *pp;
|
||||||
|
long li;
|
||||||
|
unsigned long uli;
|
||||||
BOOL first = TRUE;
|
BOOL first = TRUE;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -3314,9 +3289,15 @@ for (;;)
|
||||||
|
|
||||||
case MOD_IN2: /* One or two unsigned integers */
|
case MOD_IN2: /* One or two unsigned integers */
|
||||||
if (!isdigit(*pp)) goto INVALID_VALUE;
|
if (!isdigit(*pp)) goto INVALID_VALUE;
|
||||||
((uint32_t *)field)[0] = (uint32_t)strtoul((const char *)pp, &endptr, 10);
|
uli = strtoul((const char *)pp, &endptr, 10);
|
||||||
|
if (uli > UINT32_MAX) goto INVALID_VALUE;
|
||||||
|
((uint32_t *)field)[0] = (uint32_t)uli;
|
||||||
if (*endptr == ':')
|
if (*endptr == ':')
|
||||||
((uint32_t *)field)[1] = (uint32_t)strtoul((const char *)endptr+1, &endptr, 10);
|
{
|
||||||
|
uli = strtoul((const char *)endptr+1, &endptr, 10);
|
||||||
|
if (uli > UINT32_MAX) goto INVALID_VALUE;
|
||||||
|
((uint32_t *)field)[1] = (uint32_t)uli;
|
||||||
|
}
|
||||||
else ((uint32_t *)field)[1] = 0;
|
else ((uint32_t *)field)[1] = 0;
|
||||||
pp = (uint8_t *)endptr;
|
pp = (uint8_t *)endptr;
|
||||||
break;
|
break;
|
||||||
|
@ -3331,19 +3312,25 @@ for (;;)
|
||||||
|
|
||||||
case MOD_SIZ: /* PCRE2_SIZE value */
|
case MOD_SIZ: /* PCRE2_SIZE value */
|
||||||
if (!isdigit(*pp)) goto INVALID_VALUE;
|
if (!isdigit(*pp)) goto INVALID_VALUE;
|
||||||
*((PCRE2_SIZE *)field) = (PCRE2_SIZE)strtoul((const char *)pp, &endptr, 10);
|
uli = strtoul((const char *)pp, &endptr, 10);
|
||||||
|
if (uli == ULONG_MAX) goto INVALID_VALUE;
|
||||||
|
*((PCRE2_SIZE *)field) = (PCRE2_SIZE)uli;
|
||||||
pp = (uint8_t *)endptr;
|
pp = (uint8_t *)endptr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_INT: /* Unsigned integer */
|
case MOD_INT: /* Unsigned integer */
|
||||||
if (!isdigit(*pp)) goto INVALID_VALUE;
|
if (!isdigit(*pp)) goto INVALID_VALUE;
|
||||||
*((uint32_t *)field) = (uint32_t)strtoul((const char *)pp, &endptr, 10);
|
uli = strtoul((const char *)pp, &endptr, 10);
|
||||||
|
if (uli > UINT32_MAX) goto INVALID_VALUE;
|
||||||
|
*((uint32_t *)field) = (uint32_t)uli;
|
||||||
pp = (uint8_t *)endptr;
|
pp = (uint8_t *)endptr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_INS: /* Signed integer */
|
case MOD_INS: /* Signed integer */
|
||||||
if (!isdigit(*pp) && *pp != '-') goto INVALID_VALUE;
|
if (!isdigit(*pp) && *pp != '-') goto INVALID_VALUE;
|
||||||
*((int32_t *)field) = (int32_t)strtol((const char *)pp, &endptr, 10);
|
li = strtol((const char *)pp, &endptr, 10);
|
||||||
|
if (li > INT32_MAX || li < INT32_MIN) goto INVALID_VALUE;
|
||||||
|
*((int32_t *)field) = (int32_t)li;
|
||||||
pp = (uint8_t *)endptr;
|
pp = (uint8_t *)endptr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3371,7 +3358,10 @@ for (;;)
|
||||||
if (isdigit(*pp) || *pp == '-')
|
if (isdigit(*pp) || *pp == '-')
|
||||||
{
|
{
|
||||||
int ct = MAXCPYGET - 1;
|
int ct = MAXCPYGET - 1;
|
||||||
int32_t value = (int32_t)strtol((const char *)pp, &endptr, 10);
|
int32_t value;
|
||||||
|
li = strtol((const char *)pp, &endptr, 10);
|
||||||
|
if (li > INT32_MAX || li < INT32_MIN) goto INVALID_VALUE;
|
||||||
|
value = (int32_t)li;
|
||||||
field = (char *)field - m->offset + m->value; /* Adjust field ptr */
|
field = (char *)field - m->offset + m->value; /* Adjust field ptr */
|
||||||
if (value >= 0) /* Add new number */
|
if (value >= 0) /* Add new number */
|
||||||
{
|
{
|
||||||
|
@ -6894,8 +6884,9 @@ def_datctl.cfail[0] = def_datctl.cfail[1] = CFAIL_UNSET;
|
||||||
|
|
||||||
while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
|
while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
|
||||||
{
|
{
|
||||||
const char *endptr;
|
char *endptr;
|
||||||
char *arg = argv[op];
|
char *arg = argv[op];
|
||||||
|
unsigned long uli;
|
||||||
|
|
||||||
/* Display and/or set return code for configuration options. */
|
/* Display and/or set return code for configuration options. */
|
||||||
|
|
||||||
|
@ -6945,7 +6936,7 @@ while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
|
||||||
/* Set system stack size */
|
/* Set system stack size */
|
||||||
|
|
||||||
else if (strcmp(arg, "-S") == 0 && argc > 2 &&
|
else if (strcmp(arg, "-S") == 0 && argc > 2 &&
|
||||||
((stack_size = get_value(argv[op+1], &endptr)), *endptr == 0))
|
((uli = strtoul(argv[op+1], &endptr, 10)), *endptr == 0))
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) || defined(WIN32) || defined(__minix) || defined(NATIVE_ZOS) || defined(__VMS)
|
#if defined(_WIN32) || defined(WIN32) || defined(__minix) || defined(NATIVE_ZOS) || defined(__VMS)
|
||||||
fprintf(stderr, "pcre2test: -S is not supported on this OS\n");
|
fprintf(stderr, "pcre2test: -S is not supported on this OS\n");
|
||||||
|
@ -6953,6 +6944,12 @@ while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
|
||||||
#else
|
#else
|
||||||
int rc;
|
int rc;
|
||||||
struct rlimit rlim;
|
struct rlimit rlim;
|
||||||
|
if (uli > UINT32_MAX)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "+++ Argument for -S is too big\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
stack_size = (uint32_t)uli;
|
||||||
getrlimit(RLIMIT_STACK, &rlim);
|
getrlimit(RLIMIT_STACK, &rlim);
|
||||||
rlim.rlim_cur = stack_size * 1024 * 1024;
|
rlim.rlim_cur = stack_size * 1024 * 1024;
|
||||||
if (rlim.rlim_cur > rlim.rlim_max)
|
if (rlim.rlim_cur > rlim.rlim_max)
|
||||||
|
@ -6995,12 +6992,16 @@ while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
|
||||||
else if (strcmp(arg, "-t") == 0 || strcmp(arg, "-tm") == 0 ||
|
else if (strcmp(arg, "-t") == 0 || strcmp(arg, "-tm") == 0 ||
|
||||||
strcmp(arg, "-T") == 0 || strcmp(arg, "-TM") == 0)
|
strcmp(arg, "-T") == 0 || strcmp(arg, "-TM") == 0)
|
||||||
{
|
{
|
||||||
int temp;
|
|
||||||
int both = arg[2] == 0;
|
int both = arg[2] == 0;
|
||||||
showtotaltimes = arg[1] == 'T';
|
showtotaltimes = arg[1] == 'T';
|
||||||
if (argc > 2 && (temp = get_value(argv[op+1], &endptr), *endptr == 0))
|
if (argc > 2 && (uli = strtoul(argv[op+1], &endptr, 10), *endptr == 0))
|
||||||
{
|
{
|
||||||
timeitm = temp;
|
if (uli > INT32_MAX)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "+++ Argument for %s is too big\n", arg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
timeitm = (int)uli;
|
||||||
op++;
|
op++;
|
||||||
argc--;
|
argc--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4756,4 +4756,13 @@ a)"xI
|
||||||
/a|(b)c/replace=>$2<,substitute_unset_empty
|
/a|(b)c/replace=>$2<,substitute_unset_empty
|
||||||
cat
|
cat
|
||||||
|
|
||||||
|
/()()()/use_offset_limit
|
||||||
|
\=ovector=11000000000
|
||||||
|
\=callout_fail=11000000000
|
||||||
|
\=callout_fail=1:11000000000
|
||||||
|
\=callout_data=11000000000
|
||||||
|
\=callout_data=-11000000000
|
||||||
|
\=offset_limit=1100000000000000000000
|
||||||
|
\=copy=11000000000
|
||||||
|
|
||||||
# End of testinput2
|
# End of testinput2
|
||||||
|
|
|
@ -15085,4 +15085,20 @@ Failed: error -55 at offset 3 in replacement: requested value is not set
|
||||||
cat
|
cat
|
||||||
Failed: error -49 at offset 3 in replacement: unknown substring
|
Failed: error -49 at offset 3 in replacement: unknown substring
|
||||||
|
|
||||||
|
/()()()/use_offset_limit
|
||||||
|
\=ovector=11000000000
|
||||||
|
** Invalid value in 'ovector=11000000000'
|
||||||
|
\=callout_fail=11000000000
|
||||||
|
** Invalid value in 'callout_fail=11000000000'
|
||||||
|
\=callout_fail=1:11000000000
|
||||||
|
** Invalid value in 'callout_fail=1:11000000000'
|
||||||
|
\=callout_data=11000000000
|
||||||
|
** Invalid value in 'callout_data=11000000000'
|
||||||
|
\=callout_data=-11000000000
|
||||||
|
** Invalid value in 'callout_data=-11000000000'
|
||||||
|
\=offset_limit=1100000000000000000000
|
||||||
|
** Invalid value in 'offset_limit=1100000000000000000000'
|
||||||
|
\=copy=11000000000
|
||||||
|
** Invalid value in 'copy=11000000000'
|
||||||
|
|
||||||
# End of testinput2
|
# End of testinput2
|
||||||
|
|
Loading…
Reference in New Issue