Skip to content

Commit 7bee5bd

Browse files
authored
Add some substring function tests
1 parent 86fdfdb commit 7bee5bd

File tree

6 files changed

+163
-29
lines changed

6 files changed

+163
-29
lines changed

doc/html/pcre2_substring_length_byname.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ <h2>
3131
<pre>
3232
<i>match_data</i> The match data block for the match
3333
<i>name</i> The substring name
34-
<i>length</i> Where to return the length
34+
<i>length</i> Where to return the length, or NULL
3535
</pre>
36-
The yield is zero on success, or an error code if the substring is not found.
36+
The third argument may be NULL if all you want to know is whether or not a
37+
substring is set. The yield is zero on success, or a negative error code
38+
otherwise.
3739
</p>
3840
<p>
3941
There is a complete description of the PCRE2 native API in the

doc/pcre2_substring_length_byname.3

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ The arguments are:
1919
.sp
2020
\fImatch_data\fP The match data block for the match
2121
\fIname\fP The substring name
22-
\fIlength\fP Where to return the length
22+
\fIlength\fP Where to return the length, or NULL
2323
.sp
24-
The yield is zero on success, or an error code if the substring is not found.
24+
The third argument may be NULL if all you want to know is whether or not a
25+
substring is set. The yield is zero on success, or a negative error code
26+
otherwise.
2527
.P
2628
There is a complete description of the PCRE2 native API in the
2729
.\" HREF

src/pcre2_substring.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ permits duplicate names, the first substring that is set is chosen.
255255
Arguments:
256256
match_data pointer to match data
257257
stringname the name of the required substring
258-
sizeptr where to put the length
258+
sizeptr where to put the length, if not NULL
259259
260260
Returns: 0 if successful, else a negative error number
261261
*/
@@ -338,8 +338,15 @@ else /* Matched using pcre2_dfa_match() */
338338

339339
left = match_data->ovector[stringnumber*2];
340340
right = match_data->ovector[stringnumber*2+1];
341+
/* LCOV_EXCL_START - this appears to be unreachable, as the ovector and
342+
subject_length should always be set consistently, no matter what misbehaviour
343+
the caller has committed. */
341344
if (left > match_data->subject_length || right > match_data->subject_length)
345+
{
346+
PCRE2_DEBUG_UNREACHABLE();
342347
return PCRE2_ERROR_INVALIDOFFSET;
348+
}
349+
/* LCOV_EXCL_STOP */
343350
if (sizeptr != NULL) *sizeptr = (left > right)? 0 : right - left;
344351
return 0;
345352
}

src/pcre2test_inc.h

Lines changed: 138 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3493,7 +3493,7 @@ uint8_t *nptr;
34933493

34943494
for (i = 0; i < MAXCPYGET && dat_datctl.copy_numbers[i] >= 0; i++)
34953495
{
3496-
int rc;
3496+
int rc, rc2;
34973497
PCRE2_SIZE length, length2;
34983498
PCRE2_UCHAR copybuffer[256];
34993499
uint32_t n = (uint32_t)(dat_datctl.copy_numbers[i]);
@@ -3506,29 +3506,29 @@ for (i = 0; i < MAXCPYGET && dat_datctl.copy_numbers[i] >= 0; i++)
35063506
}
35073507
else
35083508
{
3509-
rc = pcre2_substring_length_bynumber(match_data, n, &length2);
3510-
if (rc < 0)
3511-
{
3512-
fprintf(outfile, "Get substring %d length failed (%d): ", n, rc);
3513-
if (!print_error_message(rc, "", "\n")) return FALSE;
3514-
}
3515-
else if (length2 != length)
3516-
{
3517-
fprintf(outfile, "Mismatched substring lengths: %"
3518-
SIZ_FORM " %" SIZ_FORM "\n", length, length2);
3519-
}
35203509
fprintf(outfile, "%2dC ", n);
35213510
pchars(copybuffer, length, utf, outfile);
35223511
fprintf(outfile, " (%" SIZ_FORM ")\n", length);
35233512
}
3513+
rc2 = pcre2_substring_length_bynumber(match_data, n, &length2);
3514+
if (rc2 < 0)
3515+
{
3516+
fprintf(outfile, "Get substring %d length failed (%d): ", n, rc2);
3517+
if (!print_error_message(rc2, "", "\n")) return FALSE;
3518+
}
3519+
else if (rc >= 0 && length2 != length)
3520+
{
3521+
fprintf(outfile, "Mismatched substring lengths: %"
3522+
SIZ_FORM " %" SIZ_FORM "\n", length, length2);
3523+
}
35243524
}
35253525

