perl/t/op/debug.t
Tony Cook b711f998fe amagic_call: don't invoke DB::sub for overloads called from DB
Perl decides on whether DB::sub is called for a sub called based on
the OPpENTERSUB_DB flag in the entersub op for that call.

At compilation time ck_subr sets if PL_curstash (the current
compilation stash) is not equal to PL_dbstash (%DB::), which is fine.

When calling an overload sub amagic_call() synthesizes an entersub OP
and sets OPpENTERSUB_DB based on the same condition, but PL_curstash
isn't set to the stash of the currently executing code, but is still
set to the last stash code was compiled in (as modified by scope
restoration).

This means the flag was (perhaps nearly) always set, so the debugger
would call &DB::sub even though the overload was occurring in package
DB.

Fix this by testing against CopSTASH(PL_curcop) instead, which other
runtime stash checks also do, eg. pp_caller, doeval_compile.

Fixes #24001
2025-12-18 10:36:39 +11:00

174 lines
3.4 KiB
Perl

#!./perl
# intended for testing language mechanisms that debuggers use not for
# testing the debugger itself
BEGIN {
chdir 't' if -d 't';
require "./test.pl";
set_up_inc( qw(. ../lib) );
}
use strict;
use warnings;
SKIP:
{
skip_if_miniperl("need XS", 1);
# github 23151
# trivial debugger
local $ENV{PERL5DB} = 'sub DB::DB {}';
# eval code trimmed from code generated by Sub::Quote
fresh_perl_is(<<'CODE', <<'EXPECT',
use B qw(SVf_IOK);
sub _do_eval {
eval $_[0] or die $!;
}
_do_eval(<<'EVAL');
{
sub table {
}
}
1;
EVAL
# look for lines that don't have an IV set
my ($f) = grep /\(eval/, keys %::;
my $x = $::{$f};
my $lineno = 0;
for my $l (@$x) {
if ($l) {
my $b = B::svref_2object(\$l);
if (!($b->FLAGS & SVf_IOK)) {
print "No IV for $f line $lineno: $l\n";
last
}
}
++$lineno;
}
print "Done\n";
CODE
Done
EXPECT
{
switches => [ '-d' ],
stderr => 1,
},
"saved lines all have an IV"
);
}
SKIP:
{
# Historically lines were stored as PVMG, but we don't need
# magic on these lines.
#
# This checks that none of these lines get upgraded, ie. that
# we don't need them to be PVMG
#
# If this test fails perhaps we do need to make them PVMG
# and toke.c:S_update_debugger_info and pp_ctl.c:S_save_lines
# can be switched back to using SVt_PVMG and this test
# removed.
#
# See https://github.com/Perl/perl5/pull/23171#issuecomment-2780007725
skip_if_miniperl("need B");
local $ENV{PERL5DB} = 'sub DB::DB {}';
fresh_perl_is(<<'CODE', <<'EXPECT',
use B;
sub _do_eval {
eval $_[0] or die $!;
}
_do_eval(<<'EVAL');
sub some_code {
print "Hello";
}
1;
EVAL
# check if any lines have been upgraded from PVIV
my @files = grep /^_</, keys %::;
for my $f (@files) {
my $lineno = 0;
for my $l (@{$f}) {
if ($l) {
my $b = B::svref_2object(\$l);
if (ref $b ne "B::PVIV") {
print "Not PVIV for $f:$lineno: $l\n";
last
}
}
++$lineno;
}
}
print "Done\n";
CODE
Done
EXPECT
{
switches => [ '-d' ],
stderr => 1,
},
"saved lines are all PVIV"
);
}
{
# GH 24001
local $ENV{PERL5DB} = 'sub DB::DB {}';
fresh_perl_is(<<'CODE', "OK\n",
package DB;
sub DB::sub {
# avoid deep recursion
die "Fail" if $DB::sub =~ /^version::/;
# trigger overloading call from package DB
my $v = "$^V";
print $v ne "" ? "OK\n" : ""
}
package main;
sub f {
}
f();
CODE
{
switches => [ '-d' ],
},
"overloading call from DB doesn't break into DB::sub");
}
{
local $ENV{PERL5DB} = 'sub DB::DB {}';
# make sure we don't break the expected break
fresh_perl_is(<<'CODE', "OK\n",
package DB;
sub DB::sub {
our @count;
if ($DB::sub eq 'version::(""') {
print "OK\n";
exit;
}
push @count, $DB::sub;
die "Fail @count\n" if @count > 10;
&$DB::sub;
}
package main;
sub f {
my $v = "$^V";
}
f();
CODE
{
switches => [ '-d' ],
},
"overloading call from non-DB does break into DB::sub");
}
done_testing();