[Pcre-svn] [464] code/trunk/src: Update overflow checks in …

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [464] code/trunk/src: Update overflow checks in pcre2test to allow for ULONG_MAX==UINT32_MAX.
Revision: 464
          http://www.exim.org/viewvc/pcre2?view=rev&revision=464
Author:   ph10
Date:     2015-12-09 17:33:07 +0000 (Wed, 09 Dec 2015)
Log Message:
-----------
Update overflow checks in pcre2test to allow for ULONG_MAX==UINT32_MAX.


Modified Paths:
--------------
    code/trunk/src/pcre2.h
    code/trunk/src/pcre2.h.in
    code/trunk/src/pcre2test.c


Modified: code/trunk/src/pcre2.h
===================================================================
--- code/trunk/src/pcre2.h    2015-12-05 18:17:41 UTC (rev 463)
+++ code/trunk/src/pcre2.h    2015-12-09 17:33:07 UTC (rev 464)
@@ -302,6 +302,7 @@
 the offset vector (ovector). */


 #define PCRE2_SIZE            size_t
+#define PCRE2_SIZE_MAX        SIZE_MAX
 #define PCRE2_ZERO_TERMINATED (~(PCRE2_SIZE)0)
 #define PCRE2_UNSET           (~(PCRE2_SIZE)0)



Modified: code/trunk/src/pcre2.h.in
===================================================================
--- code/trunk/src/pcre2.h.in    2015-12-05 18:17:41 UTC (rev 463)
+++ code/trunk/src/pcre2.h.in    2015-12-09 17:33:07 UTC (rev 464)
@@ -302,6 +302,7 @@
 the offset vector (ovector). */


 #define PCRE2_SIZE            size_t
+#define PCRE2_SIZE_MAX        SIZE_MAX
 #define PCRE2_ZERO_TERMINATED (~(PCRE2_SIZE)0)
 #define PCRE2_UNSET           (~(PCRE2_SIZE)0)



Modified: code/trunk/src/pcre2test.c
===================================================================
--- code/trunk/src/pcre2test.c    2015-12-05 18:17:41 UTC (rev 463)
+++ code/trunk/src/pcre2test.c    2015-12-09 17:33:07 UTC (rev 464)
@@ -239,6 +239,22 @@
 #include "pcre2_tables.c"
 #include "pcre2_ucd.c"


+/* 32-bit integer values in the input are read by strtoul() or strtol(). The
+check needed for overflow depends on whether long ints are in fact longer than
+ints. They are defined not to be shorter. */
+
+#if ULONG_MAX > UINT32_MAX
+#define U32OVERFLOW(x) (x > UINT32_MAX)
+#else
+#define U32OVERFLOW(x) (x == UINT32_MAX)
+#endif
+
+#if LONG_MAX > INT32_MAX
+#define S32OVERFLOW(x) (x > INT32_MAX || x < INT32_MIN)
+#else
+#define S32OVERFLOW(x) (x == INT32_MAX || x == INT32_MIN)
+#endif
+
 /* When PCRE2_CODE_UNIT_WIDTH is zero, pcre2_internal.h does not include
 pcre2_intmodedep.h, which is where mode-dependent macros and structures are
 defined. We can now include it for each supported code unit width. Because
@@ -3290,12 +3306,12 @@
     case MOD_IN2:    /* One or two unsigned integers */
     if (!isdigit(*pp)) goto INVALID_VALUE;
     uli = strtoul((const char *)pp, &endptr, 10);
-    if (uli > UINT32_MAX) goto INVALID_VALUE;
+    if (U32OVERFLOW(uli)) goto INVALID_VALUE;
     ((uint32_t *)field)[0] = (uint32_t)uli;
     if (*endptr == ':')
       {
       uli = strtoul((const char *)endptr+1, &endptr, 10);
-      if (uli > UINT32_MAX) goto INVALID_VALUE;
+      if (U32OVERFLOW(uli)) goto INVALID_VALUE;
       ((uint32_t *)field)[1] = (uint32_t)uli;
       }
     else ((uint32_t *)field)[1] = 0;
@@ -3302,26 +3318,33 @@
     pp = (uint8_t *)endptr;
     break;


-    case MOD_IND:    /* Unsigned integer with default */
-    if (len == 0)
-      {
-      *((uint32_t *)field) = (uint32_t)(m->value);
-      break;
-      }
-    /* Fall through */
+    /* PCRE2_SIZE_MAX is usually SIZE_MAX, which may be greater, equal to, or
+    less than ULONG_MAX. So first test for overflowing the long int, and then
+    test for overflowing PCRE2_SIZE_MAX if it is smaller than ULONG_MAX. */


     case MOD_SIZ:    /* PCRE2_SIZE value */
     if (!isdigit(*pp)) goto INVALID_VALUE;
     uli = strtoul((const char *)pp, &endptr, 10);
     if (uli == ULONG_MAX) goto INVALID_VALUE;
+#if ULONG_MAX > PCRE2_SIZE_MAX
+    if (uli > PCRE2_SIZE_MAX) goto INVALID_VALUE;
+#endif
     *((PCRE2_SIZE *)field) = (PCRE2_SIZE)uli;
     pp = (uint8_t *)endptr;
     break;


+    case MOD_IND:    /* Unsigned integer with default */
+    if (len == 0)
+      {
+      *((uint32_t *)field) = (uint32_t)(m->value);
+      break;
+      }
+    /* Fall through */
+
     case MOD_INT:    /* Unsigned integer */
     if (!isdigit(*pp)) goto INVALID_VALUE;
     uli = strtoul((const char *)pp, &endptr, 10);
-    if (uli > UINT32_MAX) goto INVALID_VALUE;
+    if (U32OVERFLOW(uli)) goto INVALID_VALUE;
     *((uint32_t *)field) = (uint32_t)uli;
     pp = (uint8_t *)endptr;
     break;
@@ -3329,7 +3352,7 @@
     case MOD_INS:   /* Signed integer */
     if (!isdigit(*pp) && *pp != '-') goto INVALID_VALUE;
     li = strtol((const char *)pp, &endptr, 10);
-    if (li > INT32_MAX || li < INT32_MIN) goto INVALID_VALUE;
+    if (S32OVERFLOW(li)) goto INVALID_VALUE;
     *((int32_t *)field) = (int32_t)li;
     pp = (uint8_t *)endptr;
     break;
@@ -3360,7 +3383,7 @@
       int ct = MAXCPYGET - 1;
       int32_t value;
       li = strtol((const char *)pp, &endptr, 10);
-      if (li > INT32_MAX || li < INT32_MIN) goto INVALID_VALUE;
+      if (S32OVERFLOW(li)) goto INVALID_VALUE;
       value = (int32_t)li;
       field = (char *)field - m->offset + m->value;      /* Adjust field ptr */
       if (value >= 0)                                    /* Add new number */
@@ -6944,7 +6967,7 @@
 #else
     int rc;
     struct rlimit rlim;
-    if (uli > UINT32_MAX)
+    if (U32OVERFLOW(uli))
       {
       fprintf(stderr, "+++ Argument for -S is too big\n");
       exit(1);
@@ -6996,7 +7019,7 @@
     showtotaltimes = arg[1] == 'T';
     if (argc > 2 && (uli = strtoul(argv[op+1], &endptr, 10), *endptr == 0))
       {
-      if (uli > INT32_MAX)
+      if (U32OVERFLOW(uli))
         {
         fprintf(stderr, "+++ Argument for %s is too big\n", arg);
         exit(1);