summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorph10 <ph10@6239d852-aaf2-0410-a92c-79f79f948069>2015-12-05 18:17:41 +0000
committerph10 <ph10@6239d852-aaf2-0410-a92c-79f79f948069>2015-12-05 18:17:41 +0000
commit959274234c98be7f9723edb9338c3385c7628781 (patch)
tree08a19a5afce53947ea677514361ae62fe2e44af4
parent126905bfccac7e652507e42fc14d7e74692dd457 (diff)
downloadpcre2-959274234c98be7f9723edb9338c3385c7628781.tar.gz
Harden pcre2test against ridiculously large values in modifiers and command
line arguments. git-svn-id: svn://vcs.exim.org/pcre2/code/trunk@463 6239d852-aaf2-0410-a92c-79f79f948069
-rw-r--r--ChangeLog3
-rw-r--r--src/pcre2test.c77
-rw-r--r--testdata/testinput29
-rw-r--r--testdata/testoutput216
4 files changed, 67 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 02333f9..e27b96b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -383,6 +383,9 @@ was found by the LLVM fuzzer.
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
--------------------------
diff --git a/src/pcre2test.c b/src/pcre2test.c
index 984c35e..93f57f7 100644
--- a/src/pcre2test.c
+++ b/src/pcre2test.c
@@ -2974,33 +2974,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 *
*************************************************/
@@ -3149,6 +3122,8 @@ static BOOL
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 @@ for (;;)
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 @@ for (;;)
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 @@ for (;;)
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 @@ def_datctl.cfail[0] = def_datctl.cfail[1] = CFAIL_UNSET;
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 @@ while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
/* 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 @@ while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
#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 @@ while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
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--;
}
diff --git a/testdata/testinput2 b/testdata/testinput2
index cbb2dcb..075d414 100644
--- a/testdata/testinput2
+++ b/testdata/testinput2
@@ -4756,4 +4756,13 @@ a)"xI
/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
diff --git a/testdata/testoutput2 b/testdata/testoutput2
index 023843b..ea0c69d 100644
--- a/testdata/testoutput2
+++ b/testdata/testoutput2
@@ -15085,4 +15085,20 @@ Failed: error -55 at offset 3 in replacement: requested value is not set
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