in reply to pack() returns an unusable string

Parameters can't contain the NUL character. Your so-called working code breaks if you change 2.4 to 2.5 (which generates at least one a NUL byte).

I recommend that you pass the hex of the packed string. You could also use base64, JSON, etc, etc, etc.


Furthermore, you have a code-injection bug. "'$p'" is not an appropriate way to generate a Perl string literal. $p could easily contain byte 0x27 (single quote). A trailing byte 0x5C (backslash) would also be problematic.

I recommend that you pass the value as an argument.


use strict; use warnings; my $template = 'd<'; my $nv = 2.5; my $p = pack $template, $nv; system $^X, '-wle', 'print $ARGV[0]', unpack('H*', $p);

Seeking work! You can reach me at ikegami@adaelis.com

Replies are listed 'Best First'.
Re^2: pack() returns an unusable string
by syphilis (Bishop) on May 29, 2021 at 08:53 UTC
    I recommend that you pass the value as an argument

    What I was wanting to do was to pass the actual string as the argument.
    It didn't really occur to me that doing that would be such a problem. I thought that people would be able to show me that this could be achieved with little fuss. (I was wrong ;-)
    What I was interested in doing is easily demonstrated in the following script, where I've used the code that you supplied, but have replaced the last line with 2 lines:
    use strict; use warnings; my $template = 'D<'; my $nv = 2.4; my $p = pack $template, $nv; # I'm running this script on perl-5.34.0 # with nvtype of 'long double'. # I want to see the result of perl-5.34.0 # with nvtype of 'double' unpacking $p : my $perl = "C:/perl-5.34.0/bin/MSWin32-x64-multi-thread/perl.exe"; system $perl, '-wle', 'print unpack("H*", $p)';
    If that DWIMmed, it would output :
    9a999999999999990040000000000000
    but, of course, all that it emits is the warning:
    Use of uninitialized value $_ in print at -e line 1.
    Sure, I could take a leaf out of your book and alter my last line to:
    system $perl, '-wle', 'print $ARGV[0]', unpack('H*', $p);
    But that unpack('H*', $p) is being evaluated by the 'long double' build of perl.
    I wanted to see what happened when it was evaluated by my 'double' build of perl-5.34.0.
    I've since accomplished this by other means.

    Cheers,
    Rob

      unpack "H*" hasn't changed, so what you're saying makes no sense. Encode the string in the parent (say using unpack "H*"), then recreate the original in the child if so you desire (using pack "H*").

      Seeking work! You can reach me at ikegami@adaelis.com

        unpack "H*" hasn't changed, so what you're saying makes no sense.

        Well - you apparently knew that, but I didn't.
        I was fairly certain it would be the case and that it should be the case, but I wanted to verify it with an actual example, and your approach does not provide that verification.
        (Admittedly, it is pretty hard to see how anything else *could* be the case ;-)

        I was also wanting to do the same thing, but replacing "H*" with "D" - in order to verify that rounding would be performed as expected. (It is ... so long as one's expectation is correct.)
        Wrt perl-5.34.0, unlike unpack("H*", $string) we see that the value returned by unpack("D", $string) will often vary between 'double' and 'long double' builds, for the very same $string.
        I don't doubt that you regard running those checks as also being something that "makes no sense".
        But having a "D" template on a perl whose nvtype is 'double' is a little disconcerting to me, and I just want to make sure that its behaviour is clear in my mind.

        Cheers,
        Rob