35263526
/* Test copy strings by name */
35273527

35283528
nptr = dat_datctl.copy_names;
35293529
for (;;)
35303530
{
3531-
int rc;
3531+
int rc, rc2;
35323532
int groupnumber;
35333533
PCRE2_SIZE length, length2;
35343534
PCRE2_UCHAR copybuffer[256];
@@ -3564,23 +3564,23 @@ for (;;)
35643564
}
35653565
else
35663566
{
3567-
rc = pcre2_substring_length_byname(match_data, pbuffer, &length2);
3568-
if (rc < 0)
3569-
{
3570-
fprintf(outfile, "Get substring \"%s\" length failed (%d): ", nptr, rc);
3571-
if (!print_error_message(rc, "", "\n")) return FALSE;
3572-
}
3573-
else if (length2 != length)
3574-
{
3575-
fprintf(outfile, "Mismatched substring lengths: %"
3576-
SIZ_FORM " %" SIZ_FORM "\n", length, length2);
3577-
}
35783567
fprintf(outfile, " C ");
35793568
pchars(copybuffer, length, utf, outfile);
35803569
fprintf(outfile, " (%" SIZ_FORM ") %s", length, nptr);
35813570
if (groupnumber >= 0) fprintf(outfile, " (group %d)\n", groupnumber);
35823571
else fprintf(outfile, " (non-unique)\n");
35833572
}
3573+
rc2 = pcre2_substring_length_byname(match_data, pbuffer, &length2);
3574+
if (rc2 < 0)
3575+
{
3576+
fprintf(outfile, "Get substring \"%s\" length failed (%d): ", nptr, rc2);
3577+
if (!print_error_message(rc2, "", "\n")) return FALSE;
3578+
}
3579+
else if (rc >= 0 && length2 != length)
3580+
{
3581+
fprintf(outfile, "Mismatched substring lengths: %"
3582+
SIZ_FORM " %" SIZ_FORM "\n", length, length2);
3583+
}
35843584
nptr += namelen + 1;
35853585
}
35863586

