Fix crash in pcre2_substitute() with NULL match context.

This commit is contained in:
Philip.Hazel 2019-03-11 17:29:08 +00:00
parent 590f65f061
commit e85de98d0a
8 changed files with 70 additions and 40 deletions

View File

@ -2,8 +2,8 @@ Change Log for PCRE2
-------------------- --------------------
Version 10.33-RC1 03-March-2019 Version 10.33 11-March-2019
------------------------------- ---------------------------
1. Added "allvector" to pcre2test to make it easy to check the part of the 1. Added "allvector" to pcre2test to make it easy to check the part of the
ovector that shouldn't be changed, in particular after substitute and failed or ovector that shouldn't be changed, in particular after substitute and failed or
@ -12,7 +12,9 @@ partial matches.
2. Fix subject buffer overread in JIT when UTF is disabled and \X or \R has 2. Fix subject buffer overread in JIT when UTF is disabled and \X or \R has
a greater than 1 fixed quantifier. This issue was found by Yunho Kim. a greater than 1 fixed quantifier. This issue was found by Yunho Kim.
3. Added support for callouts from pcre2_substitute(). 3. Added support for callouts from pcre2_substitute(). After 10.33-RC1, but
prior to release, fixed a bug that caused a crash if pcre2_substitute() was
called with a NULL match context.
4. The POSIX functions are now all called pcre2_regcomp() etc., with wrapper 4. The POSIX functions are now all called pcre2_regcomp() etc., with wrapper
functions that use the standard POSIX names. However, in pcre2posix.h the POSIX functions that use the standard POSIX names. However, in pcre2posix.h the POSIX

View File

@ -1450,8 +1450,10 @@ Testing substitute callouts
</b><br> </b><br>
<P> <P>
If the <b>substitute_callout</b> modifier is set, a substitution callout If the <b>substitute_callout</b> modifier is set, a substitution callout
function is set up. When it is called (after each substitution), details of the function is set up. The <b>null_context</b> modifier must not be set, because
the input and output strings are output. For example: the address of the callout function is passed in a match context. When the
callout function is called (after each substitution), details of the the input
and output strings are output. For example:
<pre> <pre>
/abc/g,replace=&#60;$0&#62;,substitute_callout /abc/g,replace=&#60;$0&#62;,substitute_callout
abcdefabcpqr abcdefabcpqr
@ -1626,11 +1628,11 @@ Passing a NULL context
</b><br> </b><br>
<P> <P>
Normally, <b>pcre2test</b> passes a context block to <b>pcre2_match()</b>, Normally, <b>pcre2test</b> passes a context block to <b>pcre2_match()</b>,
<b>pcre2_dfa_match()</b> or <b>pcre2_jit_match()</b>. If the <b>null_context</b> <b>pcre2_dfa_match()</b>, <b>pcre2_jit_match()</b> or <b>pcre2_substitute()</b>.
modifier is set, however, NULL is passed. This is for testing that the matching If the <b>null_context</b> modifier is set, however, NULL is passed. This is for
functions behave correctly in this case (they use default values). This testing that the matching and substitution functions behave correctly in this
modifier cannot be used with the <b>find_limits</b> modifier or when testing the case (they use default values). This modifier cannot be used with the
substitution function. <b>find_limits</b> or <b>substitute_callout</b> modifiers.
</P> </P>
<br><a name="SEC12" href="#TOC1">THE ALTERNATIVE MATCHING FUNCTION</a><br> <br><a name="SEC12" href="#TOC1">THE ALTERNATIVE MATCHING FUNCTION</a><br>
<P> <P>
@ -2076,7 +2078,7 @@ Cambridge, England.
</P> </P>
<br><a name="SEC21" href="#TOC1">REVISION</a><br> <br><a name="SEC21" href="#TOC1">REVISION</a><br>
<P> <P>
Last updated: 11 February 2019 Last updated: 11 March 2019
<br> <br>
Copyright &copy; 1997-2019 University of Cambridge. Copyright &copy; 1997-2019 University of Cambridge.
<br> <br>

View File

