[ruby-trunk - Bug #6479][Open] ipaddr.rbの受け付ける書式が、プラットフォームによって異なる

Issue #6479 has been reported by kachick (Kenichi K.).


Bug #6479: ipaddr.rbの受け付ける書式が、プラットフォームによって異なる

Author: kachick (Kenichi K.)
Status: Open
Priority: Normal
Assignee:
Category: lib
Target version: 1.9.3
ruby -v: ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]

状況

標準添付ライブラリの ipaddr.rb に於いて、アドレス書式チェック時の厳しさがプラットフォームによって異なるよう感じました。
IPv4で気がついた限りですが、次の2点でWindowsだと常に例外を吐き、Linuxだと書式によっては(自分にとって)想定し難い値を返します。

  • 0埋めを含んだ場合
  • 改行文字を含んだ場合

動作例を載せます。

共通

require 'ipaddr'

p IPAddr.new("11.22.33.45") #=> #<IPAddr: 

IPv4:11.22.33.45/255.255.255.255>

Windows(7) / ruby 1.9.3p194 (2012-04-20) [i386-mingw32]

# 以下全てで、同じ例外を吐きます。
p IPAddr.new("011.22.33.45")
p IPAddr.new("011.0022.00033.000045")
p IPAddr.new("011.0022.00033.000045\n")
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar  ")
p 

IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ")

