Skip to content

Commit 4428256

Browse files
committed
sv.c - sv_2pv_flags: Fix double FETCH from tied overloaded scalar
When dealing with a tied scalar with get magic, and the FETCH method returned a blessed reference with overloading magic (with "a" magic), the tied scalar returned from the fetch was not copied prior to calling the magic function as an argument, this would then cause the get magic to be called again if the overloaded method happened to copy or otherwise use the tied scalar. The solution is to copy the reference prior to dispatching the overload call. It looks like we have been testing for the double FETCH for some time, without any good rationale, so this test merely changes things to expect the desired count.
1 parent 9a266c0 commit 4428256

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

lib/overload.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1906,7 +1906,7 @@ foreach my $op (qw(<=> == != < <= > >=)) {
19061906

19071907
# eval should do tie, overload on its arg before checking taint */
19081908
push @tests, [ '1;', 'eval q(eval %s); $@ =~ /Insecure/',
1909-
'("")', '("")', [ 1, 2, 0 ], 0 ];
1909+
'("")', '("")', [ 1, 1, 0 ], 0 ];
19101910

19111911

19121912
for my $sub (keys %subs) {

pod/perldelta.pod

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,12 @@ Also, embedded C<NUL> characters are now allowed in the input.
395395
If locale collation is not enabled on the platform (C<LC_COLLATE>), the
396396
input is returned unchanged.
397397

398+
=item *
399+
400+
Double FETCH during stringification of tied scalars returning an
401+
overloaded object have been fixed. The FETCH method should only be
402+
called once, but prior to this release was actually called twice.
403+
398404
=back
399405

400406
=head1 Known Problems

sv.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2830,21 +2830,28 @@ char *
28302830
Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const U32 flags)
28312831
{
28322832
char *s;
2833+
bool done_gmagic = FALSE;
28332834

28342835
PERL_ARGS_ASSERT_SV_2PV_FLAGS;
28352836

28362837
assert (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV
28372838
&& SvTYPE(sv) != SVt_PVFM);
2838-
if (SvGMAGICAL(sv) && (flags & SV_GMAGIC))
2839+
if (SvGMAGICAL(sv) && (flags & SV_GMAGIC)) {
28392840
mg_get(sv);
2841+
done_gmagic = TRUE;
2842+
}
2843+
28402844
if (SvROK(sv)) {
28412845
if (SvAMAGIC(sv)) {
28422846
SV *tmpstr;
2847+
SV *nsv= (SV *)sv;
28432848
if (flags & SV_SKIP_OVERLOAD)
28442849
return NULL;
2845-
tmpstr = AMG_CALLunary(sv, string_amg);
2850+
if (done_gmagic)
2851+
nsv = sv_mortalcopy_flags(sv,0);
2852+
tmpstr = AMG_CALLunary(nsv, string_amg);
28462853
TAINT_IF(tmpstr && SvTAINTED(tmpstr));
2847-
if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
2854+
if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(nsv)))) {
28482855
/* Unwrap this: */
28492856
/* char *pv = lp ? SvPV(tmpstr, *lp) : SvPV_nolen(tmpstr);
28502857
*/

0 commit comments

Comments
 (0)