Skip to content

Commit

Permalink
Merge pull request #19701 from jrafanie/do_not_autoload_models_in_saf…
Browse files Browse the repository at this point in the history
…e_load

Autoload Rails Models unless called from safe_load
  • Loading branch information
Fryguy authored Jan 9, 2020
2 parents a45b411 + 11a69b5 commit b91909c
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 7 deletions.
8 changes: 6 additions & 2 deletions config/initializers/yaml_autoloader.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Autoload Rails Models
# Autoload Rails Models unless called from safe_load
# see https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/psych_ext.rb

# Psych::ClassLoader::Restricted is the class_loader if you use safe_load and was
# added in psych 2.0.0:
# https://github.com/ruby/psych/commit/2c644e184192975b261a81f486a04defa3172b3f
# Note, ruby 2.4.0 shipped with psych 2.2.2+. This class_loader would not work with ruby 2.3 and older.
Psych::Visitors::ToRuby.prepend Module.new {
def resolve_class(klass_name)
klass_name && klass_name.safe_constantize || super
(class_loader.class != Psych::ClassLoader::Restricted && klass_name && klass_name.safe_constantize) || super
end
}
18 changes: 15 additions & 3 deletions spec/initializers/yaml_autoloader_spec.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
require 'fileutils'
require 'pathname'

describe Psych::Visitors::ToRuby do
let(:missing_model) { Rails.root.join("app/models/zzz_model.rb") }
let(:model_directory) { Pathname.new(Dir.mktmpdir("yaml_autoloader")) }
let(:missing_model) { model_directory.join("zzz_model.rb") }

before do
File.write(missing_model, "class ZzzModel\nend\n")
ActiveSupport::Dependencies.autoload_paths << model_directory
end

after do
require 'fileutils'
FileUtils.rm_f(missing_model)
ActiveSupport::Dependencies.autoload_paths.reject! { |p| p == model_directory }
Object.send(:remove_const, "ZzzModel") if Object.const_defined?("ZzzModel")
end

it "YAML.load autoloads missing constants" do
dump = "--- !ruby/object:ZzzModel {}\n"
expect(YAML.load(dump).class.name).to eql "ZzzModel"
end

it "missing constants during yaml load are autoloaded" do
it "YAML.safe_load does not autoload missing constants" do
dump = "--- !ruby/object:ZzzModel {}\n"
expect(YAML.load(dump).class.name).to eql "ZzzModel"
expect { YAML.safe_load(dump) }.to raise_error(Psych::DisallowedClass)
end
end
4 changes: 2 additions & 2 deletions spec/lib/rbac/filterer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2240,7 +2240,7 @@ def get_rbac_results_for_and_expect_objects(klass, expected_objects)
service2.update(:service_template => nil)

# exclude service2 (no service template)
exp = YAML.safe_load("--- !ruby/object:MiqExpression
exp = YAML.load("--- !ruby/object:MiqExpression
exp:
and:
- IS NOT EMPTY:
Expand Down Expand Up @@ -2269,7 +2269,7 @@ def get_rbac_results_for_and_expect_objects(klass, expected_objects)
FactoryBot.create_list(:service, 1, :parent => root_service) # matches ruby and sql filter, not rbac

# expression with sql AND ruby
exp = YAML.safe_load("--- !ruby/object:MiqExpression
exp = YAML.load("--- !ruby/object:MiqExpression
exp:
and:
- IS NOT EMPTY:
Expand Down

0 comments on commit b91909c

Please sign in to comment.