Domanda

I want to pack various results of expressions with integer overflow checking in Perl (signed, unsigned, big-endian and little-endian). If I try:

$ perl -e 'use warnings; print pack("c", 200)' | hexdump -C

I get:

Character in 'c' format wrapped in pack at -e line 1.
00000000  c8                                                |.|
00000001

Is there a way to check the integer overflow occurred in the pack() function? Or maybe force the function to fail on overflow? If I will check the range for each type before packing (signed 1,2,4,8 bytes, unsigned 1,2,4,8), the code seems slightly ugly.

Thanks.

È stato utile?

Soluzione

You can turn on the "pack" warning category and make it fatal. Then an overflow would cause an exception which can be trapped. E.g.:

for my $val (127, 128) {
    print "$val -> ";
    if (eval {
        use warnings FATAL => qw(pack);
        pack("c", $val);
    }) {
        print "no overflow";
    } else {
        print "overflow ($@)";
    }
    print "\n";
}

Another possibility is to use a (preferably local-ized) $SIG{__WARN__} handler and check in the handler if a warning happened.

Altri suggerimenti

Fatalizing warnings is the simplest solution, but you could write your own packing functions.

use Carp         qw( croak );
use Scalar::Util qw( looks_like_number );

sub pack_uint32_be {
   my ($n) = @_;
   croak "Not a number" unless looks_like_number($n);
   croak "Overflow"     unless 0 < $n && $n <= 2**32;
   return pack 'L>', $n;
}

$packed .= pack_uint32_be($x);
$packed .= pack_uint32_be($y);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top