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);