summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornigel <nigel@2f5784b3-3f2a-0410-8824-cb99058d5e15>2007-02-24 21:38:13 +0000
committernigel <nigel@2f5784b3-3f2a-0410-8824-cb99058d5e15>2007-02-24 21:38:13 +0000
commit91453b91d322e9d5812026584c2ecbe8f4cab52a (patch)
treeb87e19c06fa0a5304d6b611bb5999b4fadaac77d
parent94ffc03e8ac1628911f231a91d7d8d94c2f0dc38 (diff)
downloadpcre-91453b91d322e9d5812026584c2ecbe8f4cab52a.tar.gz
Load pcre-1.03 into code/trunk.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@9 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r--ChangeLog46
-rw-r--r--Makefile2
-rw-r--r--internal.h10
-rw-r--r--pcre.32
-rw-r--r--pcre.c240
-rw-r--r--pcre.h1
-rw-r--r--pcretest.c17
-rw-r--r--testinput45
-rw-r--r--testinput24
-rw-r--r--testoutput68
-rw-r--r--testoutput28
11 files changed, 306 insertions, 137 deletions
diff --git a/ChangeLog b/ChangeLog
index f2283d4..881fc37 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,52 @@ ChangeLog for PCRE
------------------
+Version 1.03 18-Dec-97
+----------------------
+
+1. A erroneous regex with a missing opening parenthesis was correctly
+diagnosed, but PCRE attempted to access brastack[-1], which could cause crashes
+on some systems.
+
+2. Replaced offsetof(real_pcre, code) by offsetof(real_pcre, code[0]) because
+it was reported that one broken compiler failed on the former because "code" is
+also an independent variable.
+
+3. The erroneous regex a[]b caused an array overrun reference.
+
+4. A regex ending with a one-character negative class (e.g. /[^k]$/) did not
+fail on data ending with that character. (It was going on too far, and checking
+the next character, typically a binary zero.) This was specific to the
+optimized code for single-character negative classes.
+
+5. Added a contributed patch from the TIN world which does the following:
+
+ + Add an undef for memmove, in case the the system defines a macro for it.
+
+ + Add a definition of offsetof(), in case there isn't one. (I don't know
+ the reason behind this - offsetof() is part of the ANSI standard - but
+ it does no harm).
+
+ + Reduce the ifdef's in pcre.c using macro DPRINTF, thereby eliminating
+ most of the places where whitespace preceded '#'. I have given up and
+ allowed the remaining 2 cases to be at the margin.
+
+ + Rename some variables in pcre to eliminate shadowing. This seems very
+ pedantic, but does no harm, of course.
+
+6. Moved the call to setjmp() into its own function, to get rid of warnings
+from gcc -Wall, and avoided calling it at all unless PCRE_EXTRA is used.
+
+7. Constructs such as \d{8,} were compiling into the equivalent of
+\d{8}\d{65527} instead of \d{8}\d* which didn't make much difference to the
+outcome, but in this particular case used more store than had been allocated,
+which caused the bug to be discovered because it threw up an internal error.
+
+8. The debugging code in both pcre and pcretest for outputting the compiled
+form of a regex was going wrong in the case of back references followed by
+curly-bracketed repeats.
+
+
Version 1.02 12-Dec-97
----------------------
diff --git a/Makefile b/Makefile
index b04ceda..d8efeb1 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@
# lacks the strerror() function, but can provide the equivalent by indexing
# into errlist.
-CC = gcc -O2
+CC = gcc -O2 -Wall
CFLAGS =
RANLIB = @true
diff --git a/internal.h b/internal.h
index 806ee9a..c8d17e1 100644
--- a/internal.h
+++ b/internal.h
@@ -3,7 +3,7 @@
*************************************************/
-#define PCRE_VERSION "1.02 12-Dec-1997"
+#define PCRE_VERSION "1.03 18-Dec-1997"
/* This is a library of functions to support regular expressions whose syntax
@@ -38,6 +38,7 @@ modules, but which are not relevant to the outside. */
define a macro for memmove() if USE_BCOPY is defined. */
#ifdef USE_BCOPY
+#undef memmove /* some systems may have a macro */
#define memmove(a, b, c) bcopy(b, a, c)
#endif
@@ -52,6 +53,13 @@ define a macro for memmove() if USE_BCOPY is defined. */
#include <string.h>
#include "pcre.h"
+/* In case there is no definition of offsetof() provided - though any proper
+Standard C system should have one. */
+
+#ifndef offsetof
+#define offsetof(p_type,field) ((size_t)&(((p_type)0)->field))
+#endif
+
/* Private options flags start at the most significant end of the two bytes.
The public options defined in pcre.h start at the least significant end. Make
sure they don't overlap! */
diff --git a/pcre.3 b/pcre.3
index f10dd86..8760ff9 100644
--- a/pcre.3
+++ b/pcre.3
@@ -603,7 +603,7 @@ operation from backtracking past it. For example, if the expression
.*/foo
-is matched against the string "/foo/this/is/not" then after the greedy .*
+is matched against the string "/this/string/is/not" then after the greedy .*
has swallowed the whole string, PCRE keeps backtracking all the way to the
beginning before failing. If, on the other hand, the expression is
diff --git a/pcre.c b/pcre.c
index 930737f..542f9e2 100644
--- a/pcre.c
+++ b/pcre.c
@@ -33,6 +33,15 @@ restrictions:
/* #define DEBUG */
+/* Use a macro for debugging printing, 'cause that eliminates the the use
+of #ifdef inline, and there are *still* stupid compilers about that don't like
+indented pre-processor statements. I suppose it's only been 10 years... */
+
+#ifdef DEBUG
+#define DPRINTF(p) printf p
+#else
+#define DPRINTF(p) /*nothing*/
+#endif
/* Include the internals header, which itself includes Standard C headers plus
the external pcre header. */
@@ -187,7 +196,8 @@ Arguments:
Returns: nothing
*/
-static pchars(uschar *p, int length, BOOL is_subject, match_data *md)
+static void
+pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
{
int c;
if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
@@ -977,9 +987,17 @@ for (;; ptr++)
if (code == previous) code += 2; else previous[1]++;
}
- /* Insert an UPTO if the max is greater than the min. */
+ /* If the maximum is unlimited, insert an OP_STAR. */
+
+ if (repeat_max < 0)
+ {
+ *code++ = c;
+ *code++ = OP_STAR + repeat_type;
+ }
+
+ /* Else insert an UPTO if the max is greater than the min. */
- if (repeat_max != repeat_min)
+ else if (repeat_max != repeat_min)
{
*code++ = c;
repeat_max -= repeat_min;
@@ -1023,7 +1041,7 @@ for (;; ptr++)
else if ((int)*previous >= OP_BRA)
{
int i;
- int length = code - previous;
+ int len = code - previous;
if (repeat_max == -1 && could_be_empty(previous))
{
@@ -1040,8 +1058,8 @@ for (;; ptr++)
{
for (i = 1; i < repeat_min; i++)
{
- memcpy(code, previous, length);
- code += length;
+ memcpy(code, previous, len);
+ code += len;
}
}
@@ -1053,22 +1071,22 @@ for (;; ptr++)
{
if (repeat_min == 0)
{
- memmove(previous+1, previous, length);
+ memmove(previous+1, previous, len);
code++;
*previous++ = OP_BRAZERO + repeat_type;
}
for (i = 1; i < repeat_min; i++)
{
- memcpy(code, previous, length);
- code += length;
+ memcpy(code, previous, len);
+ code += len;
}
for (i = (repeat_min > 0)? repeat_min : 1; i < repeat_max; i++)
{
*code++ = OP_BRAZERO + repeat_type;
- memcpy(code, previous, length);
- code += length;
+ memcpy(code, previous, len);
+ code += len;
}
}
@@ -1529,10 +1547,8 @@ if ((options & ~PUBLIC_OPTIONS) != 0)
return NULL;
}
-#ifdef DEBUG
-printf("------------------------------------------------------------------\n");
-printf("%s\n", pattern);
-#endif
+DPRINTF(("------------------------------------------------------------------\n"));
+DPRINTF(("%s\n", pattern));
/* The first thing to do is to make a pass over the pattern to compute the
amount of store required to hold the compiled code. This does not have to be
@@ -1647,9 +1663,9 @@ while ((c = *(++ptr)) != 0)
{
if (*ptr == '\\')
{
- int c = check_escape(&ptr, errorptr, bracount, options, TRUE);
+ int ch = check_escape(&ptr, errorptr, bracount, options, TRUE);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
- if (-c == ESC_b) class_charcount++; else class_charcount = 10;
+ if (-ch == ESC_b) class_charcount++; else class_charcount = 10;
}
else class_charcount++;
ptr++;
@@ -1664,7 +1680,7 @@ while ((c = *(++ptr)) != 0)
/* A repeat needs either 1 or 5 bytes. */
- if (ptr[1] == '{' && is_counted_repeat(ptr+2))
+ if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2))
{
ptr = read_repeat_counts(ptr+2, &min, &max, errorptr);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
@@ -1772,37 +1788,38 @@ while ((c = *(++ptr)) != 0)
continue;
/* Handle ket. Look for subsequent max/min; for certain sets of values we
- have to replicate this bracket up to that many times. */
+ have to replicate this bracket up to that many times. If brastackptr is
+ 0 this is an unmatched bracket which will generate an error, but take care
+ not to try to access brastack[-1]. */
case ')':
length += 3;
{
- int min = 1;
- int max = 1;
- int duplength = length - brastack[--brastackptr];
+ int minval = 1;
+ int maxval = 1;
+ int duplength = (brastackptr > 0)? length - brastack[--brastackptr] : 0;
/* Leave ptr at the final char; for read_repeat_counts this happens
automatically; for the others we need an increment. */
if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2))
{
- ptr = read_repeat_counts(ptr+2, &min, &max, errorptr);
+ ptr = read_repeat_counts(ptr+2, &minval, &maxval, errorptr);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
}
- else if (c == '*') { min = 0; max = -1; ptr++; }
- else if (c == '+') { max = -1; ptr++; }
- else if (c == '?') { min = 0; ptr++; }
+ else if (c == '*') { minval = 0; maxval = -1; ptr++; }
+ else if (c == '+') { maxval = -1; ptr++; }
+ else if (c == '?') { minval = 0; ptr++; }
- /* If there is a minimum > 1 we have to replicate up to min-1 times; if
- there is a limited maximum we have to replicate up to max-1 times and
- allow for a BRAZERO item before each optional copy, as we also have to
- do before the first copy if the minimum is zero. */
+ /* If there is a minimum > 1 we have to replicate up to minval-1 times;
+ if there is a limited maximum we have to replicate up to maxval-1 times
+ and allow for a BRAZERO item before each optional copy, as we also have
+ to do before the first copy if the minimum is zero. */
- if (min == 0) length++;
- else if (min > 1) length += (min - 1) * duplength;
- if (max > min) length += (max - min) * (duplength + 1);
+ if (minval == 0) length++;
+ else if (minval > 1) length += (minval - 1) * duplength;
+ if (maxval > minval) length += (maxval - minval) * (duplength + 1);
}
-
continue;
/* Non-special character. For a run of such characters the length required
@@ -1863,9 +1880,12 @@ if (length > 65539)
}
/* Compute the size of data block needed and get it, either from malloc or
-externally provided function. Put in the magic number and the options. */
+externally provided function. We specify "code[0]" in the offsetof() expression
+rather than just "code", because it has been reported that one broken compiler
+fails on "code" because it is also an independent variable. It should make no
+difference to the value of the offsetof(). */
-size = length + offsetof(real_pcre, code);
+size = length + offsetof(real_pcre, code[0]);
re = (real_pcre *)(pcre_malloc)(size);
if (re == NULL)
@@ -1874,6 +1894,8 @@ if (re == NULL)
return NULL;
}
+/* Put in the magic number and the options. */
+
re->magic_number = MAGIC_NUMBER;
re->options = options;
@@ -1924,10 +1946,10 @@ if ((options & PCRE_ANCHORED) == 0)
re->options |= PCRE_ANCHORED;
else
{
- int c = find_firstchar(re->code);
- if (c >= 0)
+ int ch = find_firstchar(re->code);
+ if (ch >= 0)
{
- re->first_char = c;
+ re->first_char = ch;
re->options |= PCRE_FIRSTSET;
}
else if (is_startline(re->code))
@@ -2064,7 +2086,8 @@ while (code < code_end)
case OP_REF:
printf(" \\%d", *(++code));
- break;
+ code ++;
+ goto CLASS_REF_REPEAT;
case OP_CLASS:
{
@@ -2094,6 +2117,8 @@ while (code < code_end)
printf("]");
code += 32;
+ CLASS_REF_REPEAT:
+
switch(*code)
{
case OP_CRSTAR:
@@ -2278,9 +2303,7 @@ for (;;)
int number = (*ecode - OP_BRA) << 1;
int save_offset1 = 0, save_offset2 = 0;
- #ifdef DEBUG
- printf("start bracket %d\n", number/2);
- #endif
+ DPRINTF(("start bracket %d\n", number/2));
if (number > 0 && number < md->offset_end)
{
@@ -2288,9 +2311,7 @@ for (;;)
save_offset2 = md->offset_vector[number+1];
md->offset_vector[number] = eptr - md->start_subject;
- #ifdef DEBUG
- printf("saving %d %d\n", save_offset1, save_offset2);
- #endif
+ DPRINTF(("saving %d %d\n", save_offset1, save_offset2));
}
/* Recurse for all the alternatives. */
@@ -2302,9 +2323,7 @@ for (;;)
}
while (*ecode == OP_ALT);
- #ifdef DEBUG
- printf("bracket %d failed\n", number/2);
- #endif
+ DPRINTF(("bracket %d failed\n", number/2));
if (number > 0 && number < md->offset_end)
{
@@ -2443,9 +2462,7 @@ for (;;)
number = (*prev - OP_BRA) << 1;
- #ifdef DEBUG
- printf("end bracket %d\n", number/2);
- #endif
+ DPRINTF(("end bracket %d\n", number/2));
if (number > 0)
{
@@ -2813,7 +2830,7 @@ for (;;)
register int length = ecode[1];
ecode += 2;
- #ifdef DEBUG
+#ifdef DEBUG /* Sigh. Some compilers never learn. */
if (eptr >= md->end_subject)
printf("matching subject <null> against pattern ");
else
@@ -2824,7 +2841,7 @@ for (;;)
}
pchars(ecode, length, FALSE, md);
printf("\n");
- #endif
+#endif
if (length > md->end_subject - eptr) return FALSE;
if (md->caseless)
@@ -2881,10 +2898,8 @@ for (;;)
maximum. Alternatively, if maximizing, find the maximum number of
characters and work backwards. */
- #ifdef DEBUG
- printf("matching %c{%d,%d} against subject %.*s\n", c, min, max,
- max, eptr);
- #endif
+ DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
+ max, eptr));
if (md->caseless)
{
@@ -2949,7 +2964,7 @@ for (;;)
/* Match a negated single character */
case OP_NOT:
- if (eptr > md->end_subject) return FALSE;
+ if (eptr >= md->end_subject) return FALSE;
ecode++;
if (md->caseless)
{
@@ -3008,10 +3023,8 @@ for (;;)
maximum. Alternatively, if maximizing, find the maximum number of
characters and work backwards. */
- #ifdef DEBUG
- printf("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
- max, eptr);
- #endif
+ DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
+ max, eptr));
if (md->caseless)
{
@@ -3261,9 +3274,7 @@ for (;;)
/* There's been some horrible disaster. */
default:
- #ifdef DEBUG
- printf("Unknown opcode %d\n", *ecode);
- #endif
+ DPRINTF(("Unknown opcode %d\n", *ecode));
md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
return FALSE;
}
@@ -3279,6 +3290,28 @@ for (;;)
/*************************************************
+* Segregate setjmp() *
+*************************************************/
+
+/* The -Wall option of gcc gives warnings for all local variables when setjmp()
+is used, even if the coding conforms to the rules of ANSI C. To avoid this, we
+hide it in a separate function. This is called only when PCRE_EXTRA is set,
+since it's needed only for the extension \X option, and with any luck, a good
+compiler will spot the tail recursion and compile it efficiently.
+
+Arguments: The block containing the match data
+Returns: The return from setjump()
+*/
+
+static int
+my_setjmp(match_data *match_block)
+{
+return setjmp(match_block->fail_env);
+}
+
+
+
+/*************************************************
* Execute a Regular Expression *
*************************************************/
@@ -3310,7 +3343,7 @@ int ocount = offsetcount;
int first_char = -1;
match_data match_block;
const uschar *start_bits = NULL;
-const uschar *start_match = (uschar *)subject;
+const uschar *start_match = (const uschar *)subject;
const uschar *end_subject;
const real_pcre *re = (const real_pcre *)external_re;
const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
@@ -3351,9 +3384,7 @@ if (re->top_backref > 0 && re->top_backref + 1 >= ocount/2)
ocount = re->top_backref * 2 + 2;
match_block.offset_vector = (pcre_malloc)(ocount * sizeof(int));
if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
- #ifdef DEBUG
- printf("Got memory to hold back references\n");
- #endif
+ DPRINTF(("Got memory to hold back references\n"));
}
else match_block.offset_vector = offsets;
@@ -3406,6 +3437,7 @@ if (!anchored)
do
{
+ int rc;
register int *iptr = match_block.offset_vector;
register int *iend = iptr + resetcount;
@@ -3447,11 +3479,11 @@ do
}
}
- #ifdef DEBUG
+#ifdef DEBUG /* Sigh. Some compilers never learn. */
printf(">>>> Match against: ");
pchars(start_match, end_subject - start_match, TRUE, &match_block);
printf("\n");
- #endif
+#endif
/* When a match occurs, substrings will be set for all internal extractions;
we just need to set up the whole thing as substring 0 before returning. If
@@ -3461,54 +3493,48 @@ do
if certain parts of the pattern were not used.
Before starting the match, we have to set up a longjmp() target to enable
- the "cut" operation to fail a match completely without backtracking. */
-
- if (setjmp(match_block.fail_env) == 0 &&
- match(start_match, re->code, 2, &match_block))
- {
- int rc;
+ the "cut" operation to fail a match completely without backtracking. This
+ is done in a separate function to avoid compiler warnings. We need not do
+ it unless PCRE_EXTRA is set, since only in that case is the "cut" operation
+ enabled. */
- if (ocount != offsetcount)
- {
- if (offsetcount >= 4)
- {
- memcpy(offsets + 2, match_block.offset_vector + 2,
- (offsetcount - 2) * sizeof(int));
- #ifdef DEBUG
- printf("Copied offsets; freeing temporary memory\n");
- #endif
- }
- if (match_block.end_offset_top > offsetcount)
- match_block.offset_overflow = TRUE;
+ if (((re->options & PCRE_EXTRA) != 0 && my_setjmp(&match_block) != 0) ||
+ !match(start_match, re->code, 2, &match_block))
+ continue;
- #ifdef DEBUG
- printf("Freeing temporary memory\n");
- #endif
+ /* Copy the offset information from temporary store if necessary */
- (pcre_free)(match_block.offset_vector);
+ if (ocount != offsetcount)
+ {
+ if (offsetcount >= 4)
+ {
+ memcpy(offsets + 2, match_block.offset_vector + 2,
+ (offsetcount - 2) * sizeof(int));
+ DPRINTF(("Copied offsets; freeing temporary memory\n"));
}
+ if (match_block.end_offset_top > offsetcount)
+ match_block.offset_overflow = TRUE;
- rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
+ DPRINTF(("Freeing temporary memory\n"));
+ (pcre_free)(match_block.offset_vector);
+ }
- if (match_block.offset_end < 2) rc = 0; else
- {
- offsets[0] = start_match - match_block.start_subject;
- offsets[1] = match_block.end_match_ptr - match_block.start_subject;
- }
+ rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
- #ifdef DEBUG
- printf(">>>> returning %d\n", rc);
- #endif
- return rc;
+ if (match_block.offset_end < 2) rc = 0; else
+ {
+ offsets[0] = start_match - match_block.start_subject;
+ offsets[1] = match_block.end_match_ptr - match_block.start_subject;
}
+
+ DPRINTF((">>>> returning %d\n", rc));
+ return rc;
}
while (!anchored &&
match_block.errorcode == PCRE_ERROR_NOMATCH &&
start_match++ < end_subject);
-#ifdef DEBUG
-printf(">>>> returning %d\n", match_block.errorcode);
-#endif
+DPRINTF((">>>> returning %d\n", match_block.errorcode));
return match_block.errorcode;
}
diff --git a/pcre.h b/pcre.h
index c6b3612..c82b73a 100644
--- a/pcre.h
+++ b/pcre.h
@@ -10,6 +10,7 @@
/* Have to include stdlib.h in order to ensure that size_t is defined;
it is needed here for malloc. */
+#include <sys/types.h>
#include <stdlib.h>
/* Options */
diff --git a/pcretest.c b/pcretest.c
index 64ec216..5d5eec5 100644
--- a/pcretest.c
+++ b/pcretest.c
@@ -157,7 +157,8 @@ for(;;)
case OP_REF:
printf(" \\%d", *(++code));
- break;
+ code++;
+ goto CLASS_REF_REPEAT;
case OP_CLASS:
{
@@ -187,6 +188,8 @@ for(;;)
printf("]");
code += 32;
+ CLASS_REF_REPEAT:
+
switch(*code)
{
case OP_CRSTAR:
@@ -581,7 +584,7 @@ for (;;)
for (;;)
{
- unsigned char *pp;
+ unsigned char *q;
int count, c;
int offsets[30];
int size_offsets = sizeof(offsets)/sizeof(int);
@@ -600,7 +603,7 @@ for (;;)
p = buffer;
while (isspace(*p)) p++;
- pp = dbuffer;
+ q = dbuffer;
while ((c = *p++) != 0)
{
int i = 0;
@@ -662,17 +665,17 @@ for (;;)
case 'O':
while(isdigit(*p)) n = n * 10 + *p++ - '0';
- if (n <= (int)sizeof(offsets)/sizeof(int)) size_offsets = n;
+ if (n <= (int)(sizeof(offsets)/sizeof(int))) size_offsets = n;
continue;
case 'Z':
options |= PCRE_NOTEOL;
continue;
}
- *pp++ = c;
+ *q++ = c;
}
- *pp = 0;
- len = pp - dbuffer;
+ *q = 0;
+ len = q - dbuffer;
/* Handle matching via the POSIX interface, which does not
support timing. */
diff --git a/testinput b/testinput
index 0c00e7f..de98e81 100644
--- a/testinput
+++ b/testinput
@@ -1489,12 +1489,12 @@
abc\100\60
/abc\81/
- abc\081
- abc\0\x38\x31
+ abc\081
+ abc\0\x38\x31
/abc\91/
- abc\091
- abc\0\x39\x31
+ abc\091
+ abc\0\x39\x31
/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\12\123/
abcdefghijkllS
@@ -1534,18 +1534,45 @@
baccd
/[^a]/
- Abc
+ Abc
/[^a]/i
- Abc
+ Abc
/[^a]+/
- AAAaAbc
+ AAAaAbc
/[^a]+/i
- AAAaAbc
+ AAAaAbc
/[^a]+/
- bbb\nccc
+ bbb\nccc
+
+/[^k]$/
+ abc
+ *** Failers
+ abk
+
+/[^k]{2,3}$/
+ abc
+ kbc
+ kabc
+ *** Failers
+ abk
+ akb
+ akk
+
+/^\d{8,}\@.+[^k]$/
+ 12345678\@a.b.c.d
+ 123456789\@x.y.z
+ *** Failers
+ 12345678\@x.y.uk
+ 1234567\@a.b.c.d
+
+/(a)\1{8,}/
+ aaaaaaaaa
+ aaaaaaaaaa
+ *** Failers
+ aaaaaaa
/ End of test input /
diff --git a/testinput2 b/testinput2
index 5542437..0cdb18b 100644
--- a/testinput2
+++ b/testinput2
@@ -263,4 +263,8 @@
/((?>a*?))*/X
+/)/
+
+/a[]b/
+
/ End of test input /
diff --git a/testoutput b/testoutput
index 14745c4..3596b2a 100644
--- a/testoutput
+++ b/testoutput
@@ -1,5 +1,5 @@
Testing Perl-Compatible Regular Expressions
-PCRE version 1.02 12-Dec-1997
+PCRE version 1.03 18-Dec-1997
/the quick brown fox/
the quick brown fox
@@ -2165,15 +2165,15 @@ No match
1: abc
/abc\81/
- abc\081
+ abc\081
0: abc\x0081
- abc\0\x38\x31
+ abc\0\x38\x31
0: abc\x0081
/abc\91/
- abc\091
+ abc\091
0: abc\x0091
- abc\0\x39\x31
+ abc\0\x39\x31
0: abc\x0091
/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\12\123/
@@ -2275,24 +2275,72 @@ No match
No match
/[^a]/
- Abc
+ Abc
0: A
/[^a]/i
- Abc
+ Abc
0: b
/[^a]+/
- AAAaAbc
+ AAAaAbc
0: AAA
/[^a]+/i
- AAAaAbc
+ AAAaAbc
0: bc
/[^a]+/
- bbb\nccc
+ bbb\nccc
0: bbb\x0accc
+
+/[^k]$/
+ abc
+ 0: c
+ *** Failers
+ 0: s
+ abk
+No match
+
+/[^k]{2,3}$/
+ abc
+ 0: abc
+ kbc
+ 0: bc
+ kabc
+ 0: abc
+ *** Failers
+ 0: ers
+ abk
+No match
+ akb
+No match
+ akk
+No match
+
+/^\d{8,}\@.+[^k]$/
+ 12345678\@a.b.c.d
+ 0: 12345678@a.b.c.d
+ 123456789\@x.y.z
+ 0: 123456789@x.y.z
+ *** Failers
+No match
+ 12345678\@x.y.uk
+No match
+ 1234567\@a.b.c.d
+No match
+
+/(a)\1{8,}/
+ aaaaaaaaa
+ 0: aaaaaaaaa
+ 1: a
+ aaaaaaaaaa
+ 0: aaaaaaaaaa
+ 1: a
+ *** Failers
+No match
+ aaaaaaa
+No match
/ End of test input /
diff --git a/testoutput2 b/testoutput2
index 4034a2e..23da939 100644
--- a/testoutput2
+++ b/testoutput2
@@ -1,5 +1,5 @@
Testing Perl-Compatible Regular Expressions
-PCRE version 1.02 12-Dec-1997
+PCRE version 1.03 18-Dec-1997
/(a)b|/
Identifying subpattern count = 1
@@ -599,6 +599,12 @@ Failed: operand of unlimited repeat could match the empty string at offset 8
/((?>a*?))*/X
Failed: operand of unlimited repeat could match the empty string at offset 9
+/)/
+Failed: unmatched brackets at offset 0
+
+/a[]b/
+Failed: missing terminating ] for character class at offset 4
+
/ End of test input /
Identifying subpattern count = 0
No options