Другой вариант, если вы хотите минимизировать уязвимость до #eval
(что рационально), это использовать String#scan
:
quoted = /"(?:\\.|[^\\"])*"/
pairs = '{"city": "London", "country": "England", "region": "Europe"}'.scan(/(#{quoted})\s*:\s*(#{quoted})/)
hash = Hash[ *pairs.flatten.map { |q| eval q } ]
Мы все еще используем #eval
, но мы знаем, что мы только #eval
делаем что-то похожее на строку в кавычках, так что мы в безопасности.
Поскольку строки ruby могут содержать произвольный код (посредством чуда интерполяции), мы все еще уязвимы:
# arbitrary code evaluation
p eval('"one two #{puts %{Give me a three!}; gets.chomp} four"')
Самая безопасная альтернатива - полностью обойти #eval
и использовать библиотеку для удаления строк без кавычек, которая не позволяет
интерполяция. Библиотека JSON (как упоминалось ранее) является отличным примером этого. Это может показаться медленнее (так как это
не так оптимизирован, как #eval
), но гораздо безопаснее.