Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.0: Fix yaml safe_load #1414

Merged
merged 4 commits into from
Apr 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/models/alchemy/cell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def translated_label_for(cell_name)
private

def read_yml_file
::YAML.safe_load(ERB.new(File.read(yml_file_path)).result, [], [], true) || []
::YAML.safe_load(ERB.new(File.read(yml_file_path)).result, YAML_WHITELIST_CLASSES, [], true) || []
end

def yml_file_path
Expand Down
2 changes: 1 addition & 1 deletion app/models/alchemy/element/definitions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def definition_by_name(name)
#
def read_definitions_file
if ::File.exist?(definitions_file_path)
::YAML.safe_load(ERB.new(File.read(definitions_file_path)).result, [Date, Regexp, Symbol], [], true) || []
::YAML.safe_load(ERB.new(File.read(definitions_file_path)).result, YAML_WHITELIST_CLASSES, [], true) || []
else
raise LoadError, "Could not find elements.yml file! Please run `rails generate alchemy:scaffold`"
end
Expand Down
3 changes: 2 additions & 1 deletion lib/alchemy/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ def env_specific_config
# If it does not exist, or its empty, it returns an empty Hash.
#
def read_file(file)
return YAML.load_file(file) || {} if File.exist?(file) # YAML.load_file returns false if file is empty.
YAML.safe_load(ERB.new(File.read(file)).result, YAML_WHITELIST_CLASSES, [], true) || {}
rescue Errno::ENOENT
{}
end

Expand Down
2 changes: 1 addition & 1 deletion lib/alchemy/page_layout.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def available_on_site?(layout)
#
def read_definitions_file
if File.exist?(layouts_file_path)
YAML.safe_load(ERB.new(File.read(layouts_file_path)).result, [Date, Symbol], [], true) || []
YAML.safe_load(ERB.new(File.read(layouts_file_path)).result, YAML_WHITELIST_CLASSES, [], true) || []
else
raise LoadError, "Could not find page_layouts.yml file! Please run `rails generate alchemy:scaffold`"
end
Expand Down
1 change: 1 addition & 0 deletions lib/alchemy_cms.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Instantiate the global Alchemy namespace
module Alchemy
Alchemy::YAML_WHITELIST_CLASSES = %w(Symbol Date Regexp)
end

# Require globally used external libraries
Expand Down
4 changes: 2 additions & 2 deletions lib/rails/generators/alchemy/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ def template_engine
end

def load_alchemy_yaml(name)
YAML.safe_load(ERB.new(File.read("#{Rails.root}/config/alchemy/#{name}")).result, [Regexp], [], true)
YAML.safe_load(ERB.new(File.read("#{Rails.root}/config/alchemy/#{name}")).result, YAML_WHITELIST_CLASSES, [], true)
rescue Errno::ENOENT
puts "\nERROR: Could not read config/alchemy/#{name} file. Please run: rails generate alchemy:scaffold"
puts "\nERROR: Could not read config/alchemy/#{name} file. Please run: `rails generate alchemy:install`"
end
end
end
Expand Down
13 changes: 3 additions & 10 deletions spec/libraries/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,10 @@ module Alchemy

describe '.read_file' do
context 'when given path to yml file exists' do
before { allow(File).to receive(:exist?).and_return(true) }

it 'should call YAML.load_file with the given config path' do
expect(YAML).to receive(:load_file).once.with('path/to/config.yml').and_return({})
Config.send(:read_file, 'path/to/config.yml')
end

context 'but its empty' do
context 'and file is empty' do
before do
allow(File).to receive(:exist?).with('empty_file.yml').and_return(true)
allow(YAML).to receive(:load_file).and_return(false) # YAML.load_file returns false if file is empty.
# YAML.safe_load returns nil if file is empty.
allow(YAML).to receive(:safe_load) { nil }
end

it "should return an empty Hash" do
Expand Down
27 changes: 27 additions & 0 deletions spec/models/alchemy/element_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,33 @@ module Alchemy

context "with a YAML file including a symbol" do
let(:yaml) { '- name: :symbol' }

before do
expect(File).to receive(:exist?).and_return(true)
expect(File).to receive(:read).and_return(yaml)
end

it "returns the definition without error" do
expect { Element.definitions }.to_not raise_error
end
end

context "with a YAML file including a Date" do
let(:yaml) { '- default: 2017-12-24' }

before do
expect(File).to receive(:exist?).and_return(true)
expect(File).to receive(:read).and_return(yaml)
end

it "returns the definition without error" do
expect { Element.definitions }.to_not raise_error
end
end

context "with a YAML file including a Regex" do
let(:yaml) { "- format: !ruby/regexp '/\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/'" }

before do
expect(File).to receive(:exist?).and_return(true)
expect(File).to receive(:read).and_return(yaml)
Expand Down