@ -1,4 +1,4 @@
.TH PCRE2TEST 1 "11 February 2019" "PCRE 10.33" .TH PCRE2TEST 1 "11 March 2019" "PCRE 10.33"
.SH NAME .SH NAME
pcre2test - a program for testing Perl-compatible regular expressions. pcre2test - a program for testing Perl-compatible regular expressions.
.SH SYNOPSIS .SH SYNOPSIS
@ -1417,8 +1417,10 @@ matching provokes an error return ("bad option value") from
.rs .rs
.sp .sp
If the \fBsubstitute_callout\fP modifier is set, a substitution callout If the \fBsubstitute_callout\fP modifier is set, a substitution callout
function is set up. When it is called (after each substitution), details of the function is set up. The \fBnull_context\fP modifier must not be set, because
the input and output strings are output. For example: the address of the callout function is passed in a match context. When the
callout function is called (after each substitution), details of the the input
and output strings are output. For example:
.sp .sp
/abc/g,replace=<$0>,substitute_callout /abc/g,replace=<$0>,substitute_callout
abcdefabcpqr abcdefabcpqr
@ -1587,11 +1589,11 @@ passing the replacement string as zero-terminated.
.rs .rs
.sp .sp
Normally, \fBpcre2test\fP passes a context block to \fBpcre2_match()\fP, Normally, \fBpcre2test\fP passes a context block to \fBpcre2_match()\fP,
\fBpcre2_dfa_match()\fP or \fBpcre2_jit_match()\fP. If the \fBnull_context\fP \fBpcre2_dfa_match()\fP, \fBpcre2_jit_match()\fP or \fBpcre2_substitute()\fP.
modifier is set, however, NULL is passed. This is for testing that the matching If the \fBnull_context\fP modifier is set, however, NULL is passed. This is for
functions behave correctly in this case (they use default values). This testing that the matching and substitution functions behave correctly in this
modifier cannot be used with the \fBfind_limits\fP modifier or when testing the case (they use default values). This modifier cannot be used with the
substitution function. \fBfind_limits\fP or \fBsubstitute_callout\fP modifiers.
. .
. .
.SH "THE ALTERNATIVE MATCHING FUNCTION" .SH "THE ALTERNATIVE MATCHING FUNCTION"
@ -2057,6 +2059,6 @@ Cambridge, England.
.rs .rs
.sp .sp
.nf .nf
Last updated: 11 February 2019 Last updated: 11 March 2019
Copyright (c) 1997-2019 University of Cambridge. Copyright (c) 1997-2019 University of Cambridge.
.fi .fi

View File

@ -1303,8 +1303,10 @@ SUBJECT MODIFIERS
Testing substitute callouts Testing substitute callouts
If the substitute_callout modifier is set, a substitution callout func- If the substitute_callout modifier is set, a substitution callout func-
tion is set up. When it is called (after each substitution), details of tion is set up. The null_context modifier must not be set, because the
the the input and output strings are output. For example: address of the callout function is passed in a match context. When the
callout function is called (after each substitution), details of the
the input and output strings are output. For example:
/abc/g,replace=<$0>,substitute_callout /abc/g,replace=<$0>,substitute_callout
abcdefabcpqr abcdefabcpqr
@ -1457,11 +1459,11 @@ SUBJECT MODIFIERS
Passing a NULL context Passing a NULL context
Normally, pcre2test passes a context block to pcre2_match(), Normally, pcre2test passes a context block to pcre2_match(),
pcre2_dfa_match() or pcre2_jit_match(). If the null_context modifier is pcre2_dfa_match(), pcre2_jit_match() or pcre2_substitute(). If the
set, however, NULL is passed. This is for testing that the matching null_context modifier is set, however, NULL is passed. This is for
functions behave correctly in this case (they use default values). This testing that the matching and substitution functions behave correctly
modifier cannot be used with the find_limits modifier or when testing in this case (they use default values). This modifier cannot be used
the substitution function. with the find_limits or substitute_callout modifiers.
THE ALTERNATIVE MATCHING FUNCTION THE ALTERNATIVE MATCHING FUNCTION
@ -1888,5 +1890,5 @@ AUTHOR
REVISION REVISION
Last updated: 11 February 2019 Last updated: 11 March 2019
Copyright (c) 1997-2019 University of Cambridge. Copyright (c) 1997-2019 University of Cambridge.

View File

