Revision: 463
http://www.exim.org/viewvc/pcre2?view=rev&revision=463
Author: ph10
Date: 2015-12-05 18:17:41 +0000 (Sat, 05 Dec 2015)
Log Message:
-----------
Harden pcre2test against ridiculously large values in modifiers and command
line arguments.
Modified Paths:
--------------
code/trunk/ChangeLog
code/trunk/src/pcre2test.c
code/trunk/testdata/testinput2
code/trunk/testdata/testoutput2
Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog 2015-12-04 18:43:00 UTC (rev 462)
+++ code/trunk/ChangeLog 2015-12-05 18:17:41 UTC (rev 463)
@@ -383,7 +383,10 @@
110. Implemented PCRE2_SUBSTITUTE_UNSET_EMPTY, and updated pcre2test to make it
possible to test it.
+111. "Harden" pcre2test against ridiculously large values in modifiers and
+command line arguments.
+
Version 10.20 30-June-2015
--------------------------
Modified: code/trunk/src/pcre2test.c
===================================================================
--- code/trunk/src/pcre2test.c 2015-12-04 18:43:00 UTC (rev 462)
+++ code/trunk/src/pcre2test.c 2015-12-05 18:17:41 UTC (rev 463)
@@ -2974,33 +2974,6 @@
/*************************************************
-* 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 *
*************************************************/
@@ -3149,6 +3122,8 @@
decode_modifiers(uint8_t *p, int ctx, patctl *pctl, datctl *dctl)
{
uint8_t *ep, *pp;
+long li;
+unsigned long uli;
BOOL first = TRUE;
for (;;)
@@ -3314,9 +3289,15 @@
case MOD_IN2: /* One or two unsigned integers */
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 == ':')
- ((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;
pp = (uint8_t *)endptr;
break;
@@ -3331,19 +3312,25 @@
case MOD_SIZ: /* PCRE2_SIZE 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;
break;
case MOD_INT: /* Unsigned integer */
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;
break;
case MOD_INS: /* Signed integer */
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;
break;
@@ -3371,7 +3358,10 @@
if (isdigit(*pp) || *pp == '-')
{
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 */
if (value >= 0) /* Add new number */
{
@@ -6894,8 +6884,9 @@
while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
{
- const char *endptr;
+ char *endptr;
char *arg = argv[op];
+ unsigned long uli;
/* Display and/or set return code for configuration options. */
@@ -6945,7 +6936,7 @@
/* Set system stack size */
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)
fprintf(stderr, "pcre2test: -S is not supported on this OS\n");
@@ -6953,6 +6944,12 @@
#else
int rc;
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);
rlim.rlim_cur = stack_size * 1024 * 1024;
if (rlim.rlim_cur > rlim.rlim_max)
@@ -6995,12 +6992,16 @@
else if (strcmp(arg, "-t") == 0 || strcmp(arg, "-tm") == 0 ||
strcmp(arg, "-T") == 0 || strcmp(arg, "-TM") == 0)
{
- int temp;
int both = arg[2] == 0;
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++;
argc--;
}
Modified: code/trunk/testdata/testinput2
===================================================================
--- code/trunk/testdata/testinput2 2015-12-04 18:43:00 UTC (rev 462)
+++ code/trunk/testdata/testinput2 2015-12-05 18:17:41 UTC (rev 463)
@@ -4756,4 +4756,13 @@
/a|(b)c/replace=>$2<,substitute_unset_empty
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
Modified: code/trunk/testdata/testoutput2
===================================================================
--- code/trunk/testdata/testoutput2 2015-12-04 18:43:00 UTC (rev 462)
+++ code/trunk/testdata/testoutput2 2015-12-05 18:17:41 UTC (rev 463)
@@ -15085,4 +15085,20 @@
cat
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