# 例外
ArgumentError: invalid address
from C:/Ruby193/lib/ruby/1.9.1/ipaddr.rb:496:in `rescue in 

initialize’

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

# Windowsの際と同じ引数に対して、一つも例外を吐きません
p IPAddr.new("011.22.33.45") 

#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045\n”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar ")
#=> #<IPAddr: IPv4:11.22.33.0/255.255.255.0>
p
IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ") #=> #<IPAddr: IPv4:45.67.78.0/255.255.255.0>

希望

Windows環境下の例にみるよう、上記全てのパターンで例外を吐いてくれる方が自然に感じました。
特にLinux上での0埋めに関しては、桁数に制限が見られ無い点と、IPSocket.getaddress(8進数?)と返す値の異なってしまう点が気になります。

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

require 'socket'

p IPSocket.getaddress("011.0022.00033.000045") #=> "9.18.27.37"

参考

ipaddr.rbを自分なりに読んでみた限り、次の要素に起因するのではないかとあたりをつけてみましたが・・・確信はありません。

  • 全体的に、チェック用正規表現のメタ文字へ \A\z を使わず、 \A\Z や ^$ で括っていること
  • #initialize で、 IPSocket.getaddress が例外を返すかどうかに、正常異常の判断を大きく委ねていること
  • #in_addr で、1つのオクテットを \d+ のみでキャプチャしていること

とりあえず、#in_addrのみを次のように上書きした際、Windowsと同様に動作することまでは確認できました。

require 'ipaddr'

class IPAddr

  private

  remove_method :in_addr

  def in_addr(addr)
    if addr =~ /\A(?:(?:0|[1-9]\d{0,2})\.){3}(?:0|[1-9]\d{0,2})\z/
      return addr.split('.').inject(0) { |i, s|
        n = s.to_i
        raise ArgumentError, 'invalid address' unless n <= 255

        i << 8 | n
      }
    end
    return nil
  end

end

$B$3$s$K$A$O!"$J$+$`$i(B($B$&(B)$B$G$9!#(B

In message “[ruby-dev:45671] [ruby-trunk - Bug #6479][Assigned]
ipaddr.rb$B$N<u$1IU$1$k=q<0$,!”%W%i%C%H%U%)!<%`$K$h$C$F0[$J$k(B"
on May.23,2012 16:16:40, [email protected] wrote:

$B$H$j$“$($:!”(B#in_addr$B$N$_$r<!$N$h$&$K>e=q$-$7$?:]!"(BWindows$B$HF1MM$KF0:n$9$k$3$H$^$G$O3NG’$G$-$^$7$?!#(B

Socket::AF_INET6$B$,$J$$>l9g$K(BIPSocket.getaddress$B$r>e=q$-$7$F$$(B
$B$k%3!<%I$,(Bipaddr.rb$B$NKAF,$K$“$k$H;W$$$^$9$N$G!”%W%i%C%H%U%)!<(B
$B%`Ds6!$N$=$l$,?.MQ$G$-$J$$$J$i$3$C$A$r>o$KM-8z$K$9$k$N$b$"$j(B
$B$+$b$7$l$^$;$s!#(B
Windows$B$@$H$?$V$s$=$l$r;H$C$F$k$s$@$H;W$$$^$9!#(B

$B$=$l$G$O!#(B

$B$3$s$P$s$O!"$+$_$d$G$9!#(B
$B$4JV?.M-Fq$&$4$6$$$^$9!#(B

2012$BG/(B5$B7n(B23$BF|(B 17:23 U.Nakamura [email protected]:

Socket::AF_INET6$B$,$J$$>l9g$K(BIPSocket.getaddress$B$r>e=q$-$7$F$$(B
$B$k%3!<%I$,(Bipaddr.rb$B$NKAF,$K$“$k$H;W$$$^$9$N$G!”%W%i%C%H%U%)!<(B
$B%`Ds6!$N$=$l$,?.MQ$G$-$J$$$J$i$3$C$A$r>o$KM-8z$K$9$k$N$b$"$j(B
$B$+$b$7$l$^$;$s!#(B

$B3N$+$K!“$I$N4D6-$G$b$3$NJU$N%A%'%C%/$r7PM3$9$k$h$&$K$J$l$P(B
$B0B?446$,A}$9$H;W$$$^$9!#(B
$BDI2C$5$l$k(B IPSocket.valid_v4? $B$@$H(B
$B!”!V(B0$BKd$a$O(B3$B7e$^$G5vMF!W(B
$B!VKvHx$N2~9TJ8;z$O5vMF!W(B $B$K$J$k46$8$G$7$g$&$+(B

Windows$B$@$H$?$V$s$=$l$r;H$C$F$k$s$@$H;W$$$^$9!#(B

$B$?$@!“8=:_(BWindows$B>e$G$3$l$i$N%Q%?!<%s$rCF$$$F$/$l$F$$$k$N$H!”(B
ipaddr$B%i%$%V%i%j$N(B require$BA0$G$b!"(B
Socket::AF_INET6 $B$NDj5A$5$l$F$$$k$3$H$,5$$K$J$j$^$7$?!#(B

Windows(7) / ruby 1.9.3p194 (2012-04-20) [i386-mingw32]

require 'socket'

Socket.const_defined? :AF_INET6 #=> true
Socket::AF_INET6                #=> 23

$B2?$+:,K\E*$K4*0c$$$7$F$$$k$h$&$G$“$l$P?=$7Lu$”$j$^$;$s!#(B

At Wed, 23 May 2012 17:23:23 +0900,
U.Nakamura wrote:

In message “[ruby-dev:45671] [ruby-trunk - Bug #6479][Assigned]
ipaddr.rb$B$N<u$1IU$1$k=q<0$,!”%W%i%C%H%U%)!<%`$K$h$C$F0[$J$k(B"
on May.23,2012 16:16:40, [email protected] wrote:

$B$H$j$“$($:!”(B#in_addr$B$N$_$r<!$N$h$&$K>e=q$-$7$?:]!"(BWindows$B$HF1MM$KF0:n$9$k$3$H$^$G$O3NG’$G$-$^$7$?!#(B

Socket::AF_INET6$B$,$J$$>l9g$K(BIPSocket.getaddress$B$r>e=q$-$7$F$$(B
$B$k%3!<%I$,(Bipaddr.rb$B$NKAF,$K$“$k$H;W$$$^$9$N$G!”%W%i%C%H%U%)!<(B
$B%`Ds6!$N$=$l$,?.MQ$G$-$J$$$J$i$3$C$A$r>o$KM-8z$K$9$k$N$b$"$j(B
$B$+$b$7$l$^$;$s!#(B
Windows$B$@$H$?$V$s$=$l$r;H$C$F$k$s$@$H;W$$$^$9!#(B

IPAddr.new $B$K$*$1$k(B IPSocket.getaddress
$B$N8F$S=P$7$G$9$,!“?dB,$9$k$K!”(B
Socket.getaddrinfo(…, Socket::AI_NUMERICHOST)
$B$,0U?^DL$jF0$$$F$/$l$J(B
$B$+$C$?$N$G(B IPSocket.getaddress $B$K=q$-49$($?$,!“A[Dj!J(Bsocket
$B$N(BIPv6$BBP1~(B
$B$O40N;$7$F$$$?$N$G!D!K$KH?$7$F$3$$$D$N(BIPv6$B%”%I%l%9BP1~$,%W%i%C%H%U%)!<(B
$B%`0MB8$@$C$?$H$$$&$3$H$G$O$J$$$+$H;W$$$^$9!#(B

$B$$$:$l$K$7$F$b!“(B IPAddr
$B%l%Y%k$G$N%W%i%C%H%U%)!<%`0MB8@-$OK>$^$7$/$J$$(B
$B$N$G!”$3$l$r8F$VA0$K8!::$*$h$S@55,2=!J%<%mKd$aGS=|Ey!K$9$k$h$&$K$7$^$9!#(B

$B$J$!"(B IPSocket.valid? $B>r7oIU$-$GI=$K=P$k$N$OJQ$J$N$G$3$3$O(B
private $B$K(B
$B$7!“(B IPSocket.getaddress $B$N>e=q$-$K$D$$$F$b(B AF_INET6
$B$,$J$$>l9g$N(B
IPv6$B%”%I%l%9BP1~$NIU2CDxEY$K;_$a$?$$$H;W$$$^$9!#(B

$B$3$s$K$A$O!"$J$+$`$i(B($B$&(B)$B$G$9!#(B

In message “[ruby-dev:45678] Re: [ruby-trunk - Bug #6479][Assigned]
ipaddr.rb$B$N<u$1IU$1$k=q<0$,!”%W%i%C%H%U%)!<%`$K$h$C$F0[$J$k(B"
on May.25,2012 00:03:08, [email protected] wrote:

Windows$B$@$H$?$V$s$=$l$r;H$C$F$k$s$@$H;W$$$^$9!#(B

$B$?$@!“8=:_(BWindows$B>e$G$3$l$i$N%Q%?!<%s$rCF$$$F$/$l$F$$$k$N$H!”(B
ipaddr$B%i%$%V%i%j$N(B require$BA0$G$b!"(B
Socket::AF_INET6 $B$NDj5A$5$l$F$$$k$3$H$,5$$K$J$j$^$7$?!#(B

$B$“!<!”(BWindows$B$N(BIPv6$B%5%]!<%H$O:#$OM-8z$J$s$G$7$?$C$1!#(B

$B<+J,$G$d$C$?$N$KK:$l$F$$$k!#(B

$B2?$+:,K\E*$K4*0c$$$7$F$$$k$h$&$G$“$l$P?=$7Lu$”$j$^$;$s!#(B

$B$J$N$G4*0c$$$7$F$$$?$N$O;d$N$h$&$G$9!#(B

$B$=$l$G$O!#(B

Issue #6479 has been updated by knu (Akinori MUSHA).

Status changed from Open to Assigned
Assignee set to knu (Akinori MUSHA)


Bug #6479: ipaddr.rbの受け付ける書式が、プラットフォームによって異なる

Author: kachick (Kenichi K.)
Status: Assigned
Priority: Normal
Assignee: knu (Akinori MUSHA)
Category: lib
Target version: 1.9.3
ruby -v: ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]

状況

標準添付ライブラリの ipaddr.rb に於いて、アドレス書式チェック時の厳しさがプラットフォームによって異なるよう感じました。
IPv4で気がついた限りですが、次の2点でWindowsだと常に例外を吐き、Linuxだと書式によっては(自分にとって)想定し難い値を返します。

  • 0埋めを含んだ場合
  • 改行文字を含んだ場合

動作例を載せます。

共通

require 'ipaddr'

p IPAddr.new("11.22.33.45") #=> #<IPAddr: 

IPv4:11.22.33.45/255.255.255.255>

Windows(7) / ruby 1.9.3p194 (2012-04-20) [i386-mingw32]

# 以下全てで、同じ例外を吐きます。
p IPAddr.new("011.22.33.45")
p IPAddr.new("011.0022.00033.000045")
p IPAddr.new("011.0022.00033.000045\n")
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar  ")
p 

IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ")

# 例外
ArgumentError: invalid address
from C:/Ruby193/lib/ruby/1.9.1/ipaddr.rb:496:in `rescue in 

initialize’

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

# Windowsの際と同じ引数に対して、一つも例外を吐きません
p IPAddr.new("011.22.33.45") 

#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045\n”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar ")
#=> #<IPAddr: IPv4:11.22.33.0/255.255.255.0>
p
IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ") #=> #<IPAddr: IPv4:45.67.78.0/255.255.255.0>

希望

Windows環境下の例にみるよう、上記全てのパターンで例外を吐いてくれる方が自然に感じました。
特にLinux上での0埋めに関しては、桁数に制限が見られ無い点と、IPSocket.getaddress(8進数?)と返す値の異なってしまう点が気になります。

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

require 'socket'

p IPSocket.getaddress("011.0022.00033.000045") #=> "9.18.27.37"

参考

ipaddr.rbを自分なりに読んでみた限り、次の要素に起因するのではないかとあたりをつけてみましたが・・・確信はありません。

  • 全体的に、チェック用正規表現のメタ文字へ \A\z を使わず、 \A\Z や ^$ で括っていること
  • #initialize で、 IPSocket.getaddress が例外を返すかどうかに、正常異常の判断を大きく委ねていること
  • #in_addr で、1つのオクテットを \d+ のみでキャプチャしていること

とりあえず、#in_addrのみを次のように上書きした際、Windowsと同様に動作することまでは確認できました。

require 'ipaddr'

class IPAddr

  private

  remove_method :in_addr

  def in_addr(addr)
    if addr =~ /\A(?:(?:0|[1-9]\d{0,2})\.){3}(?:0|[1-9]\d{0,2})\z/
      return addr.split('.').inject(0) { |i, s|
        n = s.to_i
        raise ArgumentError, 'invalid address' unless n <= 255

        i << 8 | n
      }
    end
    return nil
  end

end

Issue #6479 has been updated by kachick (Kenichi K.).

武者さん、なかむら(う)さん

お二方とも、御返信下さり有難う御座います。

cf. inet_addr

0埋め時のC側に於ける解釈は、8進数にする旨明記されていたのですね
由来が把握できて、すっきりしました。

なお、あとは x:x:x:x:x:x:d.d.d.d
形式で今までは意図せずエラーとなっていた部分について仕様を詰めており、これが詰まり次第commitおよびbackportする予定です。もうしばらくお待ちください。

御丁寧に有難うございます。
手元の ipaddr.rb を利用しているコード内で問題が表面化している/いそうなわけでもないので、気長に待つつもりでした。
お手すきの際でも結構ですので、引き続き御検討頂けると嬉しいです。

Bug #6479: ipaddr.rbの受け付ける書式が、プラットフォームによって異なる

Author: kachick (Kenichi K.)
Status: Assigned
Priority: Normal
Assignee: knu (Akinori MUSHA)
Category: lib
Target version: 1.9.3
ruby -v: ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]

状況

標準添付ライブラリの ipaddr.rb に於いて、アドレス書式チェック時の厳しさがプラットフォームによって異なるよう感じました。
IPv4で気がついた限りですが、次の2点でWindowsだと常に例外を吐き、Linuxだと書式によっては(自分にとって)想定し難い値を返します。

  • 0埋めを含んだ場合
  • 改行文字を含んだ場合

動作例を載せます。

共通

require 'ipaddr'

p IPAddr.new("11.22.33.45") #=> #<IPAddr: 

IPv4:11.22.33.45/255.255.255.255>

Windows(7) / ruby 1.9.3p194 (2012-04-20) [i386-mingw32]

# 以下全てで、同じ例外を吐きます。
p IPAddr.new("011.22.33.45")
p IPAddr.new("011.0022.00033.000045")
p IPAddr.new("011.0022.00033.000045\n")
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar  ")
p 

IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ")

# 例外
ArgumentError: invalid address
from C:/Ruby193/lib/ruby/1.9.1/ipaddr.rb:496:in `rescue in 

initialize’

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

# Windowsの際と同じ引数に対して、一つも例外を吐きません
p IPAddr.new("011.22.33.45") 

#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045\n”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar ")
#=> #<IPAddr: IPv4:11.22.33.0/255.255.255.0>
p
IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ") #=> #<IPAddr: IPv4:45.67.78.0/255.255.255.0>

希望

Windows環境下の例にみるよう、上記全てのパターンで例外を吐いてくれる方が自然に感じました。
特にLinux上での0埋めに関しては、桁数に制限が見られ無い点と、IPSocket.getaddress(8進数?)と返す値の異なってしまう点が気になります。

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

require 'socket'

p IPSocket.getaddress("011.0022.00033.000045") #=> "9.18.27.37"

参考

ipaddr.rbを自分なりに読んでみた限り、次の要素に起因するのではないかとあたりをつけてみましたが・・・確信はありません。

  • 全体的に、チェック用正規表現のメタ文字へ \A\z を使わず、 \A\Z や ^$ で括っていること
  • #initialize で、 IPSocket.getaddress が例外を返すかどうかに、正常異常の判断を大きく委ねていること
  • #in_addr で、1つのオクテットを \d+ のみでキャプチャしていること

とりあえず、#in_addrのみを次のように上書きした際、Windowsと同様に動作することまでは確認できました。

require 'ipaddr'

class IPAddr

  private

  remove_method :in_addr

  def in_addr(addr)
    if addr =~ /\A(?:(?:0|[1-9]\d{0,2})\.){3}(?:0|[1-9]\d{0,2})\z/
      return addr.split('.').inject(0) { |i, s|
        n = s.to_i
        raise ArgumentError, 'invalid address' unless n <= 255

        i << 8 | n
      }
    end
    return nil
  end

end

Issue #6479 has been updated by knu (Akinori MUSHA).

本件の実装の大枠はもうできていて、あとはどういう表記を認めるかというところで諸方面に確認中ですが、ゼロ埋めについては不許可にしたいと思うようになりました。

というのもアドレスのパースに用いられるCの inet_addr()
の仕様を見ると、ドット区切りの各オクテットが0で始まるときは8進数として扱うべしとあり、一方でゼロ埋めの十進3桁固定方式も入力フォーム等で見られるため、ライブラリ側ではいずれとも判断しかねるからです。

cf.
http://pubs.opengroup.org/onlinepubs/009696799/functions/inet_addr.html

従来もWindowsではエラーになっていたことですし、ここで禁止とするのもありかなと思います。

なお、あとは x:x:x:x:x:x:d.d.d.d
形式で今までは意図せずエラーとなっていた部分について仕様を詰めており、これが詰まり次第commitおよびbackportする予定です。もうしばらくお待ちください。

Bug #6479: ipaddr.rbの受け付ける書式が、プラットフォームによって異なる

Author: kachick (Kenichi K.)
Status: Assigned
Priority: Normal
Assignee: knu (Akinori MUSHA)
Category: lib
Target version: 1.9.3
ruby -v: ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]

状況

標準添付ライブラリの ipaddr.rb に於いて、アドレス書式チェック時の厳しさがプラットフォームによって異なるよう感じました。
IPv4で気がついた限りですが、次の2点でWindowsだと常に例外を吐き、Linuxだと書式によっては(自分にとって)想定し難い値を返します。

  • 0埋めを含んだ場合
  • 改行文字を含んだ場合

動作例を載せます。

共通

require 'ipaddr'

p IPAddr.new("11.22.33.45") #=> #<IPAddr: 

IPv4:11.22.33.45/255.255.255.255>

Windows(7) / ruby 1.9.3p194 (2012-04-20) [i386-mingw32]

# 以下全てで、同じ例外を吐きます。
p IPAddr.new("011.22.33.45")
p IPAddr.new("011.0022.00033.000045")
p IPAddr.new("011.0022.00033.000045\n")
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar  ")
p 

IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ")

# 例外
ArgumentError: invalid address
from C:/Ruby193/lib/ruby/1.9.1/ipaddr.rb:496:in `rescue in 

initialize’

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

# Windowsの際と同じ引数に対して、一つも例外を吐きません
p IPAddr.new("011.22.33.45") 

#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045\n”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar ")
#=> #<IPAddr: IPv4:11.22.33.0/255.255.255.0>
p
IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ") #=> #<IPAddr: IPv4:45.67.78.0/255.255.255.0>

希望

Windows環境下の例にみるよう、上記全てのパターンで例外を吐いてくれる方が自然に感じました。
特にLinux上での0埋めに関しては、桁数に制限が見られ無い点と、IPSocket.getaddress(8進数?)と返す値の異なってしまう点が気になります。

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

require 'socket'

p IPSocket.getaddress("011.0022.00033.000045") #=> "9.18.27.37"

参考

ipaddr.rbを自分なりに読んでみた限り、次の要素に起因するのではないかとあたりをつけてみましたが・・・確信はありません。

  • 全体的に、チェック用正規表現のメタ文字へ \A\z を使わず、 \A\Z や ^$ で括っていること
  • #initialize で、 IPSocket.getaddress が例外を返すかどうかに、正常異常の判断を大きく委ねていること
  • #in_addr で、1つのオクテットを \d+ のみでキャプチャしていること

とりあえず、#in_addrのみを次のように上書きした際、Windowsと同様に動作することまでは確認できました。

require 'ipaddr'

class IPAddr

  private

  remove_method :in_addr

  def in_addr(addr)
    if addr =~ /\A(?:(?:0|[1-9]\d{0,2})\.){3}(?:0|[1-9]\d{0,2})\z/
      return addr.split('.').inject(0) { |i, s|
        n = s.to_i
        raise ArgumentError, 'invalid address' unless n <= 255

        i << 8 | n
      }
    end
    return nil
  end

end

Issue #6479 has been updated by knu (Akinori MUSHA).

Status changed from Assigned to Closed

本件を修正して様子を見るうちに2.0.0が正式リリースとなったので、すみませんが旧シリーズとなった1.9ではこのままとしたいと思います。
報告ありがとうございました。

Bug #6479: ipaddr.rbの受け付ける書式が、プラットフォームによって異なる

Author: kachick (Kenichi K.)
Status: Closed
Priority: Normal
Assignee: knu (Akinori MUSHA)
Category: lib
Target version: next minor
ruby -v: ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]

状況

標準添付ライブラリの ipaddr.rb に於いて、アドレス書式チェック時の厳しさがプラットフォームによって異なるよう感じました。
IPv4で気がついた限りですが、次の2点でWindowsだと常に例外を吐き、Linuxだと書式によっては(自分にとって)想定し難い値を返します。

  • 0埋めを含んだ場合
  • 改行文字を含んだ場合

動作例を載せます。

共通

require 'ipaddr'

p IPAddr.new("11.22.33.45") #=> #<IPAddr: 

IPv4:11.22.33.45/255.255.255.255>

Windows(7) / ruby 1.9.3p194 (2012-04-20) [i386-mingw32]

# 以下全てで、同じ例外を吐きます。
p IPAddr.new("011.22.33.45")
p IPAddr.new("011.0022.00033.000045")
p IPAddr.new("011.0022.00033.000045\n")
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar  ")
p 

IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ")

# 例外
ArgumentError: invalid address
from C:/Ruby193/lib/ruby/1.9.1/ipaddr.rb:496:in `rescue in 

initialize’

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

# Windowsの際と同じ引数に対して、一つも例外を吐きません
p IPAddr.new("011.22.33.45") 

#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new(“011.0022.00033.000045\n”)
#=> #<IPAddr: IPv4:11.22.33.45/255.255.255.255>
p IPAddr.new("011.0022.00033.000045\nfoo32/0024/bar \n/foobar ")
#=> #<IPAddr: IPv4:11.22.33.0/255.255.255.0>
p
IPAddr.new("011.0022.00033.000045\n056.0067.00078.00089\nfoo32/0024/bar
\n/foobar ") #=> #<IPAddr: IPv4:45.67.78.0/255.255.255.0>

希望

Windows環境下の例にみるよう、上記全てのパターンで例外を吐いてくれる方が自然に感じました。
特にLinux上での0埋めに関しては、桁数に制限が見られ無い点と、IPSocket.getaddress(8進数?)と返す値の異なってしまう点が気になります。

Linux(Mint12) / ruby 1.9.3p194 (2012-04-20 revision 35410)

[i686-linux]

require 'socket'

p IPSocket.getaddress("011.0022.00033.000045") #=> "9.18.27.37"

参考

ipaddr.rbを自分なりに読んでみた限り、次の要素に起因するのではないかとあたりをつけてみましたが・・・確信はありません。

  • 全体的に、チェック用正規表現のメタ文字へ \A\z を使わず、 \A\Z や ^$ で括っていること
  • #initialize で、 IPSocket.getaddress が例外を返すかどうかに、正常異常の判断を大きく委ねていること
  • #in_addr で、1つのオクテットを \d+ のみでキャプチャしていること

とりあえず、#in_addrのみを次のように上書きした際、Windowsと同様に動作することまでは確認できました。

require 'ipaddr'

class IPAddr

  private

  remove_method :in_addr

  def in_addr(addr)
    if addr =~ /\A(?:(?:0|[1-9]\d{0,2})\.){3}(?:0|[1-9]\d{0,2})\z/
      return addr.split('.').inject(0) { |i, s|
        n = s.to_i
        raise ArgumentError, 'invalid address' unless n <= 255

        i << 8 | n
      }
    end
    return nil
  end

end