--k1lZvvs/B4yU6o8G
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sun, Oct 15, 2006 at 05:33:16PM +0900, Eric Hodel wrote:
> 
> Please attach the testcase.


OK, i have stripped down the testcase further. The program does not
make much sense anymore, but still shows the bug:

The program calls 

  IPAddrRange.new("192.168.0.0-192.168.255.255")

twice, once directly and once hidden within the

  Whois.get("192.168.155.1")

call. Althoug both calls to IPAddrRange.new do the very same, it works
for the first time and then it fails for the second time, because the
regular expression engine seems to have gone into a state where it
keeps tainting any results. 


When I run the attached program the output looks like this:



% ruby WhoisBug.rb
IPAddrRangeInit 192.168.0.0-192.168.255.255 Tainted false  SAFETainted arg false 192.168.0.0-192.168.255.255  SAFETainted v   false |192.168.0.0|
Tainted b   false |192.168.255.255|

192.168.0.0-192.168.255.255

IPAddrRangeInit 192.168.0.0-192.168.255.255 Tainted false  SAFETainted arg false 192.168.0.0-192.168.255.255  SAFETainted v   false |192.168.0.0|
Tainted b   false |192.168.255.255|
Exception: invalid address  (ArgumentError)
/usr/lib/ruby/1.8/ipaddr.rb:422:in `initialize'
WhoisBug.rb:27:in `new'
WhoisBug.rb:27:in `initialize'
WhoisBug.rb:159:in `new'
WhoisBug.rb:159:in `parse'
WhoisBug.rb:137:in `each'
WhoisBug.rb:137:in `parse'
WhoisBug.rb:94:in `get_whois_net'
WhoisBug.rb:76:in `get'
WhoisBug.rb:186


So calling the same thing twice works only in the first time.

regards
Hadmut

--k1lZvvs/B4yU6o8G
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="WhoisBug.rb"

# Copyright 2003-2006 Hadmut Danisch, hadmut / danisch.de

require 'thread'
require 'monitor'
require 'ipaddr'


##########################################################################

class IPAddrRange
  attr_reader :von, :bis, :mask_len


  def initialize(arg)
    @von,@bis,@maskl,nil,nil
    
    $stderr.puts "IPAddrRangeInit #{arg} Tainted #{arg.tainted?}  SAFE$SAFE}"

    case arg

      when /^([\da-f\.:]+)\s*-\s*([\da-f\.:]+)$/i
        v,b.untaint,$2.untaint
        $stderr.puts "Tainted arg #{arg.tainted?} #{arg}  SAFE$SAFE}"
	$stderr.puts "Tainted v   #{v.tainted?} |#{v}|"
	$stderr.puts "Tainted b   #{b.tainted?} |#{b}|"
        @vonAddr.new(v)
        @bisAddr.new(b)

      else
        raise "Address Range Syntax"
    end
    $stderr.puts
  end


  def to_s
    @von.to_s + "-" + @bis.to_s
  end

end






###########################################################################


class WhoisData
  attr_reader :country,:org,:range,:id,:typ

  def initialize(country,org,range,idl,typl)
    @country,@org,@rangentry,org,range
    @id
    @typ  end


  def to_s
    "#{@country}:  #{@org}   #{@range}"
  end

end


###########################################################################

module Whois


  def Whois.get(ipaddr,dbmutexl)

    ipaddr   PAddr.new(ipaddr)
    addrkey  paddr.native
    result   hois.get_whois_net(addrkey)

    return result
  end



###########################################################################

  def Whois.get_whois_net(net,hostl)
    #whois  jwhois -d #{net}`
    # jwhois call replaced with static data for debugging purposes
    whoisENDE
OrgName:    Internet Assigned Numbers Authority 
Country:    US
NetRange:   192.168.0.0 - 192.168.255.255 
ENDE
    whois.taint
    Whois.parse(whois)
  end




###########################################################################


  def Whois.parse(whois)

    case whois
      when String
	whoisois.split("\n")
      when Array
	# ok
      else
	raise "Argument #{whois.class}"
    end


      wh  }
      for zeile in whois do 
	zeile.delete!("\r\n")
	#puts "Z #{zeile}"

	case zeile 

	  when /^(\w[\w ]+\w)\s*:\s*([-_\s\w\.\,\(\)\/]+)$/
	    wh[$1] unless wh.has_key?($1)
	  
        end
      end

      #wh.keys.sort.each{|k| printf "%-20.20s %s\n",k,wh[k]}




      # Here the bug begins:
      # Problem does not occur if we pass back the same results directly
      # return "US","IANA",IPAddrRange.new("192.168.0.0 - 192.168.255.255")
      
      for i in [
  	  ["NetRange",     "OrgName",  "Country"],
  	  ["NetRange",     "NetName",  "Country"],
  	] do
  	
   	  netkey,orgkey,countrykey
          if    wh.has_key?(netkey) &&
         	wh.has_key?(orgkey)  &&
  	        wh.has_key?(countrykey)	

	    addr[netkey].gsub(" ","")
	 
	    case addr 
	      when /^[-\.\d]+$/
		addr¥ådr.untaint
	      else
	        raise "Address syntax"
	    end

	    #$stderr.puts "Angekommen #{wh[orgkey]} |#{wh[netkey]}|#{addr}|#{addr.tainted?}"
	    return  WhoisData.new(wh[countrykey],  
				  wh[orgkey],
				  IPAddrRange.new(addr)) 
	  end #if
      end #for

      return nil
    
  end









end


###########################################################################

if __FILE__ $0
  begin

    $SAFE    puts IPAddrRange.new("192.168.0.0-192.168.255.255")
    puts
    puts Whois.get("192.168.155.1")

  rescue SystemExit
    raise
  rescue Exception exc
    $stderr.puts "Exception: #{exc}  (#{exc.class.to_s})"
    $stderr.puts exc.backtrace
    exit 99
  end

end

--k1lZvvs/B4yU6o8G--