Skip to content

Commit f082678

Browse files
mauzorgs
authored andcommitted
RT#69616: regexp SVs lose regexpness in assignment
It uses reg_temp_copy to copy the REGEXP onto the destination SV without needing to copy the underlying pattern structure. This means changing the prototype of reg_temp_copy, so it can copy onto a passed-in SV, but it isn't API (and probably shouldn't be exported) so I don't think this is a problem.
1 parent dc35ab6 commit f082678

File tree

8 files changed

+49
-12
lines changed

8 files changed

+49
-12
lines changed

embed.fnc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ Ap |I32 |pregexec |NN REGEXP * const prog|NN char* stringarg \
825825
Ap |void |pregfree |NULLOK REGEXP* r
826826
Ap |void |pregfree2 |NN REGEXP *rx
827827
: FIXME - is anything in re using this now?
828-
EXp |REGEXP*|reg_temp_copy |NN REGEXP* r
828+
EXp |REGEXP*|reg_temp_copy |NULLOK REGEXP* ret_x|NN REGEXP* rx
829829
Ap |void |regfree_internal|NN REGEXP *const rx
830830
#if defined(USE_ITHREADS)
831831
Ap |void* |regdupe_internal|NN REGEXP * const r|NN CLONE_PARAMS* param

embed.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3089,7 +3089,7 @@
30893089
#define pregfree(a) Perl_pregfree(aTHX_ a)
30903090
#define pregfree2(a) Perl_pregfree2(aTHX_ a)
30913091
#if defined(PERL_CORE) || defined(PERL_EXT)
3092-
#define reg_temp_copy(a) Perl_reg_temp_copy(aTHX_ a)
3092+
#define reg_temp_copy(a,b) Perl_reg_temp_copy(aTHX_ a,b)
30933093
#endif
30943094
#define regfree_internal(a) Perl_regfree_internal(aTHX_ a)
30953095
#if defined(USE_ITHREADS)

pp_ctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ PP(pp_regcomp)
122122
re = (REGEXP*) sv;
123123
}
124124
if (re) {
125-
re = reg_temp_copy(re);
125+
re = reg_temp_copy(NULL, re);
126126
ReREFCNT_dec(PM_GETRE(pm));
127127
PM_SETRE(pm, re);
128128
}

proto.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,10 +2557,10 @@ PERL_CALLCONV void Perl_pregfree2(pTHX_ REGEXP *rx)
25572557
#define PERL_ARGS_ASSERT_PREGFREE2 \
25582558
assert(rx)
25592559

2560-
PERL_CALLCONV REGEXP* Perl_reg_temp_copy(pTHX_ REGEXP* r)
2561-
__attribute__nonnull__(pTHX_1);
2560+
PERL_CALLCONV REGEXP* Perl_reg_temp_copy(pTHX_ REGEXP* ret_x, REGEXP* rx)
2561+
__attribute__nonnull__(pTHX_2);
25622562
#define PERL_ARGS_ASSERT_REG_TEMP_COPY \
2563-
assert(r)
2563+
assert(rx)
25642564

25652565
PERL_CALLCONV void Perl_regfree_internal(pTHX_ REGEXP *const rx)
25662566
__attribute__nonnull__(pTHX_1);

regcomp.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9442,15 +9442,18 @@ Perl_pregfree2(pTHX_ REGEXP *rx)
94429442

94439443

94449444
REGEXP *
9445-
Perl_reg_temp_copy (pTHX_ REGEXP *rx)
9445+
Perl_reg_temp_copy (pTHX_ REGEXP *ret_x, REGEXP *rx)
94469446
{
9447-
REGEXP *ret_x = (REGEXP*) newSV_type(SVt_REGEXP);
9448-
struct regexp *ret = (struct regexp *)SvANY(ret_x);
9447+
struct regexp *ret;
94499448
struct regexp *const r = (struct regexp *)SvANY(rx);
94509449
register const I32 npar = r->nparens+1;
94519450

94529451
PERL_ARGS_ASSERT_REG_TEMP_COPY;
94539452

9453+
if (!ret_x)
9454+
ret_x = (REGEXP*) newSV_type(SVt_REGEXP);
9455+
ret = (struct regexp *)SvANY(ret_x);
9456+
94549457
(void)ReREFCNT_inc(rx);
94559458
/* We can take advantage of the existing "copied buffer" mechanism in SVs
94569459
by pointing directly at the buffer, but flagging that the allocated

regexec.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3755,7 +3755,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog)
37553755
assert(rx);
37563756
}
37573757
if (rx) {
3758-
rx = reg_temp_copy(rx);
3758+
rx = reg_temp_copy(NULL, rx);
37593759
}
37603760
else {
37613761
U32 pm_flags = 0;

sv.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3891,7 +3891,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
38913891
}
38923892
/* Fall through */
38933893
#endif
3894-
case SVt_REGEXP:
38953894
case SVt_PV:
38963895
if (dtype < SVt_PV)
38973896
sv_upgrade(dstr, SVt_PV);
@@ -3914,6 +3913,11 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
39143913
}
39153914
break;
39163915

3916+
case SVt_REGEXP:
3917+
if (dtype < SVt_REGEXP)
3918+
sv_upgrade(dstr, SVt_REGEXP);
3919+
break;
3920+
39173921
/* case SVt_BIND: */
39183922
case SVt_PVLV:
39193923
case SVt_PVGV:
@@ -4016,6 +4020,9 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
40164020
}
40174021
}
40184022
}
4023+
else if (dtype == SVt_REGEXP && stype == SVt_REGEXP) {
4024+
reg_temp_copy((REGEXP*)dstr, (REGEXP*)sstr);
4025+
}
40194026
else if (sflags & SVp_POK) {
40204027
bool isSwipe = 0;
40214028

t/op/ref.t

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ BEGIN {
77

88
require 'test.pl';
99
use strict qw(refs subs);
10+
use re ();
1011

11-
plan(189);
12+
plan(196);
1213

1314
# Test glob operations.
1415

@@ -124,6 +125,32 @@ $subrefref = \\&mysub2;
124125
is ($$subrefref->("GOOD"), "good");
125126
sub mysub2 { lc shift }
126127

128+
# Test REGEXP assignment
129+
130+
{
131+
my $x = qr/x/;
132+
my $str = "$x"; # regex stringification may change
133+
134+
my $y = $$x;
135+
is ($y, $str, "bare REGEXP stringifies correctly");
136+
ok (eval { "x" =~ $y }, "bare REGEXP matches correctly");
137+
138+
my $z = \$y;
139+
ok (re::is_regexp($z), "new ref to REXEXP passes is_regexp");
140+
is ($z, $str, "new ref to REGEXP stringifies correctly");
141+
ok (eval { "x" =~ $z }, "new ref to REGEXP matches correctly");
142+
}
143+
{
144+
my ($x, $str);
145+
{
146+
my $y = qr/x/;
147+
$str = "$y";
148+
$x = $$y;
149+
}
150+
is ($x, $str, "REGEXP keeps a ref to its mother_re");
151+
ok (eval { "x" =~ $x }, "REGEXP with mother_re still matches");
152+
}
153+
127154
# Test the ref operator.
128155

129156
sub PVBM () { 'foo' }

0 commit comments

Comments
 (0)