Skip to content

Commit 1065606

Browse files
committed
avoid leak in regex with overload and code block
When concatenating the components of a run-time pattern, if a component has concat overloading, then that method is used, and any previously accumulated code blocks - i.e. (?{...}) and similar - are discarded. However, the ref counts of of any regex objects pointed to which contained those code block(s) weren't having their reference count decremented, and so leaked. Spotted by code inspection while working on the previous commit.
1 parent b74d82c commit 1065606

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

regcomp.c

+3
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,9 @@ S_concat_pat(pTHX_ RExC_state_t * const pRExC_state,
758758
*/
759759
struct reg_code_blocks *cbs = pRExC_state->code_blocks;
760760
if (cbs) {
761+
for (int n = 0; n < cbs->count; n++) {
762+
SvREFCNT_dec(cbs->cb[n].src_regex);
763+
}
761764
cbs->count = 0;
762765
}
763766
}

t/op/svleak.t

+28-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ BEGIN {
1515

1616
use Config;
1717

18-
plan tests => 156;
18+
plan tests => 157;
1919

2020
# run some code N times. If the number of SVs at the end of loop N is
2121
# greater than (N-1)*delta at the end of loop 1, we've got a leak
@@ -683,3 +683,30 @@ leak 2, 0, sub {
683683
} } 1..2;
684684
},
685685
'sort block return';
686+
687+
688+
# Avoid leaks when overloading causes a compile-time pattern code block
689+
# to be recompiled at runtime.
690+
691+
package myconcat {
692+
use overload
693+
'""' => sub { ${$_[0]} },
694+
'.' => sub {
695+
my ($x, $y) = @_[ $_[2] ? (1,0) : (0,1) ];
696+
my ($xx, $yy) = ("$x", "$y");
697+
"$xx$yy";
698+
}
699+
;
700+
701+
::leak(2, 0,
702+
sub {
703+
my $r1 = qr/(?{1})/;
704+
my $r2 = qr/(?{2})/;
705+
bless $r2, 'myconcat';
706+
use re "eval";
707+
qr/$r1$r2/;
708+
1;
709+
},
710+
'overloaded pattern with code block'
711+
);
712+
}

0 commit comments

Comments
 (0)