Я написал обходной путь, который использует интерфейс YAML.parse_stream
:
Редактировать : теперь как gem yaml-safe_load_stream .Кроме того, сопровождающие Psych (YAML
в ruby stdlib) изучают добавление этой функции в библиотеку.
require 'yaml'
module YAML
def safe_load_stream(yaml, filename = nil, &block)
parse_stream(yaml, filename) do |stream|
raise_if_tags(stream, filename)
if block_given?
yield stream.to_ruby
else
stream.to_ruby
end
end
end
module_function :safe_load_stream
def raise_if_tags(obj, filename = nil, doc_num = 1)
doc_num += 1 if obj.is_a?(Psych::Nodes::Document)
if obj.respond_to?(:tag)
if tag = obj.tag
message = "tag #{tag} encountered on line #{obj.start_line} column #{obj.start_column} of document #{doc_num}"
message << " in file #{filename}" if filename
raise Psych::DisallowedClass, message
end
end
if obj.respond_to?(:children)
Array(obj.children).each do |child|
raise_if_tags(child, filename, doc_num)
end
end
end
module_function :raise_if_tags
private_class_method :raise_if_tags
end
С этим вы можете сделать:
YAML.safe_load_stream(content, 'file.txt')
И получите исключение:
Psych::DisallowedClass (Tried to load unspecified class: tag !ruby/struct
encountered on line 1 column 7 of document 2 in file file.txt)
Номера строк, возвращаемые с .start_line
, относятся к началу документа, я не нашел способа получить номер строки, с которой начинается документпоэтому я добавил номер документа к сообщению об ошибке.
В нем нет белого списка классов и символов, а также переключение якорей / псевдонимов, таких как YAML.safe_load
.
. Также есть способыиспользуйте теги, которые, вероятно, дадут ложный положительный результат при таком упрощенном обнаружении unless tag.nil?
.