我如何在Ruby 1.9.2-p180下`$ Kernel.load`一个带有$ SAFE = 1的类定义的文件?

时间:2011-06-09 00:21:02

标签: ruby

我试图在安全级别1运行时使用Kernel.load的双参数形式来在匿名命名空间中加载类定义。例如,我正在尝试Kernel.load的文件如下:

# module.rb
class Foo < Superclass
    def bar
        puts "Bar!"
    end
end

测试案例如下:

# loader.rb

BASEDIR = File.expand_path( File.dirname(__FILE__) )
MODULE_FILE = File.join( BASEDIR, 'module.rb' ).untaint

$stderr.puts "Module file name (%p) is %s" %
    [ MODULE_FILE, MODULE_FILE.tainted? ? "tainted" : "not tainted" ]

class Superclass
    @subclasses = []
    class << self; attr_reader :subclasses; end
    def self::inherited( subclass )
        super
        @subclasses << subclass
    end
end

$stderr.puts "Ruby version: #{RUBY_DESCRIPTION}"

$stderr.puts "In $SAFE = 0:"
Kernel.load( MODULE_FILE, true )
result = Superclass.subclasses.last
p result
$stderr.puts "Instantiating and calling its #bar method:"
result.new.bar

$stderr.puts "In $SAFE = 1:"
$SAFE = 1
Kernel.load( MODULE_FILE, true )
result = Superclass.subclasses.last
p result
$stderr.puts "Instantiating and calling its #bar method:"
result.new.bar

当我在Ruby 1.8.7下运行它时,输出如下:

Module file name ("/Users/mgranger/source/ruby/misc/safeload/module.rb") is not tainted
Ruby version: ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]
In $SAFE = 0:
#<Module:0x1001688d8>::Foo
Instantiating and calling its #bar method:
Bar!
In $SAFE = 1:
#<Module:0x100168090>::Foo
Instantiating and calling its #bar method:
Bar!

但在1.9.2下,我得到一个SecurityError:

Module file name ("/Users/mgranger/source/ruby/misc/safeload/module.rb") is not tainted
Ruby version: ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-darwin10.7.0]
In $SAFE = 0:
#<Module:0x0000010086b5b8>::Foo
Instantiating and calling its #bar method:
Bar!
In $SAFE = 1:
loader.rb:29:in `load': Insecure operation - load (SecurityError)
    from loader.rb:29:in `<main>'

最新的Pickaxe和ruby-doc.org上的文档Kernel.load执行以下操作:

load(filename, wrap=false) → true
     

在文件filename中加载并执行Ruby程序。如果文件名未解析为绝对路径,则在$:中列出的库目录中搜索该文件。如果可选的wrap参数为true,则加载的脚本将在匿名模块下执行,从而保护调用程序的全局名称空间。在任何情况下,加载文件中的任何局部变量都不会传播到加载环境。

如果我用puts或者其他东西替换类定义,它会很好地加载,所以这似乎是问题所在。我不确定1.9.2中的变化以及我需要采取哪些不同的方法才能达到同样的效果。有什么想法吗?

0 个答案:

没有答案