Skip to content

Commit aee5e9a

Browse files
NWilsoncarenas
andauthored
Fix null-dereference bug in pcre2_substitute (#618)
Avoid one crash introduced with recent changes to substitute code as well as clarify what the expected offset value should be when overflowing the provided buffer. --------- Co-authored-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
1 parent 0d2c59d commit aee5e9a

File tree

7 files changed

+116
-16
lines changed

7 files changed

+116
-16
lines changed

doc/html/pcre2api.html

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3808,9 +3808,10 @@ <h1>pcre2api man page</h1>
38083808
too small. The default action is to return PCRE2_ERROR_NOMEMORY immediately. If
38093809
this option is set, however, <b>pcre2_substitute()</b> continues to go through
38103810
the motions of matching and substituting (without, of course, writing anything)
3811-
in order to compute the size of buffer that is needed. This value is passed
3812-
back via the <i>outlengthptr</i> variable, with the result of the function still
3813-
being PCRE2_ERROR_NOMEMORY.
3811+
in order to compute the size of buffer that is needed, which will include the
3812+
extra space for the terminating NUL. This value is passed back via the
3813+
<i>outlengthptr</i> variable, with the result of the function still being
3814+
PCRE2_ERROR_NOMEMORY.
38143815
</P>
38153816
<P>
38163817
Passing a buffer size of zero is a permitted way of finding out how much memory
@@ -3944,7 +3945,7 @@ <h1>pcre2api man page</h1>
39443945
<P>
39453946
If either PCRE2_UTF or PCRE2_UCP was set when the pattern was compiled, Unicode
39463947
properties are used for case forcing characters whose code points are greater
3947-
than 127. However, only basic case folding, as determined by the Unicode file
3948+
than 127. However, only simple case folding, as determined by the Unicode file
39483949
<b>CaseFolding.txt</b> is supported. PCRE2 does not support language-specific
39493950
special casing rules such as using different lower case Greek sigmas in the
39503951
middle and ends of words (as defined in the Unicode file

doc/pcre2.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3669,9 +3669,9 @@ CREATING A NEW STRING WITH SUBSTITUTIONS
36693669
ORY immediately. If this option is set, however, pcre2_substitute()
36703670
continues to go through the motions of matching and substituting (with-
36713671
out, of course, writing anything) in order to compute the size of
3672-
buffer that is needed. This value is passed back via the outlengthptr
3673-
variable, with the result of the function still being PCRE2_ER-
3674-
ROR_NOMEMORY.
3672+
buffer that is needed, which will include the extra space for the ter-
3673+
minating NUL. This value is passed back via the outlengthptr variable,
3674+
with the result of the function still being PCRE2_ERROR_NOMEMORY.
36753675

36763676
Passing a buffer size of zero is a permitted way of finding out how
36773677
much memory is needed for given substitution. However, this does mean
@@ -3798,7 +3798,7 @@ CREATING A NEW STRING WITH SUBSTITUTIONS
37983798

37993799
If either PCRE2_UTF or PCRE2_UCP was set when the pattern was compiled,
38003800
Unicode properties are used for case forcing characters whose code
3801-
points are greater than 127. However, only basic case folding, as de-
3801+
points are greater than 127. However, only simple case folding, as de-
38023802
termined by the Unicode file CaseFolding.txt is supported. PCRE2 does
38033803
not support language-specific special casing rules such as using dif-
38043804
ferent lower case Greek sigmas in the middle and ends of words (as de-

doc/pcre2api.3

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3815,9 +3815,10 @@ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH changes what happens when the output buffer is
38153815
too small. The default action is to return PCRE2_ERROR_NOMEMORY immediately. If
38163816
this option is set, however, \fBpcre2_substitute()\fP continues to go through
38173817
the motions of matching and substituting (without, of course, writing anything)
3818-
in order to compute the size of buffer that is needed. This value is passed
3819-
back via the \fIoutlengthptr\fP variable, with the result of the function still
3820-
being PCRE2_ERROR_NOMEMORY.
3818+
in order to compute the size of buffer that is needed, which will include the
3819+
extra space for the terminating NUL. This value is passed back via the
3820+
\fIoutlengthptr\fP variable, with the result of the function still being
3821+
PCRE2_ERROR_NOMEMORY.
38213822
.P
38223823
Passing a buffer size of zero is a permitted way of finding out how much memory
38233824
is needed for given substitution. However, this does mean that the entire
@@ -3938,7 +3939,7 @@ that can be applied to group captures. For example, if group 1 has captured
39383939
.P
39393940
If either PCRE2_UTF or PCRE2_UCP was set when the pattern was compiled, Unicode
39403941
properties are used for case forcing characters whose code points are greater
3941-
than 127. However, only basic case folding, as determined by the Unicode file
3942+
than 127. However, only simple case folding, as determined by the Unicode file
39423943
\fBCaseFolding.txt\fP is supported. PCRE2 does not support language-specific
39433944
special casing rules such as using different lower case Greek sigmas in the
39443945
middle and ends of words (as defined in the Unicode file

src/pcre2_substitute.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ do
943943
GETCHARINCTEST(ch, subptr);
944944
if (forcecase != 0)
945945
{
946-
if (mcontext->substitute_case_callout)
946+
if (mcontext != NULL && mcontext->substitute_case_callout != NULL)
947947
{
948948
ch = mcontext->substitute_case_callout(
949949
ch,
@@ -1105,7 +1105,7 @@ do
11051105
LITERAL:
11061106
if (forcecase != 0)
11071107
{
1108-
if (mcontext->substitute_case_callout)
1108+
if (mcontext != NULL && mcontext->substitute_case_callout != NULL)
11091109
{
11101110
ch = mcontext->substitute_case_callout(
11111111
ch,

src/pcre2test.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7500,6 +7500,13 @@ if (pat_patctl.replacement[0] != 0)
75007500
return PR_OK;
75017501
}
75027502

7503+
if (pat_patctl.replacement_case[0] != 0 &&
7504+
(dat_datctl.control & CTL_NULLCONTEXT) != 0)
7505+
{
7506+
fprintf(outfile, "** Replacement case callouts are not supported with null_context.\n");
7507+
return PR_OK;
7508+
}
7509+
75037510
if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)
75047511
fprintf(outfile, "** Ignored with replacement text: allcaptures\n");
75057512
}

testdata/testinput2

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4226,6 +4226,37 @@
42264226
apple lemon blackberry
42274227

42284228
/abc/
4229+
123abc123\=replace=XYZ
4230+
123abc123\=replace=[10]XYZ
4231+
\= Expect error
4232+
123abc123\=replace=[9]XYZ
4233+
123abc123\=substitute_overflow_length,replace=[9]XYZ
4234+
123abc123\=substitute_overflow_length,replace=[6]XYZ
4235+
123abc123\=substitute_overflow_length,replace=[1]XYZ
4236+
123abc123\=substitute_overflow_length,replace=[0]XYZ
4237+
4238+
/abc/
4239+
123abc123\=replace=XY
4240+
123abc123\=replace=[9]XY
4241+
123abc123\=replace=[9]XY,substitute_literal
4242+
\= Expect error
4243+
123abc123\=replace=[8]XY,substitute_overflow_length
4244+
123abc123\=replace=[8]XY,substitute_overflow_length,substitute_literal
4245+
123abc123\=replace=[6]XY,substitute_overflow_length
4246+
123abc123\=replace=[6]XY,substitute_overflow_length,substitute_literal
4247+
123abc123\=replace=[5]XY,substitute_overflow_length
4248+
123abc123\=replace=[5]XY,substitute_overflow_length,substitute_literal
4249+
123abc123\=replace=[4]XY,substitute_overflow_length
4250+
123abc123\=replace=[4]XY,substitute_overflow_length,substitute_literal
4251+
123abc123\=replace=[3]XY,substitute_overflow_length
4252+
123abc123\=replace=[3]XY,substitute_overflow_length,substitute_literal
4253+
123abc123\=replace=[2]XY,substitute_overflow_length
4254+
123abc123\=replace=[2]XY,substitute_overflow_length,substitute_literal
4255+
4256+
/abc/substitute_literal
4257+
123abc123\=replace=XYZ
4258+
123abc123\=replace=[10]XYZ
4259+
\= Expect error
42294260
123abc123\=replace=[9]XYZ
42304261
123abc123\=substitute_overflow_length,replace=[9]XYZ
42314262
123abc123\=substitute_overflow_length,replace=[6]XYZ
@@ -4720,7 +4751,7 @@ B)x/alt_verbnames,mark
47204751

47214752
/abcd/null_context
47224753
abcd\=null_context
4723-
\= Expect error - not allowed together
4754+
\= Expect not allowed together
47244755
abcd\=null_context,find_limits
47254756
abcd\=allusedtext,startchar
47264757

@@ -6067,6 +6098,8 @@ a)"xI
60676098

60686099
/abc/replace=\U$0,substitute_extended,substitute_case_callout=a.U.b.V.
60696100
XabcY
6101+
\= Expect not supported
6102+
XabcY\=null_context
60706103

60716104
/a/substitute_extended
60726105
XaY\=replace=\U$0,substitute_case_callout=a.U.

testdata/testoutput2

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13907,6 +13907,61 @@ Failed: error -48: no more memory: 23 code units are needed
1390713907
1: fruit\x00juice lemon blackberry
1390813908

1390913909
/abc/
13910+
123abc123\=replace=XYZ
13911+
1: 123XYZ123
13912+
123abc123\=replace=[10]XYZ
13913+
1: 123XYZ123
13914+
\= Expect error
13915+
123abc123\=replace=[9]XYZ
13916+
Failed: error -48: no more memory
13917+
123abc123\=substitute_overflow_length,replace=[9]XYZ
13918+
Failed: error -48: no more memory: 10 code units are needed
13919+
123abc123\=substitute_overflow_length,replace=[6]XYZ
13920+
Failed: error -48: no more memory: 10 code units are needed
13921+
123abc123\=substitute_overflow_length,replace=[1]XYZ
13922+
Failed: error -48: no more memory: 10 code units are needed
13923+
123abc123\=substitute_overflow_length,replace=[0]XYZ
13924+
Failed: error -48: no more memory: 10 code units are needed
13925+
13926+
/abc/
13927+
123abc123\=replace=XY
13928+
1: 123XY123
13929+
123abc123\=replace=[9]XY
13930+
1: 123XY123
13931+
123abc123\=replace=[9]XY,substitute_literal
13932+
1: 123XY123
13933+
\= Expect error
13934+
123abc123\=replace=[8]XY,substitute_overflow_length
13935+
Failed: error -48: no more memory: 9 code units are needed
13936+
123abc123\=replace=[8]XY,substitute_overflow_length,substitute_literal
13937+
Failed: error -48: no more memory: 9 code units are needed
13938+
123abc123\=replace=[6]XY,substitute_overflow_length
13939+
Failed: error -48: no more memory: 9 code units are needed
13940+
123abc123\=replace=[6]XY,substitute_overflow_length,substitute_literal
13941+
Failed: error -48: no more memory: 9 code units are needed
13942+
123abc123\=replace=[5]XY,substitute_overflow_length
13943+
Failed: error -48: no more memory: 9 code units are needed
13944+
123abc123\=replace=[5]XY,substitute_overflow_length,substitute_literal
13945+
Failed: error -48: no more memory: 9 code units are needed
13946+
123abc123\=replace=[4]XY,substitute_overflow_length
13947+
Failed: error -48: no more memory: 9 code units are needed
13948+
123abc123\=replace=[4]XY,substitute_overflow_length,substitute_literal
13949+
Failed: error -48: no more memory: 9 code units are needed
13950+
123abc123\=replace=[3]XY,substitute_overflow_length
13951+
Failed: error -48: no more memory: 9 code units are needed
13952+
123abc123\=replace=[3]XY,substitute_overflow_length,substitute_literal
13953+
Failed: error -48: no more memory: 9 code units are needed
13954+
123abc123\=replace=[2]XY,substitute_overflow_length
13955+
Failed: error -48: no more memory: 9 code units are needed
13956+
123abc123\=replace=[2]XY,substitute_overflow_length,substitute_literal
13957+
Failed: error -48: no more memory: 9 code units are needed
13958+
13959+
/abc/substitute_literal
13960+
123abc123\=replace=XYZ
13961+
1: 123XYZ123
13962+
123abc123\=replace=[10]XYZ
13963+
1: 123XYZ123
13964+
\= Expect error
1391013965
123abc123\=replace=[9]XYZ
1391113966
Failed: error -48: no more memory
1391213967
123abc123\=substitute_overflow_length,replace=[9]XYZ
@@ -15154,7 +15209,7 @@ No match
1515415209
/abcd/null_context
1515515210
abcd\=null_context
1515615211
0: abcd
15157-
\= Expect error - not allowed together
15212+
\= Expect not allowed together
1515815213
abcd\=null_context,find_limits
1515915214
** Not allowed together: find_limits null_context
1516015215
abcd\=allusedtext,startchar
@@ -18088,6 +18143,9 @@ Failed: error -55 at offset 3 in replacement: requested value is not set
1808818143
/abc/replace=\U$0,substitute_extended,substitute_case_callout=a.U.b.V.
1808918144
XabcY
1809018145
1: XUVcY
18146+
\= Expect not supported
18147+
XabcY\=null_context
18148+
** Replacement case callouts are not supported with null_context.
1809118149

1809218150
/a/substitute_extended
1809318151
XaY\=replace=\U$0,substitute_case_callout=a.U.

0 commit comments

Comments
 (0)