Skip to content

Test::Exception doesn't play nice with Safe #18

Open

Description

@choroba
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 2;

use Safe;

for my $test_exception (0, 1) {
    require Test::Exception if $test_exception;

    my $compartment = Safe->new();
    $compartment->permit(qw{ require caller });
    my $r = $compartment->reval('use warnings;1;');
    note($@) if $@;
    ok($r, 'warnings');
}

Output:

1..2
ok 1 - warnings
Number found where operator expected (Do you need to predeclare "caller"?) at /home/perlbot/perl5/custom/5.40.0/lib/5.40.0/warnings.pm line 454, near "caller 1"
# syntax error at /home/perlbot/perl5/custom/5.40.0/lib/5.40.0/warnings.pm line 454, near "caller 1"
# Execution of /home/perlbot/perl5/custom/5.40.0/lib/5.40.0/warnings.pm aborted due to compilation errors.
# Compilation failed in require at (eval 15) line 1.
# BEGIN failed--compilation aborted at (eval 15) line 1.
not ok 2 - warnings
#   Failed test 'warnings'
#   at (IRC) line 15.
# Looks like you failed 1 test of 2.

Activity

  1. added a commit that references this issue on Feb 18, 2025
  2. haarg commented on Feb 18, 2025

    @haarg
    Member

    This is caused by Sub::Uplevel overriding CORE::GLOBAL::caller, which isn't shared into the Safe container. This should probably be considered a core bug, where the override should be ignored since it isn't available inside the Safe container.

    I don't think there's really anything that this module can do to work around this. Sub::Uplevel is a terrible tool, but is needed for this module to operate correctly. And Sub::Uplevel can't fix how Safe or core is behaving.

    Demonstration of the problem without Test::Exception or Sub::Uplevel:

    #!/usr/bin/perl
    use strict;
    use warnings;
    use Test::More tests => 2;
    
    use Safe;
    
    for my $test_exception (0, 1) {
        *CORE::GLOBAL::caller = \&CORE::caller if $test_exception;
    
        my $compartment = Safe->new();
        $compartment->permit(qw{ require caller });
        my $r = $compartment->reval('use warnings; 1;');
        note($@) if $@;
        ok($r, 'warnings');
    }
  3. choroba commented on Feb 18, 2025

    @choroba
    Author

    Interestingly, replacing Test::Exception with Test::Trap seems to fix this particular issue.

  4. haarg commented on Feb 18, 2025

    @haarg
    Member

    Test::Trap has a different API that doesn't require Sub::Uplevel to work around problems. Test::Fatal also doesn't suffer from this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions