Subject: | IPv6 addresses with fewer than 4 digits per word handled wrong |
Date: | Sat, 27 Sep 2014 16:36:37 +0200 |
To: | bug-Net-IPAddress-Util [...] rt.cpan.org |
From: | Moritz Bunkus <moritz [...] bunkus.org> |
Hey,
Net::IPAddress::Util v3.012
your module doesn't handle IPv6 addresses in which leading zeros have
been omitted from the words. For example, let's take a simple address:
1:2::1. This is equivalent to 1:2:0:0:0:0:0:1 or
0001:0002:0000:0000:0000:0000:0000:0001. Your module does very, very
wrong things with it:
[0 mosu@sweet-chili ~/tmp] perl -MNet::IPAddress::Util -e 'print Net::IPAddress::Util::IP("1:2::1")->ipv6_expanded, "\n"'
0012:0000:0000:0000:0000:0000:0000:0001
[0 mosu@sweet-chili ~/tmp] perl -MNet::IPAddress::Util -e 'print Net::IPAddress::Util::IP("1:2::1")->normal_form, "\n"'
00120000000000000000000000000001
The problem is in Util's new() function when it tries to parse an IPv6
address. The following two lines…
$upper =~ s/://g;
$lower =~ s/://g;
…are where the information about those omitted leading 0s is lost.
Here's an alternative implementation for the whole »parse IPv6« case:
# Split address into a lower and an upper half.
my @parts = split /::/, $address;
push @parts, '' if scalar(@parts) < 2;
# Process both halves identically.
foreach my $idx (0, 1) {
# Split each word up into its digits/half-bytes and add
# missing leading zeros at the same time.
my @digits;
foreach my $word (split m/:/, $parts[$idx]) {
push @digits, (0) x (4 - length($word)), map { hex } split //, $word;
}
# Assemble two consecutive half-bytes into 16 bytes.
@parts[$idx] = [
map { ($digits[$_ * 2] << 4) + $digits[$_ * 2 + 1] } (0..scalar(@digits) / 2 - 1)
];
}
# Concatenate the processed halves and add the missing 0 bytes
# in the middle where the :: was.
$normal = [
(@{$parts[0]},
(0) x (16 - scalar(@{$parts[0]}) - scalar(@{$parts[1]})),
@{$parts[1]})
];
Kind regards,
mosu
Message body not shown because it is not plain text.