Skip to content

regcomp.c: incr ref cnt of re_intuit_string() return #17763

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 27 additions & 14 deletions regcomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -21491,7 +21491,9 @@ SV *
Perl_re_intuit_string(pTHX_ REGEXP * const r)
{ /* Assume that RE_INTUIT is set */
/* Returns an SV containing a string that must appear in the target for it
* to match */
* to match, or NULL if nothing is known that must match.
*
* CAUTION: the SV can be freed during execution of the regex engine */

struct regexp *const prog = ReANY(r);
DECLARE_AND_GET_RE_DEBUG_FLAGS;
Expand Down Expand Up @@ -25011,8 +25013,10 @@ S_handle_names_wildcard(pTHX_ const char * wname, /* wildcard name to match */
where we are now */
bool found_matches = FALSE; /* Did any name match so far? */
SV * empty; /* For matching zero length names */
SV * must; /* What substring, if any, must be in a name
for the subpattern to match */
SV * must_sv; /* Contains the substring, if any, that must be
in a name for the subpattern to match */
char * must; /* The PV of 'must' */
STRLEN must_len; /* And its length */
SV * syllable_name = NULL; /* For Hangul syllables */
const char hangul_prefix[] = "HANGUL SYLLABLE ";
const STRLEN hangul_prefix_len = sizeof(hangul_prefix) - 1;
Expand Down Expand Up @@ -25077,7 +25081,23 @@ S_handle_names_wildcard(pTHX_ const char * wname, /* wildcard name to match */

/* Compile the subpattern consisting of the name being looked for */
subpattern_re = compile_wildcard(wname, wname_len, FALSE /* /-i */ );
must = re_intuit_string(subpattern_re);

must_sv = re_intuit_string(subpattern_re);
if (must_sv) {
/* regexec.c can free the re_intuit_string() return. GH #17734 */
must_sv = sv_2mortal(newSVsv(must_sv));
must = SvPV(must_sv, must_len);
}
else {
must = "";
must_len = 0;
}

/* (Note: 'must' could contain a NUL. And yet we use strspn() below on it.
* This works because the NUL causes the function to return early, thus
* showing that there are characters in it other than the acceptable ones,
* which is our desired result.) */

prog = ReANY(subpattern_re);

/* If only nothing is matched, skip to where empty names are looked for */
Expand All @@ -25087,10 +25107,7 @@ S_handle_names_wildcard(pTHX_ const char * wname, /* wildcard name to match */

/* And match against the string of all names /gc. Don't even try if it
* must match a character not found in any name. */
if ( ! must
|| SvCUR(must) == 0
|| strspn(SvPVX(must), "\n -0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ()")
== SvCUR(must))
if (strspn(must, "\n -0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ()") == must_len)
{
while (execute_wildcard(subpattern_re,
cur_pos,
Expand Down Expand Up @@ -25230,9 +25247,7 @@ S_handle_names_wildcard(pTHX_ const char * wname, /* wildcard name to match */
* one of the characters in that isn't in any Hangul syllable. */
if ( prog->minlen <= (SSize_t) syl_max_len
&& prog->maxlen > 0
&& ( ! must
|| SvCUR(must) == 0
|| strspn(SvPVX(must), "\n ABCDEGHIJKLMNOPRSTUWY") == SvCUR(must)))
&& (strspn(must, "\n ABCDEGHIJKLMNOPRSTUWY") == must_len))
{
/* These constants, names, values, and algorithm are adapted from the
* Unicode standard, version 5.1, section 3.12, and should never
Expand Down Expand Up @@ -25327,9 +25342,7 @@ S_handle_names_wildcard(pTHX_ const char * wname, /* wildcard name to match */
* series */
if ( prog->minlen <= (SSize_t) SvCUR(algo_name)
&& prog->maxlen > 0
&& ( ! must
|| SvCUR(must) == 0
|| strspn(SvPVX(must), legal) == SvCUR(must)))
&& (strspn(must, legal) == must_len))
{
for (j = low; j <= high; j++) { /* For each code point in the series */

Expand Down
9 changes: 9 additions & 0 deletions t/re/pat_advanced.t
Original file line number Diff line number Diff line change
Expand Up @@ -2553,6 +2553,15 @@ EOF
{}, "Too large negative relative group number");
}

{ # GH #17734, ASAN use after free
fresh_perl_like('no warnings "experimental::uniprop_wildcards";
my $re = q<[[\p{name=/[Y-]+Z/}]]>;
eval { "\N{BYZANTINE MUSICAL SYMBOL PSILI}"
=~ /$re/ }; print $@ if $@; print "Done\n";',
qr/Done/,
{}, "GH #17734");
}


# !!! NOTE that tests that aren't at all likely to crash perl should go
# a ways above, above these last ones. There's a comment there that, like
Expand Down