From 88a8d4793473259b392241f1e2d20d39bd96b214 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 20 Jan 2022 18:34:19 +0000 Subject: use YAML.unsafe_load in Psych 4.x (Ruby 3.1+) Psych 4.x defaults to "nanny mode" to handle untrusted data. This causes breakage with since YAML references (aliases) emitted by dtas-player can't be handled by Psych clients under Ruby 3.1. Since dtas is single user and is a shell designed to run arbitrary code, favor the new YAML.unsafe_load API which behaves like the old YAML.load in Ruby <= 3.0. --- bin/dtas-console | 4 ++-- bin/dtas-msinkctl | 4 ++-- bin/dtas-readahead | 8 ++++---- bin/dtas-sinkedit | 4 ++-- bin/dtas-sourceedit | 4 ++-- bin/dtas-splitfx | 6 +++--- bin/dtas-tl | 4 ++-- lib/dtas.rb | 6 ++++++ lib/dtas/source/splitfx.rb | 4 ++-- lib/dtas/state_file.rb | 4 ++-- test/test_encoding.rb | 4 ++-- test/test_format_change.rb | 4 ++-- test/test_player_client_handler.rb | 4 ++-- test/test_player_integration.rb | 12 ++++++------ test/test_rg_integration.rb | 18 +++++++++--------- test/test_sink.rb | 4 ++-- test/test_splitfx.rb | 2 +- test/test_tfx.rb | 4 ++-- 18 files changed, 53 insertions(+), 47 deletions(-) diff --git a/bin/dtas-console b/bin/dtas-console index e02dda4..a519ba9 100755 --- a/bin/dtas-console +++ b/bin/dtas-console @@ -27,7 +27,7 @@ trap(:WINCH) { se.signal } w = DTAS::UNIXClient.new w.req_ok('watch') c = DTAS::UNIXClient.new -cur = YAML.load(c.req('current')) +cur = DTAS.yaml_load(c.req('current')) readable = [ se, w, $stdin ] set_title = (ENV['DISPLAY'] || ENV['WAYLAND_DISPLAY']) ? $stdout : nil @@ -254,7 +254,7 @@ begin events << "#{Time.now.strftime(tfmt)} #{event}" # something happened, refresh current # we could be more intelligent here, maybe, but too much work. - cur = YAML.load(c.req('current')) + cur = DTAS.yaml_load(c.req('current')) when $stdin # keybindings taken from mplayer / vi case key = Curses.getch diff --git a/bin/dtas-msinkctl b/bin/dtas-msinkctl index 189738f..6fb3863 100755 --- a/bin/dtas-msinkctl +++ b/bin/dtas-msinkctl @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require 'yaml' @@ -29,7 +29,7 @@ def filter(c, player_sinks, key) rv = [] player_sinks.each do |name| buf = c.req("sink cat #{name}") - sink = YAML.load(buf) + sink = DTAS.yaml_load(buf) rv << sink["name"] if sink[key] end rv diff --git a/bin/dtas-readahead b/bin/dtas-readahead index a1971bd..3f46b95 100755 --- a/bin/dtas-readahead +++ b/bin/dtas-readahead @@ -140,7 +140,7 @@ def do_open(path) when "---\n" buf << fp.read(fp.size - 4) Dir.chdir(File.dirname(path)) do - yml = YAML.load(buf) + yml = DTAS.yaml_load(buf) x = yml['infile'] and return File.open(File.expand_path(x).freeze) end end @@ -155,7 +155,7 @@ begin @todo_ra = @max_ra t0 = DTAS.now fp = nil - cur = YAML.load(c.req('current')) + cur = DTAS.yaml_load(c.req('current')) while @todo_ra > 0 && fp.nil? if current = cur['current'] track = current['infile'] @@ -177,7 +177,7 @@ begin end # queue has priority, work on it, first - queue = YAML.load(c.req('queue cat')) + queue = DTAS.yaml_load(c.req('queue cat')) while @todo_ra > 0 && track = queue.shift next unless track.kind_of?(String) fp = nil @@ -209,7 +209,7 @@ begin end end idx or break - cur = YAML.load(c.req('current')) + cur = DTAS.yaml_load(c.req('current')) current = cur['current'] or break end if current diff --git a/bin/dtas-sinkedit b/bin/dtas-sinkedit index 8f96a97..252270f 100755 --- a/bin/dtas-sinkedit +++ b/bin/dtas-sinkedit @@ -36,10 +36,10 @@ st_in = $stdin.stat buf = c.req(%W(sink cat #{name})) abort(buf) if buf =~ /\AERR/ -orig = YAML.load(buf) +orig = DTAS.yaml_load(buf) commit_update = lambda do |buf| - sink = YAML.load(buf) + sink = DTAS.yaml_load(buf) cmd = %W(sink ed #{name}) update_cmd_env(cmd, orig, sink) diff --git a/bin/dtas-sourceedit b/bin/dtas-sourceedit index e6603bf..1b3f4ee 100755 --- a/bin/dtas-sourceedit +++ b/bin/dtas-sourceedit @@ -36,10 +36,10 @@ st_in = $stdin.stat buf = c.req(%W(source cat #{name})) abort(buf) if buf =~ /\AERR/ -orig = YAML.load(buf) +orig = DTAS.yaml_load(buf) commit_update = lambda do |buf| - source = YAML.load(buf) + source = DTAS.yaml_load(buf) cmd = %W(source ed #{name}) update_cmd_env(cmd, orig, source) diff --git a/bin/dtas-splitfx b/bin/dtas-splitfx index 18ea0b4..05e71e5 100755 --- a/bin/dtas-splitfx +++ b/bin/dtas-splitfx @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require 'yaml' @@ -48,7 +48,7 @@ ARGV.each do |arg| when %r{\A(\w+)=(.*)\z} key, val = $1, $2 # only one that makes sense is infile=another_file - overrides[key] = YAML.load(val) + overrides[key] = DTAS.yaml_load(val) when %r{\A(\w+)\.(\w+)=(.*)\z} # comments.ARTIST='blah' top, key, val = $1, $2, $3 @@ -63,5 +63,5 @@ trap(:INT) { exit 130 } file = args.shift or abort usage target = args.shift || default_target splitfx = DTAS::SplitFX.new -splitfx.import(YAML.load(File.read(file)), overrides) +splitfx.import(DTAS.yaml_load(File.read(file)), overrides) splitfx.run(target, opts) diff --git a/bin/dtas-tl b/bin/dtas-tl index 988e726..c1af933 100755 --- a/bin/dtas-tl +++ b/bin/dtas-tl @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true # encoding: binary @@ -51,7 +51,7 @@ def do_edit(c) # jump to the line of the currently playing track if using vi or vim # Patches for other editors welcome: dtas-all@nongnu.org if ed =~ /vim?\z/ - cur = YAML.load(c.req('current')) + cur = DTAS.yaml_load(c.req('current')) if tl = cur['tracklist'] if pos = tl['pos'] ed += " +#{pos + 1}" diff --git a/lib/dtas.rb b/lib/dtas.rb index 477a176..cb7c33d 100644 --- a/lib/dtas.rb +++ b/lib/dtas.rb @@ -25,6 +25,12 @@ module DTAS Fiddle.dlopen(nil) end end + + # prevent breakage in Psych 4.x; we're a shell and designed to execute code + def self.yaml_load(buf) + require 'yaml' + YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(buf) : YAML.load(buf) + end # :startdoc: end diff --git a/lib/dtas/source/splitfx.rb b/lib/dtas/source/splitfx.rb index 11e4190..afeb6a3 100644 --- a/lib/dtas/source/splitfx.rb +++ b/lib/dtas/source/splitfx.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2014-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require 'yaml' @@ -36,7 +36,7 @@ class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc: sfx = DTAS::SplitFX.new Dir.chdir(File.dirname(ymlfile)) do # ugh - @ymlhash = YAML.load(buf) + @ymlhash = DTAS.yaml_load(buf) @ymlhash['tracks'] ||= [ "t 0 default" ] sfx.import(@ymlhash) sfx.infile.replace(File.expand_path(sfx.infile)) diff --git a/lib/dtas/state_file.rb b/lib/dtas/state_file.rb index eac3e2f..f16a866 100644 --- a/lib/dtas/state_file.rb +++ b/lib/dtas/state_file.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require 'yaml' @@ -14,7 +14,7 @@ class DTAS::StateFile # :nodoc: end def tryload - YAML.load(IO.binread(@path)) if File.readable?(@path) + DTAS.yaml_load(IO.binread(@path)) if File.readable?(@path) end def dump(obj, force_fsync = false) diff --git a/test/test_encoding.rb b/test/test_encoding.rb index 9ef6a25..666d185 100644 --- a/test/test_encoding.rb +++ b/test/test_encoding.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require './test/helper' @@ -13,7 +13,7 @@ comments: ARTIST: !binary |- RW5yaXF1ZSBSb2Ryw61ndWV6 EOD - hash = YAML.load(data) + hash = DTAS.yaml_load(data) artist = DTAS.try_enc(hash['comments']['ARTIST'], Encoding::UTF_8) assert_equal 'Enrique Rodríguez', artist end diff --git a/test/test_format_change.rb b/test/test_format_change.rb index 95bb860..dc94f02 100644 --- a/test/test_format_change.rb +++ b/test/test_format_change.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require './test/player_integration' @@ -26,7 +26,7 @@ class TestFormatChange < Testcase Timeout.timeout(len) do begin - cur = YAML.load(s.req("current")) + cur = DTAS.yaml_load(s.req("current")) end while cur["sinks"] && sleep(0.01) end diff --git a/test/test_player_client_handler.rb b/test/test_player_client_handler.rb index 7ea8cc0..eee5e49 100644 --- a/test/test_player_client_handler.rb +++ b/test/test_player_client_handler.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require './test/helper' @@ -71,7 +71,7 @@ class TestPlayerClientHandler < Testcase @sinks["default"] = sink dpc_sink(@io, %W(cat default)) assert_equal 1, @io.size - hsh = YAML.load(@io[0]) + hsh = DTAS.yaml_load(@io[0]) assert_kind_of Hash, hsh assert_equal "default", hsh["name"] assert_match("dither -s", hsh["command"]) diff --git a/test/test_player_integration.rb b/test/test_player_integration.rb index e933f7b..5059bd2 100644 --- a/test/test_player_integration.rb +++ b/test/test_player_integration.rb @@ -139,7 +139,7 @@ class TestPlayerIntegration < Testcase Timeout.timeout(5) do begin yaml = s.req("current") - cur = YAML.load(yaml) + cur = DTAS.yaml_load(yaml) end while cur["sinks"] && sleep(0.01) end @@ -166,7 +166,7 @@ class TestPlayerIntegration < Testcase Timeout.timeout(len) do begin yaml = s.req("current") - cur = YAML.load(yaml) + cur = DTAS.yaml_load(yaml) end while cur["sinks"] && sleep(0.01) end assert(system("cmp", dump.path, expect.path), @@ -195,13 +195,13 @@ class TestPlayerIntegration < Testcase state.close! s = client_socket s.req_ok(%W(state dump #{state_path})) - hash = YAML.load(IO.binread(state_path)) + hash = DTAS.yaml_load(IO.binread(state_path)) assert_equal @sock_path, hash["socket"] assert_equal "default", hash["sinks"][0]["name"] assert_equal "", IO.binread(@state_tmp.path) s.req_ok(%W(state dump)) - orig = YAML.load(IO.binread(@state_tmp.path)) + orig = DTAS.yaml_load(IO.binread(@state_tmp.path)) assert_equal orig, hash ensure File.unlink(state_path) @@ -216,11 +216,11 @@ class TestPlayerIntegration < Testcase assert_equal "sox av ff splitfx", s.req("source ls") s.req_ok("source ed sox command=true") - sox = YAML.load(s.req("source cat sox")) + sox = DTAS.yaml_load(s.req("source cat sox")) assert_equal "true", sox["command"] s.req_ok("source ed sox command=") - sox = YAML.load(s.req("source cat sox")) + sox = DTAS.yaml_load(s.req("source cat sox")) assert_equal DTAS::Source::Sox::SOX_DEFAULTS["command"], sox["command"] end diff --git a/test/test_rg_integration.rb b/test/test_rg_integration.rb index efa0721..f274272 100644 --- a/test/test_rg_integration.rb +++ b/test/test_rg_integration.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require './test/player_integration' @@ -39,7 +39,7 @@ class TestRgIntegration < Testcase yaml = cur = nil Timeout.timeout(5) do begin - cur = YAML.load(yaml = s.req("current")) + cur = DTAS.yaml_load(yaml = s.req("current")) end while cur["current_offset"] == 0 && sleep(0.01) end @@ -55,7 +55,7 @@ class TestRgIntegration < Testcase Timeout.timeout(5) do begin yaml = s.req("current") - cur = YAML.load(yaml) + cur = DTAS.yaml_load(yaml) end while cur["current"]["env"]["RGFX"] !~ expect && sleep(0.01) end assert_match expect, cur["current"]["env"]["RGFX"] @@ -67,27 +67,27 @@ class TestRgIntegration < Testcase check_gain.call(%r{gain 2\.5}, "track_peak") s.req_ok("rg preamp+=1") - rg = YAML.load(yaml = s.req("rg")) + rg = DTAS.yaml_load(yaml = s.req("rg")) assert_equal 1, rg["preamp"] s.req_ok("rg preamp-=1") - rg = YAML.load(yaml = s.req("rg")) + rg = DTAS.yaml_load(yaml = s.req("rg")) assert_nil rg["preamp"] s.req_ok("rg preamp=2") - rg = YAML.load(yaml = s.req("rg")) + rg = DTAS.yaml_load(yaml = s.req("rg")) assert_equal 2, rg["preamp"] s.req_ok("rg preamp-=0.3") - rg = YAML.load(yaml = s.req("rg")) + rg = DTAS.yaml_load(yaml = s.req("rg")) assert_equal 1.7, rg["preamp"] s.req_ok("rg preamp-=-0.3") - rg = YAML.load(yaml = s.req("rg")) + rg = DTAS.yaml_load(yaml = s.req("rg")) assert_equal 2.0, rg["preamp"] s.req_ok("rg preamp-=+0.3") - rg = YAML.load(yaml = s.req("rg")) + rg = DTAS.yaml_load(yaml = s.req("rg")) assert_equal 1.7, rg["preamp"] dethrottle_decoder(s) diff --git a/test/test_sink.rb b/test/test_sink.rb index 873fb3a..7214da6 100644 --- a/test/test_sink.rb +++ b/test/test_sink.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require './test/helper' @@ -27,6 +27,6 @@ class TestSink < Testcase def test_inactive_load orig = { "active" => false }.freeze tmp = orig.to_yaml - assert_equal orig, YAML.load(tmp) + assert_equal orig, DTAS.yaml_load(tmp) end end diff --git a/test/test_splitfx.rb b/test/test_splitfx.rb index cacda66..e3bd19d 100644 --- a/test/test_splitfx.rb +++ b/test/test_splitfx.rb @@ -39,7 +39,7 @@ class TestSplitfx < Testcase end def test_example - hash = YAML.load(File.read("examples/splitfx.sample.yml")) + hash = DTAS.yaml_load(File.read("examples/splitfx.sample.yml")) sfx = DTAS::SplitFX.new Dir.mktmpdir do |dir| Dir.chdir(dir) do diff --git a/test/test_tfx.rb b/test/test_tfx.rb index fa77ca5..51b1900 100644 --- a/test/test_tfx.rb +++ b/test/test_tfx.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2020 all contributors +# Copyright (C) all contributors # License: GPL-3.0+ # frozen_string_literal: true require './test/helper' @@ -12,7 +12,7 @@ class TestTFX < Testcase end def test_example - ex = YAML.load(File.read("examples/tfx.sample.yml")) + ex = DTAS.yaml_load(File.read("examples/tfx.sample.yml")) effects = [] ex["effects"].each do |line| words = Shellwords.split(line) -- cgit v1.2.3-24-ge0c7