Don’t let XSLoader load relative paths
authorFather Chrysostomos <sprout@cpan.org>
Sun, 3 Jul 2016 05:56:51 +0000 (22:56 -0700)
committerSteve Hay <steve.m.hay@googlemail.com>
Thu, 21 Jul 2016 20:30:48 +0000 (21:30 +0100)
commit7099cb3d4b19649244b3ff4171da683abbd5e2bd
tree99c862646b940881ae2c2e990cae18a9836caa20
parent7682ed29a1a27848f952c4d878fd57f25b603d57
Don’t let XSLoader load relative paths

[rt.cpan.org #115808]

The logic in XSLoader for determining the library goes like this:

    my $c = () = split(/::/,$caller,-1);
    $modlibname =~ s,[\\/][^\\/]+$,, while $c--;    # Q&D basename
    my $file = "$modlibname/auto/$modpname/$modfname.bundle";

(That last line varies by platform.)

$caller is the calling package.  $modlibname is the calling file.  It
removes as many path segments from $modlibname as there are segments
in $caller.  So if you have Foo/Bar/XS.pm calling XSLoader from the
Foo::Bar package, the $modlibname will end up containing the path in
@INC where XS.pm was found, followed by "/Foo".  Usually the fallback
to Dynaloader::bootstrap_inherit, which does an @INC search, makes
things Just Work.

But if our hypothetical Foo/Bar/XS.pm actually calls
XSLoader::load from inside a string eval, then path ends up being
"(eval 1)/auto/Foo/Bar/Bar.bundle".

So if someone creates a directory named ‘(eval 1)’ with a naughty
binary file in it, it will be loaded if a script using Foo::Bar is run
in the parent directory.

This commit makes XSLoader fall back to Dynaloader’s @INC search if
the calling file has a relative path that is not found in @INC.

(cherry picked from commit 08e3451d7b3b714ad63a27f1b9c2a23ee75d15ee)
dist/XSLoader/XSLoader_pm.PL
dist/XSLoader/t/XSLoader.t