in reply to Re: Perl 6: Static/Dynamic Strong/Weak Type Systems
in thread Perl 6: Static/Dynamic Strong/Weak Type Systems

Reach in arbitrary memory? Sure. We can do that. :-)

unpack 'P', pack 'j', []

⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Replies are listed 'Best First'.
Re^3: Perl 6: Static/Dynamic Strong/Weak Type Systems
by fergal (Chaplain) on Apr 16, 2006 at 09:41 UTC
    I've never seen p and P in pack before and I can't figure out what they actually do (as in I have read the docs, tried some code but still don't understand). I thought
    #! /usr/bin/perl -l $a="fergal"; $p=\$a+0; print $p; $x=unpack("P9", pack 'j', $p); print length($x);
    might read the first 9 bytes of the SV structure for $a but it just has length 0. Do you have a demo?

    Anyway, this is not really what I'm getting at. You can't use this to try treat the memory for a perl array variable as a perl string variable, at most this allows you to treat the memory for a perl array variable as the C string inside a perl string variable.

    Imagine you could twiddle the pointer inside a perl reference value, it still wouldn't be weakly typed. If you point the ref at a bit of memory that contains a perl string variable then it will become a string-ref if you point it at an array variable it will become an array-ref (I think this is the case although I'm not an XS whizz and I don't have time to test it as I'm going on holidays in an hour!). So for perl to be weakly typed I would have to wrong and the language would have to have this reference twiddling feature built in.

      Demo? I've had this code lying around for ages:

      #!/usr/bin/perl -wl use strict; my $target = 'IHBT'; print "target contains : $target"; my $target_address = \$target + 0; # nummify my $native_version = pack 'L', $target_address; my $pointer = pack 'P', $native_version; print "target address : ", sprintf('%x', $target_address); my $sv = unpack('P4', $native_version); print "deref'd packed (sv) : ", sprintf('%x', unpack('L', $sv)); my $pv = unpack('P4', $sv); print "deref'd sv (pv) : ", sprintf('%x', unpack('L', $pv)); my $value = unpack('P' . length($target), $pv); print "deref'd pv (value) : ``$value''\n";

      I hope it helps. :)

      You're just missing a few pointer dereferences. The pack("j",...) does the int->ptr conversion. The first unpack does SvANY( $p ) to find $a. The next one doesSvANY( $a ) to find its xpv struct. The next and final unpack is dereffing the xpv_pv pointer to read the C string.

      $x = unpack "P9", unpack "P4", unpack "P4", pack "j", $p;

      This is all *reading* addressable memory. Writing back to it is a completely different trick involving faking structs for B to convince perl that strings that you control are real perl structures. You can then fake up a perl string where the pointer goes to any arbitrary location.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