#ruby
#ruby
Вопрос:
Я пытаюсь использовать форму с двумя аргументами Kernel.load
во время работы на безопасном уровне 1, чтобы загрузить определение класса внутри анонимного пространства имен. Например, файл, который я пытаюсь 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
Загружает и выполняет программу Ruby в имени файла. Если имя файла не преобразуется в абсолютный путь, файл ищется в каталогах библиотеки, перечисленных в $:. Если необязательный параметр wrap имеет значение true, загруженный скрипт будет выполнен в анонимном модуле, защищающем глобальное пространство имен вызывающей программы. Ни при каких обстоятельствах какие-либо локальные переменные в загруженном файле не будут распространяться в среду загрузки.
Если я заменю определение класса на puts
или что-то еще, оно загрузится нормально, так что, похоже, в этом проблема. Я не уверен, что изменилось в 1.9.2 и что мне нужно сделать по-другому, чтобы добиться того же эффекта. Есть идеи?