我试图在安全级别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中的变化以及我需要采取哪些不同的方法才能达到同样的效果。有什么想法吗?