diff --git a/pad.c b/pad.c index d4a20ef84cbb..921c10d1cefa 100644 --- a/pad.c +++ b/pad.c @@ -2235,7 +2235,7 @@ S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned) if (UNLIKELY(CvISXSUB(proto))) { CvXSUB(cv) = CvXSUB(proto); CvXSUBANY(cv) = CvXSUBANY(proto); - if (CvREFCOUNTED_ANYSV(cv)) + if (CvREFCOUNTED_ANYSV(cv) || CvCONST(cv)) SvREFCNT_inc(CvXSUBANY(cv).any_sv); } else { diff --git a/t/op/state.t b/t/op/state.t index 747e316f226a..f309b4ec3fca 100644 --- a/t/op/state.t +++ b/t/op/state.t @@ -9,7 +9,7 @@ BEGIN { use strict; -plan tests => 164; +plan tests => 166; # Before loading feature.pm, test it with CORE:: ok eval 'CORE::state $x = 1;', 'CORE::state outside of feature.pm scope'; @@ -503,6 +503,21 @@ for (1,2) { is($s, "-1-", "state with multiconcat pass $_"); } +# This caused 'Attempt to free unreferenced scalar' because the SV holding +# the value of the const state sub wasn't having its ref count incremented +# when the sub was cloned. + +{ + my @warnings; + local $SIG{__WARN__} = sub { push @warnings, @_ }; + my $e = eval 'my $s = sub { state sub FOO () { 42 } }; 1;'; + is($e, 1, "const state sub ran ok"); + ok(!@warnings, "no 'Attempt to free unreferenced scalar'") + or diag "got these warnings:\n@warnings"; +} + + + __DATA__ (state $a) = 1; (state @a) = 1;