develooper Front page | perl.perl5.porters | Postings from July 2000

Re: [ID 20000606.004] Safe::, modules and _

July 31, 2000 11:11
Re: [ID 20000606.004] Safe::, modules and _
Message ID:
I'm one of those folks that use modules inside of Safe:: partitions.
While Sarathy's patch to "localize" %INC is one necessary part of using
modules inside of Safe partitions, it isn't quite enough...

As the following snippet of code shows:

#! perl
use Safe;
$s = new Safe 'FOO';
$s->reval('@c = caller; print qq(called from module "$c[0]"\n);');

(you'll get 'called from module "FOO"' with an unmodified Opcode.XS
for Perl versions back to ~5.002)

Code running inside of a Safe partition that checks 'caller' will get the
partition name.  No problem, except that there are modules out there that
use 'caller' to do their exporting, and they will fail horribly.

The solution is a small patch to Opcode.xs that changes the HvNAME of
partition's stash to "main".  You still reference it from the outside
via $FOO::whatever, but code inside the partition sees a package name
of "main::" and  the tricky exporting logic works correctly.

The second problem addressed by the patch below is that filetests on _
fail inside a Safe partition.  But first a program to demonstrate the

#!  perl
use Safe;
$s = new Safe 'FOO';
$script = <<'TESTSCRIPT';
opendir(D,'.') || die('horribly');
while (defined($d = readdir(D))) {
    $d =~ s/\.dir$// if $^O eq 'VMS';
    next if !(-d $d);
    print "directory $d is ".((-d $d && -w _) ? '' : 'not ')."writable\n";
print "--------------- not in Safe:: ----------------\n";
print "---------------  in Safe:: ----------------\n";
print "---------------  done      ----------------\n";

This code checks for subdirectories and whether they are writable;
Prior to the patch, you should see that all of the subdirectories
tested in the Safe partition are considered "not writable", even if
they are.

The reason is that when compiling code in the Safe partition _ is
looked up in the partition stash...then the gv for _ is compared to
PL_defgv and found to be different, bypassing the "use the results of
the last stat" logic.

Again the fix is in Opcode.xs, by creating an entry for _ in the
partition stash and pointing it to the "real, true main::_". Or at
least to PL_defgv.

There's a bunch of global symbols that need to be either set (because
they're no longer global inside the partition) or localized around
calls to the code inside the partition, but that can be handled in Perl
code, and doesn't really affect module loading.

Patch for Opcode for Perl >= 5.005.59

1) make routines in Safe:: partitions think they are in main::
2) connect the _ in the partition to the global _

--- ext/Opcode/Opcode.xs-orig	Wed Jul 26 07:00:15 2000
+++ ext/Opcode/Opcode.xs	Wed Jul 26 06:59:39 2000
@@ -253,6 +253,12 @@
     save_hptr(&PL_defstash);		/* save current default stack	*/
     /* the assignment to global defstash changes our sense of 'main'	*/
     PL_defstash = gv_stashpv(Package, GV_ADDWARN); /* should exist already	*/
+    if (strNE(HvNAME(PL_defstash),"main")) {
+        Safefree(HvNAME(PL_defstash));         
+        HvNAME(PL_defstash) = savepv("main"); /* make it think it's in main:: */
+        hv_store(PL_defstash,"_",1,(SV *)PL_defgv,0);  /* connect _ to global */
+        SvREFCNT_inc((SV *)PL_defgv);  /* want to keep _ around! */
+    }
     PL_curstash = PL_defstash;
 Drexel University       \V                    --Chuck Lane
     (215) 895-1545     _/ \  Particle Physics
FAX: (215) 895-5934     /\ /~~~~~~~~~~~ Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About