@@ -5441,6 +5441,7 @@ unittest(void)
54415441
int rc;
54425442
uint32_t uval;
54435443
PCRE2_SIZE sizeval;
5444+
PCRE2_UCHAR *sptrval;
54445445
const char *failure = NULL;
54455446
pcre2_general_context *test_gen_context = NULL, *test_gen_context_copy = NULL;
54465447
pcre2_compile_context *test_pat_context = NULL, *test_pat_context_copy = NULL;
@@ -5454,6 +5455,13 @@ PCRE2_UCHAR callout_int_pattern[] = {
54545455
PCRE2_UCHAR callout_str_pattern[] = {
54555456
CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK, CHAR_C, CHAR_QUOTATION_MARK,
54565457
CHAR_Z, CHAR_QUOTATION_MARK, CHAR_RIGHT_PARENTHESIS, 0 };
5458+
PCRE2_UCHAR capture_pattern[] = {
5459+
CHAR_A, CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK, CHAR_LESS_THAN_SIGN,
5460+
CHAR_N, CHAR_GREATER_THAN_SIGN, CHAR_DOT, CHAR_ASTERISK,
5461+
CHAR_RIGHT_PARENTHESIS, CHAR_Z, 0 };
5462+
PCRE2_UCHAR subject_abcz[] = {
5463+
CHAR_A, CHAR_B, CHAR_C, CHAR_Z, 0 };
5464+
PCRE2_UCHAR name_n[] = { CHAR_N, 0 };
54575465
#ifdef BITOTHER
54585466
G(pcre2_code_,BITOTHER) *bitother_code = NULL;
54595467
G(PCRE2_,G(UCHAR,BITOTHER)) bitother_pattern[] = { CHAR_A, CHAR_B, CHAR_C, 0 };
@@ -5467,6 +5475,9 @@ regex_t test_preg;
54675475
#endif
54685476
void *invalid_code = NULL;
54695477
const uint8_t *test_tables = NULL;
5478+
PCRE2_UCHAR copy_buf[64];
5479+
PCRE2_UCHAR **stringlist;
5480+
PCRE2_SIZE *lengthslist;
54705481

54715482
#if PCRE2_CODE_UNIT_WIDTH == 8
54725483
memset(&test_preg, 0, sizeof(test_preg));
@@ -5864,6 +5875,109 @@ errorcode = -123;
58645875
rc = pcre2_callout_enumerate(test_compiled_code, callout_enumerate_function_fail, &errorcode);
58655876
ASSERT(rc == -123, "pcre2_callout_enumerate(fail)");
58665877

5878+
/* ---------------------- Substring functions ------------------------------ */
5879+
5880+
/* Must handle NULL without crashing. */
5881+
pcre2_substring_free(NULL);
5882+
pcre2_substring_list_free(NULL);
5883+
5884+
pcre2_code_free(test_compiled_code);
5885+
test_compiled_code = pcre2_compile(capture_pattern, PCRE2_ZERO_TERMINATED,
5886+
0, &errorcode, &erroroffset, NULL);
5887+
ASSERT(test_compiled_code != NULL, "test pattern compilation");
5888+
5889+
pcre2_match_data_free(test_match_data);
5890+
test_match_data = pcre2_match_data_create_from_pattern(
5891+
test_compiled_code, test_gen_context);
5892+
ASSERT(test_match_data != NULL, "pcre2_match_data_create()");
5893+
5894+
rc = pcre2_match(test_compiled_code, subject_abcz, PCRE2_ZERO_TERMINATED, 0,
5895+
0, test_match_data, NULL);
5896+
ASSERT(rc == 2, "pcre2_match()");
5897+
5898+
/* Test the functions with insufficient buffer size. It hardly seems worth
5899+
adding controls to the pcre2test input file format to exercise this case. */
5900+
5901+
sizeval = 2;
5902+
rc = pcre2_substring_copy_byname(test_match_data, name_n, copy_buf, &sizeval);
5903+
ASSERT(rc == PCRE2_ERROR_NOMEMORY && sizeval == 2, "pcre2_substring_copy_byname(small buffer)");
5904+
sizeval = 3;
5905+
rc = pcre2_substring_copy_byname(test_match_data, name_n, copy_buf, &sizeval);
5906+
ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_copy_byname(small buffer)");
5907+
sizeval = 4;
5908+
rc = pcre2_substring_copy_byname(test_match_data, name_n, copy_buf, &sizeval);
5909+
ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_copy_byname(small buffer)");
5910+
5911+
sizeval = 2;
5912+
rc = pcre2_substring_copy_bynumber(test_match_data, 1, copy_buf, &sizeval);
5913+
ASSERT(rc == PCRE2_ERROR_NOMEMORY && sizeval == 2, "pcre2_substring_copy_bynumber(small buffer)");
5914+
sizeval = 3;
5915+
rc = pcre2_substring_copy_bynumber(test_match_data, 1, copy_buf, &sizeval);
5916+
ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_copy_bynumber(small buffer)");
5917+
5918+
mallocs_until_failure = 0;
5919+
5920+
sizeval = 0;
5921+
sptrval = NULL;
5922+
rc = pcre2_substring_get_byname(test_match_data, name_n, &sptrval, &sizeval);
5923+
ASSERT(rc == PCRE2_ERROR_NOMEMORY && sptrval == NULL, "pcre2_substring_get_byname(small buffer)");
5924+
5925+
sizeval = 0;
5926+
rc = pcre2_substring_get_bynumber(test_match_data, 1, &sptrval, &sizeval);
5927+
ASSERT(rc == PCRE2_ERROR_NOMEMORY && sptrval == NULL, "pcre2_substring_get_bynumber(small buffer)");
5928+
5929+
mallocs_until_failure = INT_MAX;
5930+
5931+
/* Test some unusual conditions, for which again it doesn't seem worth adding
5932+
pcre2test controls. */
5933+
5934+
sizeval = 0;
5935+
rc = pcre2_substring_length_bynumber(test_match_data, 1, &sizeval);
5936+
ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_length_bynumber()");
5937+
rc = pcre2_substring_length_bynumber(test_match_data, 1, NULL);
5938+
ASSERT(rc == 0, "pcre2_substring_length_bynumber()");
5939+
5940+
sizeval = 0;
5941+
rc = pcre2_substring_length_byname(test_match_data, name_n, &sizeval);
5942+
ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_length_byname()");
5943+
rc = pcre2_substring_length_byname(test_match_data, name_n, NULL);
5944+
ASSERT(rc == 0, "pcre2_substring_length_byname()");
5945+
5946+
/* Test pcre2_substring_list_get() with some NULL inputs. */
5947+
5948+
rc = pcre2_substring_list_get(test_match_data, &stringlist, &lengthslist);
5949+
ASSERT(rc == 0 && stringlist != NULL && lengthslist != NULL, "pcre2_substring_list_get()");
5950+
pcre2_substring_list_free(stringlist);
5951+
5952+
stringlist = NULL;
5953+
rc = pcre2_substring_list_get(test_match_data, &stringlist, NULL);
5954+
ASSERT(rc == 0 && stringlist != NULL, "pcre2_substring_list_get()");
5955+
pcre2_substring_list_free(stringlist);
5956+
5957+
mallocs_until_failure = 0;
5958+
5959+
stringlist = NULL;
5960+
rc = pcre2_substring_list_get(test_match_data, &stringlist, &lengthslist);
5961+
ASSERT(rc == PCRE2_ERROR_NOMEMORY && stringlist == NULL, "pcre2_substring_list_get()");
5962+
5963+
mallocs_until_failure = INT_MAX;
5964+
5965+
/* Test after an unsuccessful match. */
5966+
5967+
rc = pcre2_match(test_compiled_code, subject_abcz, PCRE2_ZERO_TERMINATED, 2,
5968+
0, test_match_data, NULL);
5969+
ASSERT(rc == PCRE2_ERROR_NOMATCH, "pcre2_match()");
5970+
5971+
sizeval = 4;
5972+
rc = pcre2_substring_copy_byname(test_match_data, name_n, copy_buf, &sizeval);
5973+
ASSERT(rc == PCRE2_ERROR_NOMATCH, "pcre2_substring_copy_byname(no match)");
5974+
rc = pcre2_substring_copy_bynumber(test_match_data, 1, copy_buf, &sizeval);
5975+
ASSERT(rc == PCRE2_ERROR_NOMATCH, "pcre2_substring_copy_bynumber(no match)");
5976+
rc = pcre2_substring_get_byname(test_match_data, name_n, &sptrval, &sizeval);
5977+
ASSERT(rc == PCRE2_ERROR_NOMATCH && sptrval == NULL, "pcre2_substring_get_byname(no match)");
5978+
rc = pcre2_substring_get_bynumber(test_match_data, 1, &sptrval, &sizeval);
5979+
ASSERT(rc == PCRE2_ERROR_NOMATCH && sptrval == NULL, "pcre2_substring_get_bynumber(no match)");
5980+
58675981
/* ------------------------------------------------------------------------- */
58685982

58695983
#undef ASSERT

testdata/testoutput2

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ Subject length lower bound = 4
10071007
1: a
10081008
2: d
10091009
Copy substring 5 failed (-49): unknown substring
1010+
Get substring 5 length failed (-49): unknown substring
10101011

10111012
/(.{20})/I
10121013
Capture group count = 1
@@ -4594,6 +4595,7 @@ Subject length lower bound = 8
45944595
2: gh
45954596
Number not found for group "three"
45964597
Copy substring "three" failed (-49): unknown substring
4598+
Get substring "three" length failed (-49): unknown substring
45974599

45984600
/(?P<Tes>)(?P<Test>)/IB
45994601
------------------------------------------------------------------
@@ -5977,6 +5979,7 @@ Subject length lower bound = 2
59775979
2: a1
59785980
Number not found for group "Z"
59795981
Copy substring "Z" failed (-49): unknown substring
5982+
Get substring "Z" length failed (-49): unknown substring
59805983
C a1 (2) A (non-unique)
59815984

59825985
/(?|(?<a>)(?<b>)(?<a>)|(?<a>)(?<b>)(?<a>))/I,dupnames
@@ -6020,6 +6023,7 @@ Subject length lower bound = 2
60206023
cd\=copy=A
60216024
0: cd
60226025
Copy substring "A" failed (-55): requested value is not set
6026+
Get substring "A" length failed (-55): requested value is not set
60236027

60246028
/^(?P<A>a)(?P<A>b)|cd(?P<A>ef)(?P<A>gh)/I,dupnames
60256029
Capture group count = 4
@@ -14574,6 +14578,7 @@ Start of matched string is beyond its end - displaying from end to start.
1457414578
Matched, but too many substrings
1457514579
0: a
1457614580
Copy substring "A" failed (-54): requested value is not available
14581+
Get substring "A" length failed (-54): requested value is not available
1457714582
Get substring 2 failed (-54): requested value is not available
1457814583
Get substring "A" failed (-54): requested value is not available
1457914584
a\=ovector=2,copy=A,get=A,get=2
@@ -14587,6 +14592,7 @@ Matched, but too many substrings
1458714592
0: b
1458814593
1: <unset>
1458914594
Copy substring "A" failed (-55): requested value is not set
14595+
Get substring "A" length failed (-55): requested value is not set
1459014596
Get substring 2 failed (-54): requested value is not available
1459114597
Get substring "A" failed (-55): requested value is not set
1459214598

@@ -14595,6 +14601,7 @@ Get substring "A" failed (-55): requested value is not set
1459514601
Partial match: abc
1459614602
0C abc (3)
1459714603
Copy substring 1 failed (-2): partial match
14604+
Get substring 1 length failed (-2): partial match
1459814605
get substring list failed (-2): partial match
1459914606

1460014607
/^abc/info

testdata/testoutput6

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7502,6 +7502,7 @@ Get substring "A" failed (-41): function is not supported for DFA matching
75027502
aa\=copy=A
75037503
0: aa
75047504
Copy substring "A" failed (-41): function is not supported for DFA matching
7505+
Get substring "A" length failed (-41): function is not supported for DFA matching
75057506

75067507
/a+/no_auto_possess
75077508
a\=ovector=2,get=1,get=2,getall
@@ -7523,6 +7524,7 @@ Get substring 2 failed (-54): requested value is not available
75237524
Partial match: abc
75247525
0C abc (3)
75257526
Copy substring 1 failed (-2): partial match
7527+
Get substring 1 length failed (-2): partial match
75267528
get substring list failed (-2): partial match
75277529

75287530
/ab(?C" any text with spaces ")cde/B

0 commit comments

Comments
 (0)