Improve testing coverage with updates to pcre2test and test files; also get rid

of redundant code in pcre2_match().
This commit is contained in:
Philip.Hazel 2017-04-16 13:03:30 +00:00
parent 87094fac10
commit 202cb2cf41
15 changed files with 1583 additions and 428 deletions

View File

@ -137,6 +137,9 @@ particular when it is serialized.
26. Correct an incorrect cast in pcre2_valid_utf.c
27. Update pcre2test, remove some unused code in pcre2_match(), and upgrade the
tests to improve coverage.
Version 10.23 14-February-2017
------------------------------

View File

@ -298,13 +298,13 @@ else /* String callout */
cb.callout_string_length =
*lengthptr - (1 + 4*LINK_SIZE) - 2;
}
/* The original matching code (pre 10.30) worked directly with the ovector
passed by the user, and this was passed to callouts. Now that the working
ovector is in the backtracking frame, it no longer needs to reserve space for
the overall match offsets (which would waste space in the frame). For backward
compatibility, however, we pass capture_top and offset_vector to the callout as
if for the extended ovector, and we ensure that the first two slots are unset
if for the extended ovector, and we ensure that the first two slots are unset
by preserving and restoring their current contents. */
save0 = Fovector[-2];
@ -628,7 +628,7 @@ if (N >= mb->match_frames_top)
if ((newsize / 1024) > mb->heap_limit)
{
PCRE2_SIZE maxsize = ((mb->heap_limit * 1024)/frame_size) * frame_size;
if (mb->frame_vector_size == maxsize) return PCRE2_ERROR_HEAPLIMIT;
if (mb->frame_vector_size >= maxsize) return PCRE2_ERROR_HEAPLIMIT;
newsize = maxsize;
}
@ -810,15 +810,15 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
RRETURN(MATCH_NOMATCH);
/* Also fail if PCRE2_ENDANCHORED is set and the end of the match is not
the end of the subject. After (*ACCEPT) we fail the entire match (at this
the end of the subject. After (*ACCEPT) we fail the entire match (at this
position) but backtrack on reaching the end of the pattern. */
if (Feptr < mb->end_subject &&
((mb->moptions | mb->poptions) & PCRE2_ENDANCHORED) != 0)
{
{
if (Fop == OP_END) RRETURN(MATCH_NOMATCH);
return MATCH_NOMATCH;
}
return MATCH_NOMATCH;
}
/* We have a successful match of the whole pattern. Record the result and
then do a direct return from the function. If there is space in the offset
@ -3057,16 +3057,20 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
Feptr += Lmin;
break;
/* This OP_ANYBYTE case will never be reached because \C gets turned
into OP_ALLANY in non-UTF mode. Cut out the code so that coverage
reports don't complain about it's never being used. */
case OP_ANYBYTE:
if (Feptr > mb->end_subject - Lmin)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
Feptr += Lmin;
break;
/* case OP_ANYBYTE:
* if (Feptr > mb->end_subject - Lmin)
* {
* SCHECK_PARTIAL();
* RRETURN(MATCH_NOMATCH);
* }
* Feptr += Lmin;
* break;
*/
case OP_ANYNL:
for (i = 1; i <= Lmin; i++)
{
@ -3573,6 +3577,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
switch(fc)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
if (Feptr < mb->end_subject && UCHAR21(Feptr) == CHAR_LF) Feptr++;
break;
@ -3700,6 +3705,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
switch(fc)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
if (Feptr < mb->end_subject && *Feptr == CHAR_LF) Feptr++;
break;
@ -5004,15 +5010,10 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
Lnext_branch = Fecode + GET(Fecode, 1);
if (*Lnext_branch != OP_ALT) break;
/* This is never the final branch */
/* This is never the final branch. We do not need to test for MATCH_THEN
here because this code is not used when there is a THEN in the pattern. */
RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM1);
if (rrc == MATCH_THEN)
{
if (mb->verb_ecode_ptr < Lnext_branch &&
(*Fecode == OP_ALT || *Lnext_branch == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
Fecode = Lnext_branch;
}

View File

@ -324,7 +324,7 @@ extern int valid_utf(PCRE2_SPTR8, PCRE2_SIZE, PCRE2_SIZE *);
/* If we have 8-bit support, default to it; if there is also 16-or 32-bit
support, it can be selected by a command-line option. If there is no 8-bit
support, there must be 16- or 32-bit support, so default to one of them. The
support, there must be 16-bit or 32-bit support, so default to one of them. The
config function, JIT stack, contexts, and version string are the same in all
modes, so use the form of the first that is available. */
@ -336,7 +336,6 @@ modes, so use the form of the first that is available. */
#define PCRE2_REAL_GENERAL_CONTEXT pcre2_real_general_context_8
#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_8
#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_8
#define VERSION_TYPE PCRE2_UCHAR8
#elif defined SUPPORT_PCRE2_16
#define DEFAULT_TEST_MODE PCRE16_MODE
@ -3725,6 +3724,7 @@ static int
pattern_info(int what, void *where, BOOL unsetok)
{
int rc;
PCRE2_PATTERN_INFO(rc, compiled_code, what, NULL); /* Exercise the code */
PCRE2_PATTERN_INFO(rc, compiled_code, what, where);
if (rc >= 0) return 0;
if (rc != PCRE2_ERROR_UNSET || !unsetok)
@ -4056,6 +4056,7 @@ if ((pat_patctl.control & (CTL_BINCODE|CTL_FULLBINCODE)) != 0)
if ((pat_patctl.control & CTL_INFO) != 0)
{
int rc;
void *nametable;
uint8_t *start_bits;
BOOL heap_limit_set, match_limit_set, depth_limit_set;
@ -4064,6 +4065,11 @@ if ((pat_patctl.control & CTL_INFO) != 0)
depth_limit, heap_limit, match_limit, minlength, nameentrysize, namecount,
newline_convention;
/* Exercise the error route. */
PCRE2_PATTERN_INFO(rc, compiled_code, 999, NULL);
(void)rc;
/* These info requests may return PCRE2_ERROR_UNSET. */
switch(pattern_info(PCRE2_INFO_HEAPLIMIT, &heap_limit, TRUE))
@ -5363,7 +5369,7 @@ return PR_OK;
/*************************************************
* Check match or depth limit *
* Check heap, match or depth limit *
*************************************************/
/* This is used for DFA, normal, and JIT fast matching. For DFA matching it
@ -5423,7 +5429,7 @@ for (;;)
else
PCRE2_MATCH(capcount, compiled_code, pp, ulen, dat_datctl.offset,
dat_datctl.options, match_data, PTR(dat_context));
if (capcount == errnumber)
{
min = mid;
@ -6720,7 +6726,7 @@ else for (gmatched = 0;; gmatched++)
if ((dat_datctl.control & CTL_FINDLIMITS) != 0)
{
capcount = 0; /* This stops compiler warnings */
if ((dat_datctl.control & CTL_DFA) == 0)
{
if (FLD(compiled_code, executable_jit) == NULL ||
@ -7484,6 +7490,7 @@ return 0;
int
main(int argc, char **argv)
{
uint32_t temp;
uint32_t yield = 0;
uint32_t op = 1;
BOOL notdone = TRUE;
@ -7528,6 +7535,20 @@ if (PCRE2_CONFIG(PCRE2_CONFIG_VERSION, NULL) !=
return 1;
}
/* Check that bad options are diagnosed. */
if (PCRE2_CONFIG(999, NULL) != PCRE2_ERROR_BADOPTION ||
PCRE2_CONFIG(999, &temp) != PCRE2_ERROR_BADOPTION)
{
fprintf(stderr, "** Error in pcre2_config(): bad option not diagnosed\n");
return 1;
}
/* This configuration option is now obsolete, but running a quick check ensures
that its code is covered. */
(void)PCRE2_CONFIG(PCRE2_CONFIG_STACKRECURSE, &temp);
/* Get buffers from malloc() so that valgrind will check their misuse when
debugging. They grow automatically when very long lines are read. The 16-
and 32-bit buffers (pbuffer16, pbuffer32) are obtained only if needed. */
@ -7571,32 +7592,45 @@ while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
goto EXIT;
}
/* Select operating mode */
/* Select operating mode. Ensure that pcre2_config() is called in 16-bit
and 32-bit modes because that won't happen naturally when 8-bit is also
configured. Also call some other functions that are not otherwise used. This
means that a coverage report won't claim there are uncalled functions. */
if (strcmp(arg, "-8") == 0)
{
#ifdef SUPPORT_PCRE2_8
test_mode = PCRE8_MODE;
(void)pcre2_set_bsr_8(pat_context8, 999);
(void)pcre2_set_newline_8(pat_context8, 999);
#else
fprintf(stderr,
"** This version of PCRE2 was built without 8-bit support\n");
exit(1);
#endif
}
else if (strcmp(arg, "-16") == 0)
{
#ifdef SUPPORT_PCRE2_16
test_mode = PCRE16_MODE;
(void)pcre2_config_16(PCRE2_CONFIG_VERSION, NULL);
(void)pcre2_set_bsr_16(pat_context16, 999);
(void)pcre2_set_newline_16(pat_context16, 999);
#else
fprintf(stderr,
"** This version of PCRE2 was built without 16-bit support\n");
exit(1);
#endif
}
else if (strcmp(arg, "-32") == 0)
{
#ifdef SUPPORT_PCRE2_32
test_mode = PCRE32_MODE;
(void)pcre2_config_32(PCRE2_CONFIG_VERSION, NULL);
(void)pcre2_set_bsr_32(pat_context32, 999);
(void)pcre2_set_newline_32(pat_context32, 999);
#else
fprintf(stderr,
"** This version of PCRE2 was built without 32-bit support\n");
@ -7848,7 +7882,13 @@ max_oveccount = DEFAULT_OVECCOUNT;
G(dat_context,BITS) = G(pcre2_match_context_copy_,BITS)(G(default_dat_context,BITS)); \
G(match_data,BITS) = G(pcre2_match_data_create_,BITS)(max_oveccount, G(general_context,BITS))
/* Call the appropriate functions for the current mode. */
#define CONTEXTTESTS \
(void)G(pcre2_set_max_pattern_length_,BITS)(G(pat_context,BITS), 0); \
(void)G(pcre2_set_offset_limit_,BITS)(G(dat_context,BITS), 0); \
(void)G(pcre2_set_recursion_memory_management_,BITS)(G(dat_context,BITS), my_malloc, my_free, NULL)
/* Call the appropriate functions for the current mode, and exercise some
functions that are not otherwise called. */
#ifdef SUPPORT_PCRE2_8
#undef BITS
@ -7856,6 +7896,7 @@ max_oveccount = DEFAULT_OVECCOUNT;
if (test_mode == PCRE8_MODE)
{
CREATECONTEXTS;
CONTEXTTESTS;
}
#endif
@ -7865,6 +7906,7 @@ if (test_mode == PCRE8_MODE)
if (test_mode == PCRE16_MODE)
{
CREATECONTEXTS;
CONTEXTTESTS;
}
#endif
@ -7874,6 +7916,7 @@ if (test_mode == PCRE16_MODE)
if (test_mode == PCRE32_MODE)
{
CREATECONTEXTS;
CONTEXTTESTS;
}
#endif

3
testdata/testinput1 vendored
View File

@ -5917,4 +5917,7 @@ ef) x/x,mark
/^(?(?!(a)(*ACCEPT))def|abc)/
abc
/^(?1)\d{3}(a)/
a123a
# End of testinput1

View File

@ -165,4 +165,7 @@
/(|]+){2,2452}/
(|]+){2,2452}
/(*LIMIT_HEAP=21)\[(a)]{60}/expand
\[a]{60}
# End of testinput15

191
testdata/testinput2 vendored
View File

@ -5054,4 +5054,195 @@ a)"xI
/(?(VERSION>=999)yes|no)^bc/I
/(*LIMIT_HEAP=0)xxx/I
/\d{0,3}(*:abc)(?C1)xxx/callout_info
# ----------------------------------------------------------------------
# These are a whole pile of tests that touch lines of code that are not
# used by any other tests (at least when these were created).
/^a+?x/i,no_start_optimize,no_auto_possess
\= Expect no match
aaa
/^[^a]{3,}?x/i,no_start_optimize,no_auto_possess
\= Expect no match
bbb
cc
/^X\S/no_start_optimize,no_auto_possess
\= Expect no match
X
/^X\W/no_start_optimize,no_auto_possess
\= Expect no match
X
/^X\H/no_start_optimize,no_auto_possess
\= Expect no match
X
/^X\h/no_start_optimize,no_auto_possess
\= Expect no match
X
/^X\V/no_start_optimize,no_auto_possess
\= Expect no match
X
/^X\v/no_start_optimize,no_auto_possess
\= Expect no match
X
/^X\h/no_start_optimize,no_auto_possess
\= Expect no match
XY
/^X\V/no_start_optimize,no_auto_possess
\= Expect no match
X\n
/^X\v/no_start_optimize,no_auto_possess
\= Expect no match
XX
/^X.+?/s,no_start_optimize,no_auto_possess
\= Expect no match
X
/^X\R+?/no_start_optimize,no_auto_possess
\= Expect no match
XX
/^X\H+?/no_start_optimize,no_auto_possess
\= Expect no match
X
/^X\h+?/no_start_optimize,no_auto_possess
\= Expect no match
X
/^X\V+?/no_start_optimize,no_auto_possess
\= Expect no match
X
X\n
/^X\D+?/no_start_optimize,no_auto_possess
\= Expect no match
X
X9
/^X\S+?/no_start_optimize,no_auto_possess
\= Expect no match
X
X\n
/^X\W+?/no_start_optimize,no_auto_possess
\= Expect no match
X
XX
/^X.+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\n
/(*CRLF)^X.+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\r\=ps
/^X\R+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\nX
X\n\r\n
X\n\rY
X\n\nY
X\n\x{0c}Y
/(*BSR_ANYCRLF)^X\R+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\nX
X\n\r\n
X\n\rY
X\n\nY
X\n\x{0c}Y
/^X\H+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\t
XYY
/^X\h+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\t\t
X\tY
/^X\V+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\n
XYY
/^X\v+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\n\n
X\nY
/^X\D+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY9
XYY
/^X\d+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X99
X9Y
/^X\S+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\n
XYY
/^X\s+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\n\n
X\nY
/^X\W+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X.A
X++
/^X\w+?Z/no_start_optimize,no_auto_possess
\= Expect no match
Xa.
Xaa
/^X.{1,3}Z/s,no_start_optimize,no_auto_possess
\= Expect no match
Xa.bd
/^X\h+Z/no_start_optimize,no_auto_possess
\= Expect no match
X\t\t
X\tY
/^X\V+Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\n
XYY
/^(X(*THEN)Y|AB){0}(?1)/
ABX
\= Expect no match
XAB
/^(?!A(?C1)B)C/
ABC\=callout_error=1
/^(?(?!A(?C1)B)C)/
ABC\=callout_error=1
# ----------------------------------------------------------------------
# End of testinput2

View File

@ -94,4 +94,8 @@
\= Expect no match in 8-bit mode
a\x{100}b
/^ab\C/utf,no_start_optimize
\= Expect no match - tests \C at end of subject
ab
# End of testinput22

13
testdata/testinput4 vendored
View File

@ -1627,6 +1627,11 @@
/[z\x{1f88}]+/i,utf
\x{1f88}\x{1f80}
# Check a reference with more than one other case
/^(\x{00b5})\1{2}$/i,utf
\x{00b5}\x{039c}\x{03bc}
# Characters with more than one other case; test in classes
/[z\x{00b5}]+/i,utf
@ -2288,4 +2293,12 @@
/(?(?=.*b)(?=.*b)\pL|.*c)/
11bb
/^\x{123}+?$/utf,no_auto_possess
\x{123}\x{123}\x{123}
/^\x{123}+?$/i,utf,no_auto_possess
\x{123}\x{122}\x{123}
\= Expect no match
\x{123}\x{124}\x{123}
# End of testinput4

649
testdata/testinput5 vendored

File diff suppressed because it is too large Load Diff

View File

@ -9487,4 +9487,9 @@ No match
0: abc
1: a
/^(?1)\d{3}(a)/
a123a
0: a123a
1: a
# End of testinput1

View File

@ -400,4 +400,8 @@ No match
0:
1:
/(*LIMIT_HEAP=21)\[(a)]{60}/expand
\[a]{60}
Failed: error -63: heap limit exceeded
# End of testinput15

266
testdata/testoutput2 vendored
View File

@ -15607,6 +15607,272 @@ Capturing subpattern count = 0
Last code unit = 'c'
Subject length lower bound = 4
/(*LIMIT_HEAP=0)xxx/I
Capturing subpattern count = 0
Heap limit = 0
First code unit = 'x'
Last code unit = 'x'
Subject length lower bound = 3
/\d{0,3}(*:abc)(?C1)xxx/callout_info
Callout 1 x
# ----------------------------------------------------------------------
# These are a whole pile of tests that touch lines of code that are not
# used by any other tests (at least when these were created).
/^a+?x/i,no_start_optimize,no_auto_possess
\= Expect no match
aaa
No match
/^[^a]{3,}?x/i,no_start_optimize,no_auto_possess
\= Expect no match
bbb
No match
cc
No match
/^X\S/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
/^X\W/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
/^X\H/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
/^X\h/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
/^X\V/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
/^X\v/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
/^X\h/no_start_optimize,no_auto_possess
\= Expect no match
XY
No match
/^X\V/no_start_optimize,no_auto_possess
\= Expect no match
X\n
No match
/^X\v/no_start_optimize,no_auto_possess
\= Expect no match
XX
No match
/^X.+?/s,no_start_optimize,no_auto_possess
\= Expect no match
X
No match
/^X\R+?/no_start_optimize,no_auto_possess
\= Expect no match
XX
No match
/^X\H+?/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
/^X\h+?/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
/^X\V+?/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
X\n
No match
/^X\D+?/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
X9
No match
/^X\S+?/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
X\n
No match
/^X\W+?/no_start_optimize,no_auto_possess
\= Expect no match
X
No match
XX
No match
/^X.+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\n
No match
/(*CRLF)^X.+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\r\=ps
Partial match: XY\x0d
/^X\R+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\nX
No match
X\n\r\n
No match
X\n\rY
No match
X\n\nY
No match
X\n\x{0c}Y
No match
/(*BSR_ANYCRLF)^X\R+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\nX
No match
X\n\r\n
No match
X\n\rY
No match
X\n\nY
No match
X\n\x{0c}Y
No match
/^X\H+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\t
No match
XYY
No match
/^X\h+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\t\t
No match
X\tY
No match
/^X\V+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\n
No match
XYY
No match
/^X\v+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\n\n
No match
X\nY
No match
/^X\D+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY9
No match
XYY
No match
/^X\d+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X99
No match
X9Y
No match
/^X\S+?Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\n
No match
XYY
No match
/^X\s+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X\n\n
No match
X\nY
No match
/^X\W+?Z/no_start_optimize,no_auto_possess
\= Expect no match
X.A
No match
X++
No match
/^X\w+?Z/no_start_optimize,no_auto_possess
\= Expect no match
Xa.
No match
Xaa
No match
/^X.{1,3}Z/s,no_start_optimize,no_auto_possess
\= Expect no match
Xa.bd
No match
/^X\h+Z/no_start_optimize,no_auto_possess
\= Expect no match
X\t\t
No match
X\tY
No match
/^X\V+Z/no_start_optimize,no_auto_possess
\= Expect no match
XY\n
No match
XYY
No match
/^(X(*THEN)Y|AB){0}(?1)/
ABX
0: AB
\= Expect no match
XAB
No match
/^(?!A(?C1)B)C/
ABC\=callout_error=1
--->ABC
1 ^^ B
Failed: error -37: callout error code
/^(?(?!A(?C1)B)C)/
ABC\=callout_error=1
--->ABC
1 ^^ B
Failed: error -37: callout error code
# ----------------------------------------------------------------------
# End of testinput2
Error -64: PCRE2_ERROR_BADDATA (unknown error number)
Error -62: bad serialized data

View File

@ -168,4 +168,9 @@ No match
a\x{100}b
No match
/^ab\C/utf,no_start_optimize
\= Expect no match - tests \C at end of subject
ab
No match
# End of testinput22

18
testdata/testoutput4 vendored
View File

@ -2716,6 +2716,13 @@ No match
\x{1f88}\x{1f80}
0: \x{1f88}\x{1f80}
# Check a reference with more than one other case
/^(\x{00b5})\1{2}$/i,utf
\x{00b5}\x{039c}\x{03bc}
0: \x{b5}\x{39c}\x{3bc}
1: \x{b5}
# Characters with more than one other case; test in classes
/[z\x{00b5}]+/i,utf
@ -3711,4 +3718,15 @@ No match
11bb
0: b
/^\x{123}+?$/utf,no_auto_possess
\x{123}\x{123}\x{123}
0: \x{123}\x{123}\x{123}
/^\x{123}+?$/i,utf,no_auto_possess
\x{123}\x{122}\x{123}
0: \x{123}\x{122}\x{123}
\= Expect no match
\x{123}\x{124}\x{123}
No match
# End of testinput4

743
testdata/testoutput5 vendored

File diff suppressed because it is too large Load Diff