[Pcre-svn] [463] code/trunk: Harden pcre2test against ridicu…

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [463] code/trunk: Harden pcre2test against ridiculously large values in modifiers and command
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