@ -839,7 +839,7 @@ do
remembered. Do the callout if there is one and we have done an actual remembered. Do the callout if there is one and we have done an actual
replacement. */ replacement. */
if (!overflowed && mcontext->substitute_callout != NULL) if (!overflowed && mcontext != NULL && mcontext->substitute_callout != NULL)
{ {
scb.subscount = subs; scb.subscount = subs;
scb.output_offsets[1] = buff_offset; scb.output_offsets[1] = buff_offset;

View File

@ -1388,13 +1388,13 @@ are supported. */
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \ #define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
if (test_mode == PCRE8_MODE) \ if (test_mode == PCRE8_MODE) \
a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),G(h,8), \ a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h, \
(PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l); \ (PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l); \
else if (test_mode == PCRE16_MODE) \ else if (test_mode == PCRE16_MODE) \
a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),G(h,16), \ a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h, \
(PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l); \ (PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l); \
else \ else \
a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),G(h,32), \ a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h, \
(PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l) (PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \ #define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
@ -1866,11 +1866,11 @@ the three different cases. */
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \ #define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
if (test_mode == G(G(PCRE,BITONE),_MODE)) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \
a = G(pcre2_substitute_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \ a = G(pcre2_substitute_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \
G(g,BITONE),G(h,BITONE),(G(PCRE2_SPTR,BITONE))i,j, \ G(g,BITONE),h,(G(PCRE2_SPTR,BITONE))i,j, \
(G(PCRE2_UCHAR,BITONE) *)k,l); \ (G(PCRE2_UCHAR,BITONE) *)k,l); \
else \ else \
a = G(pcre2_substitute_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \ a = G(pcre2_substitute_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \
G(g,BITTWO),G(h,BITTWO),(G(PCRE2_SPTR,BITTWO))i,j, \ G(g,BITTWO),h,(G(PCRE2_SPTR,BITTWO))i,j, \
(G(PCRE2_UCHAR,BITTWO) *)k,l) (G(PCRE2_UCHAR,BITTWO) *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \ #define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
@ -2068,7 +2068,7 @@ the three different cases. */
pcre2_set_substitute_callout_8(G(a,8), \ pcre2_set_substitute_callout_8(G(a,8), \
(int (*)(pcre2_substitute_callout_block_8 *, void *))b,c) (int (*)(pcre2_substitute_callout_block_8 *, void *))b,c)
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \ #define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),G(h,8), \ a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h, \
(PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l) (PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \ #define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
a = pcre2_substring_copy_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 *)d,e) a = pcre2_substring_copy_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 *)d,e)
@ -2175,7 +2175,7 @@ the three different cases. */
pcre2_set_substitute_callout_16(G(a,16), \ pcre2_set_substitute_callout_16(G(a,16), \
(int (*)(pcre2_substitute_callout_block_16 *, void *))b,c) (int (*)(pcre2_substitute_callout_block_16 *, void *))b,c)
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \ #define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),G(h,16), \ a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h, \
(PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l) (PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \ #define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
a = pcre2_substring_copy_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 *)d,e) a = pcre2_substring_copy_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 *)d,e)
@ -2282,7 +2282,7 @@ the three different cases. */
pcre2_set_substitute_callout_32(G(a,32), \ pcre2_set_substitute_callout_32(G(a,32), \
(int (*)(pcre2_substitute_callout_block_32 *, void *))b,c) (int (*)(pcre2_substitute_callout_block_32 *, void *))b,c)
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \ #define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),G(h,32), \ a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h, \
(PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l) (PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \ #define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
a = pcre2_substring_copy_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 *)d,e) a = pcre2_substring_copy_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 *)d,e)
@ -6939,11 +6939,13 @@ for (k = 0; k < sizeof(exclusive_dat_controls)/sizeof(uint32_t); k++)
if (pat_patctl.replacement[0] != 0) if (pat_patctl.replacement[0] != 0)
{ {
if ((dat_datctl.control & CTL_NULLCONTEXT) != 0) if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) != 0 &&
(dat_datctl.control & CTL_NULLCONTEXT) != 0)
{ {
fprintf(outfile, "** Replacement text is not supported with null_context.\n"); fprintf(outfile, "** Replacement callouts are not supported with null_context.\n");
return PR_OK; return PR_OK;
} }
if ((dat_datctl.control & CTL_ALLCAPTURES) != 0) if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)
fprintf(outfile, "** Ignored with replacement text: allcaptures\n"); fprintf(outfile, "** Ignored with replacement text: allcaptures\n");
} }
@ -7335,7 +7337,7 @@ if (dat_datctl.replacement[0] != 0)
} }
PCRE2_SUBSTITUTE(rc, compiled_code, pp, arg_ulen, dat_datctl.offset, PCRE2_SUBSTITUTE(rc, compiled_code, pp, arg_ulen, dat_datctl.offset,
dat_datctl.options|xoptions, match_data, dat_context, dat_datctl.options|xoptions, match_data, use_dat_context,
rbuffer, rlen, nbuffer, &nsize); rbuffer, rlen, nbuffer, &nsize);
if (rc < 0) if (rc < 0)

8
testdata/testinput2 vendored
View File

@ -5579,4 +5579,12 @@ a)"xI
/(*ACCEPT:XX)^abc/I /(*ACCEPT:XX)^abc/I
/abc/replace=xyz
abc\=null_context
/abc/replace=xyz,substitute_callout
abc
\= Expect error message
abc\=null_context
# End of testinput2 # End of testinput2

12
testdata/testoutput2 vendored
View File

@ -16922,6 +16922,18 @@ Subject length lower bound = 3
Capture group count = 0 Capture group count = 0
Subject length lower bound = 0 Subject length lower bound = 0
/abc/replace=xyz
abc\=null_context
1: xyz
/abc/replace=xyz,substitute_callout
abc
1(1) Old 0 3 "abc" New 0 3 "xyz"
1: xyz
\= Expect error message
abc\=null_context
** Replacement callouts are not supported with null_context.
# End of testinput2 # End of testinput2
Error -70: PCRE2_ERROR_BADDATA (unknown error number) Error -70: PCRE2_ERROR_BADDATA (unknown error number)
Error -62: bad serialized data Error -62: bad serialized data