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

Posted by kachick (Kenichi Kamiya) (Guest)
on 2012-05-22 19:50
(Received via mailing list)
Issue #6479 has been reported by kachick (Kenichi Kamiya).

----------------------------------------
Bug #6479: ipaddr.rbの受け付ける書式が、プラットフォームによって異なる
https://bugs.ruby-lang.org/issues/6479

Author: kachick (Kenichi Kamiya)
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
Posted by knu (Akinori MUSHA) (Guest)
on 2012-05-23 09:17
(Received via mailing list)
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の受け付ける書式が、プラットフォームによって異なる
https://bugs.ruby-lang.org/issues/6479#change-26781

Author: kachick (Kenichi Kamiya)
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
Posted by U.Nakamura (Guest)
on 2012-05-23 10:23
(Received via mailing list)
$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, <knu@ruby-lang.org> 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
Posted by Kenichi Kamiya (kachick)
on 2012-05-24 17:05
(Received via mailing list)
$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 <usa@garbagecollect.jp>:
> 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
Posted by Akinori MUSHA (Guest)
on 2012-05-25 07:00
(Received via mailing list)
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, <knu@ruby-lang.org> 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
Posted by U.Nakamura (Guest)
on 2012-05-25 08:35
(Received via mailing list)
$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, <kachick1@gmail.com> 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
Posted by knu (Akinori MUSHA) (Guest)
on 2012-05-30 05:33
(Received via mailing list)
Issue #6479 has been updated by knu (Akinori MUSHA).


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

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

cf. 
http://pubs.opengroup.org/onlinepubs/009696799/fun...

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

なお、あとは x:x:x:x:x:x:d.d.d.d 
形式で今までは意図せずエラーとなっていた部分について仕様を詰めており、これが詰まり次第commitおよびbackportする予定です。もうしばらくお待ちください。
----------------------------------------
Bug #6479: ipaddr.rbの受け付ける書式が、プラットフォームによって異なる
https://bugs.ruby-lang.org/issues/6479#change-26899

Author: kachick (Kenichi Kamiya)
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
Posted by Kenichi Kamiya (kachick)
on 2012-06-01 14:45
(Received via mailing list)
Issue #6479 has been updated by kachick (Kenichi Kamiya).


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

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

> cf. http://pubs.opengroup.org/onlinepubs/009696799/fun...

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

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

御丁寧に有難うございます。
手元の ipaddr.rb を利用しているコード内で問題が表面化している/いそうなわけでもないので、気長に待つつもりでした。
お手すきの際でも結構ですので、引き続き御検討頂けると嬉しいです。
----------------------------------------
Bug #6479: ipaddr.rbの受け付ける書式が、プラットフォームによって異なる
https://bugs.ruby-lang.org/issues/6479#change-26954

Author: kachick (Kenichi Kamiya)
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
Posted by knu (Akinori MUSHA) (Guest)
on 2013-03-07 12:06
(Received via mailing list)
Issue #6479 has been updated by knu (Akinori MUSHA).

Status changed from Assigned to Closed

本件を修正して様子を見るうちに2.0.0が正式リリースとなったので、すみませんが旧シリーズとなった1.9ではこのままとしたいと思います。
報告ありがとうございました。
----------------------------------------
Bug #6479: ipaddr.rbの受け付ける書式が、プラットフォームによって異なる
https://bugs.ruby-lang.org/issues/6479#change-37355

Author: kachick (Kenichi Kamiya)
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
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.