[#45637] [ruby-trunk - Feature #6440][Open] 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい — "Glass_saga (Masaki Matsushita)" <glass.saga@...>

14 messages 2012/05/16

[#45670] [ruby-trunk - Bug #6479][Open] ipaddr.rbの受け付ける書式が、プラットフォームによって異なる — "kachick (Kenichi Kamiya)" <kachick1+ruby@...>

9 messages 2012/05/22

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

From: "kachick (Kenichi Kamiya)" <kachick1+ruby@...>
Date: 2012-05-22 17:49:37 UTC
List: ruby-dev #45670
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


-- 
http://bugs.ruby-lang.org/

In This Thread

Prev Next