From f51b6f9e603d1fe1aa3719cac2705cb7fcbefcde Mon Sep 17 00:00:00 2001 From: TAGOMORI Satoshi Date: Thu, 3 Mar 2016 17:25:55 -0800 Subject: [PATCH] fix to dup default values to make it safe if plugins modify provided values --- lib/fluent/config/section.rb | 2 +- test/config/test_configurable.rb | 37 ++++++++++++++++++++++++++++++++ test/config/test_types.rb | 6 ++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/fluent/config/section.rb b/lib/fluent/config/section.rb index 0a0933201c..5455c5f09a 100644 --- a/lib/fluent/config/section.rb +++ b/lib/fluent/config/section.rb @@ -88,7 +88,7 @@ def self.generate(proxy, conf, logger, plugin_class, stack = []) proxy.defaults.each_pair do |name, defval| varname = name.to_sym - section_params[varname] = defval + section_params[varname] = (defval.dup rescue defval) end if proxy.argument diff --git a/test/config/test_configurable.rb b/test/config/test_configurable.rb index d09c40c5a6..226fbd6f04 100644 --- a/test/config/test_configurable.rb +++ b/test/config/test_configurable.rb @@ -158,6 +158,12 @@ class Example5 config_param :secret_param2, :string, secret: true end end + + class Example6 + include Fluent::Configurable + config_param :obj1, :hash, default: {} + config_param :obj2, :array, default: [] + end end module Fluent::Config @@ -251,6 +257,37 @@ def e(attrs) assert_raise(Fluent::ConfigError) { b2.configure(default.merge({"opt2" => "fooooooo"})) } assert_raise(Fluent::ConfigError) { b2.configure(default.merge({"opt3" => "c"})) } end + + sub_test_case 'default values should be duplicated before touched in plugin code' do + test 'default object should be dupped for cases configured twice' do + x6a = ConfigurableSpec::Example6.new + assert_nothing_raised { x6a.configure(e({})) } + assert_equal({}, x6a.obj1) + assert_equal([], x6a.obj2) + + x6b = ConfigurableSpec::Example6.new + assert_nothing_raised { x6b.configure(e({})) } + assert_equal({}, x6b.obj1) + assert_equal([], x6b.obj2) + + assert { x6a.obj1.object_id != x6b.obj1.object_id } + assert { x6a.obj2.object_id != x6b.obj2.object_id } + + x6c = ConfigurableSpec::Example6.new + assert_nothing_raised { x6c.configure(e({})) } + assert_equal({}, x6c.obj1) + assert_equal([], x6c.obj2) + + x6c.obj1['k'] = 'v' + x6c.obj2 << 'v' + + assert_equal({'k' => 'v'}, x6c.obj1) + assert_equal(['v'], x6c.obj2) + + assert_equal({}, x6a.obj1) + assert_equal([], x6a.obj2) + end + end end end diff --git a/test/config/test_types.rb b/test/config/test_types.rb index 95c544bc63..2821b115a5 100644 --- a/test/config/test_types.rb +++ b/test/config/test_types.rb @@ -128,6 +128,12 @@ class TestConfigTypes < ::Test::Unit::TestCase test 'array' do assert_equal(["1","2",1], Config::ARRAY_TYPE.call('["1","2",1]', {})) + + array_options = { + default: [], + } + assert_equal(["1","2"], Config::ARRAY_TYPE.call('["1","2"]', array_options)) + assert_equal(["3"], Config::ARRAY_TYPE.call('["3"]', array_options)) end end end