سؤال

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.

هل كانت مفيدة؟

المحلول

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.

نصائح أخرى

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);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top