Skip to content

Commit 218e1c0

Browse files
authored
Fix YAML parsing when using psych >= 4 (#306)
* Fix YAML.load to YAML.unsafe_load if possible * Add YAML.unsafe_load tests with rails 6.1
1 parent 7c48154 commit 218e1c0

35 files changed

Lines changed: 676 additions & 1 deletion

Appraisals

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,21 @@ else
4949
puts 'Skipping rails-6.0 for Ruby < 2.5'
5050
end
5151

52+
# Test rails 6.1 with psych >= 4
53+
# Rails 6.x requires Ruby >= 2.5.0
54+
if (RUBY_ENGINE == 'ruby' && RUBY_VERSION >= '2.5.0') || RUBY_ENGINE != 'ruby'
55+
appraise 'rails-6.1' do
56+
gem 'activerecord-jdbcsqlite3-adapter', '~> 61.1', platform: :jruby
57+
gem 'bootsnap', '>= 1.4.4'
58+
gem 'rails', '6.1.4'
59+
gem 'rspec-rails', '~> 5.0'
60+
gem 'sqlite3', '~> 1.4', platform: :ruby
61+
gem 'psych', '>= 4'
62+
end
63+
else
64+
puts 'Skipping rails-6.1 for Ruby < 2.5'
65+
end
66+
5267
appraise 'sinatra' do
5368
gem 'sinatra', '2.0.8.1'
5469
end

gemfiles/rails_6.1.gemfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This file was generated by Appraisal
2+
3+
source "https://rubygems.org"
4+
5+
gem "activerecord-jdbcsqlite3-adapter", "~> 61.1", platform: :jruby
6+
gem "bootsnap", ">= 1.4.4"
7+
gem "rails", "6.1.4"
8+
gem "rspec-rails", "~> 5.0"
9+
gem "sqlite3", "~> 1.4", platform: :ruby
10+
gem "psych", ">= 4"
11+
12+
gemspec path: "../"

lib/config/sources/yaml_source.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def load
1717
if @path and File.exist?(@path)
1818
file_contents = IO.read(@path)
1919
file_contents = ERB.new(file_contents).result if evaluate_erb
20-
result = YAML.load(file_contents)
20+
result = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(file_contents) : YAML.load(file_contents)
2121
end
2222

2323
result || {}

spec/app/rails_6.1/Gemfile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
source 'https://rubygems.org'
2+
3+
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'
4+
gem 'rails', '~> 6.1.4'
5+
# Use sqlite3 as the database for Active Record
6+
gem 'sqlite3', '~> 1.4'
7+
8+
# Reduces boot times through caching; required in config/boot.rb
9+
gem 'bootsnap', '>= 1.4.4', require: false
10+
11+
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
12+
# gem 'rack-cors'
13+
14+
group :development, :test do
15+
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
16+
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
17+
end
18+
19+
group :development do
20+
end
21+
22+
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
23+
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

spec/app/rails_6.1/Rakefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Add your own tasks in files placed in lib/tasks ending in .rake,
2+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3+
4+
require_relative "config/application"
5+
6+
Rails.application.load_tasks
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class ApplicationController < ActionController::API
2+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class ApplicationJob < ActiveJob::Base
2+
# Automatically retry jobs that encountered a deadlock
3+
# retry_on ActiveRecord::Deadlocked
4+
5+
# Most jobs are safe to ignore if the underlying records are no longer available
6+
# discard_on ActiveJob::DeserializationError
7+
end
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class ApplicationRecord < ActiveRecord::Base
2+
self.abstract_class = true
3+
end

spec/app/rails_6.1/bin/bundle

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
#
5+
# This file was generated by Bundler.
6+
#
7+
# The application 'bundle' is installed as part of a gem, and
8+
# this file is here to facilitate running it.
9+
#
10+
11+
require "rubygems"
12+
13+
m = Module.new do
14+
module_function
15+
16+
def invoked_as_script?
17+
File.expand_path($0) == File.expand_path(__FILE__)
18+
end
19+
20+
def env_var_version
21+
ENV["BUNDLER_VERSION"]
22+
end
23+
24+
def cli_arg_version
25+
return unless invoked_as_script? # don't want to hijack other binstubs
26+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27+
bundler_version = nil
28+
update_index = nil
29+
ARGV.each_with_index do |a, i|
30+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31+
bundler_version = a
32+
end
33+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34+
bundler_version = $1 || ">= 0.a"
35+
update_index = i
36+
end
37+
bundler_version
38+
end
39+
40+
def gemfile
41+
gemfile = ENV["BUNDLE_GEMFILE"]
42+
return gemfile if gemfile && !gemfile.empty?
43+
44+
File.expand_path("../../Gemfile", __FILE__)
45+
end
46+
47+
def lockfile
48+
lockfile =
49+
case File.basename(gemfile)
50+
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51+
else "#{gemfile}.lock"
52+
end
53+
File.expand_path(lockfile)
54+
end
55+
56+
def lockfile_version
57+
return unless File.file?(lockfile)
58+
lockfile_contents = File.read(lockfile)
59+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60+
Regexp.last_match(1)
61+
end
62+
63+
def bundler_version
64+
@bundler_version ||= begin
65+
env_var_version || cli_arg_version ||
66+
lockfile_version || "#{Gem::Requirement.default}.a"
67+
end
68+
end
69+
70+
def load_bundler!
71+
ENV["BUNDLE_GEMFILE"] ||= gemfile
72+
73+
# must dup string for RG < 1.8 compatibility
74+
activate_bundler(bundler_version.dup)
75+
end
76+
77+
def activate_bundler(bundler_version)
78+
if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
79+
bundler_version = "< 2"
80+
end
81+
gem_error = activation_error_handling do
82+
gem "bundler", bundler_version
83+
end
84+
return if gem_error.nil?
85+
require_error = activation_error_handling do
86+
require "bundler/version"
87+
end
88+
return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
89+
warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
90+
exit 42
91+
end
92+
93+
def activation_error_handling
94+
yield
95+
nil
96+
rescue StandardError, LoadError => e
97+
e
98+
end
99+
end
100+
101+
m.load_bundler!
102+
103+
if m.invoked_as_script?
104+
load Gem.bin_path("bundler", "bundle")
105+
end

spec/app/rails_6.1/bin/rails

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env ruby
2+
load File.expand_path("spring", __dir__)
3+
APP_PATH = File.expand_path('../config/application', __dir__)
4+
require_relative "../config/boot"
5+
require "rails/commands"

0 commit comments

Comments
 (0)