CVE-2022-4064
This commit is contained in:
parent
74b631d67a
commit
b36737f40e
74
CVE-2022-4064-1.patch
Normal file
74
CVE-2022-4064-1.patch
Normal file
@ -0,0 +1,74 @@
|
||||
diff --git a/lib/dalli/protocol/meta.rb b/lib/dalli/protocol/meta.rb
|
||||
index 4d6c662d..b2e66c37 100644
|
||||
--- a/lib/dalli/protocol/meta.rb
|
||||
+++ b/lib/dalli/protocol/meta.rb
|
||||
@@ -44,6 +44,7 @@ def gat(key, ttl, options = nil)
|
||||
end
|
||||
|
||||
def touch(key, ttl)
|
||||
+ ttl = TtlSanitizer.sanitize(ttl)
|
||||
encoded_key, base64 = KeyRegularizer.encode(key)
|
||||
req = RequestFormatter.meta_get(key: encoded_key, ttl: ttl, value: false, base64: base64)
|
||||
write(req)
|
||||
diff --git a/lib/dalli/protocol/meta/request_formatter.rb b/lib/dalli/protocol/meta/request_formatter.rb
|
||||
index b36a1219..7e485fea 100644
|
||||
--- a/lib/dalli/protocol/meta/request_formatter.rb
|
||||
+++ b/lib/dalli/protocol/meta/request_formatter.rb
|
||||
@@ -31,7 +31,7 @@ def self.meta_set(key:, value:, bitflags: nil, cas: nil, ttl: nil, mode: :set, b
|
||||
cmd << ' c' unless %i[append prepend].include?(mode)
|
||||
cmd << ' b' if base64
|
||||
cmd << " F#{bitflags}" if bitflags
|
||||
- cmd << " C#{cas}" if cas && !cas.zero?
|
||||
+ cmd << cas_string(cas)
|
||||
cmd << " T#{ttl}" if ttl
|
||||
cmd << " M#{mode_to_token(mode)}"
|
||||
cmd << ' q' if quiet
|
||||
@@ -43,7 +43,7 @@ def self.meta_set(key:, value:, bitflags: nil, cas: nil, ttl: nil, mode: :set, b
|
||||
def self.meta_delete(key:, cas: nil, ttl: nil, base64: false, quiet: false)
|
||||
cmd = "md #{key}"
|
||||
cmd << ' b' if base64
|
||||
- cmd << " C#{cas}" if cas && !cas.zero?
|
||||
+ cmd << cas_string(cas)
|
||||
cmd << " T#{ttl}" if ttl
|
||||
cmd << ' q' if quiet
|
||||
cmd + TERMINATOR
|
||||
@@ -54,8 +54,9 @@ def self.meta_arithmetic(key:, delta:, initial:, incr: true, cas: nil, ttl: nil,
|
||||
cmd << ' b' if base64
|
||||
cmd << " D#{delta}" if delta
|
||||
cmd << " J#{initial}" if initial
|
||||
- cmd << " C#{cas}" if cas && !cas.zero?
|
||||
- cmd << " N#{ttl}" if ttl
|
||||
+ # Always set a TTL if an initial value is specified
|
||||
+ cmd << " N#{ttl || 0}" if ttl || initial
|
||||
+ cmd << cas_string(cas)
|
||||
cmd << ' q' if quiet
|
||||
cmd << " M#{incr ? 'I' : 'D'}"
|
||||
cmd + TERMINATOR
|
||||
@@ -75,7 +76,7 @@ def self.version
|
||||
|
||||
def self.flush(delay: nil, quiet: false)
|
||||
cmd = +'flush_all'
|
||||
- cmd << " #{delay}" if delay
|
||||
+ cmd << " #{parse_to_64_bit_int(delay, 0)}" if delay
|
||||
cmd << ' noreply' if quiet
|
||||
cmd + TERMINATOR
|
||||
end
|
||||
@@ -102,6 +103,18 @@ def self.mode_to_token(mode)
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
+
|
||||
+ def self.cas_string(cas)
|
||||
+ cas = parse_to_64_bit_int(cas, nil)
|
||||
+ cas.nil? || cas.zero? ? '' : " C#{cas}"
|
||||
+ end
|
||||
+
|
||||
+ def self.parse_to_64_bit_int(val, default)
|
||||
+ val.nil? ? nil : Integer(val)
|
||||
+ rescue ArgumentError
|
||||
+ # Sanitize to default if it isn't parsable as an integer
|
||||
+ default
|
||||
+ end
|
||||
end
|
||||
end
|
||||
end
|
||||
228
CVE-2022-4064-2.patch
Normal file
228
CVE-2022-4064-2.patch
Normal file
@ -0,0 +1,228 @@
|
||||
diff --git a/test/integration/test_network.rb b/test/integration/test_network.rb
|
||||
index e0ea862c..bf20baae 100644
|
||||
--- a/test/integration/test_network.rb
|
||||
+++ b/test/integration/test_network.rb
|
||||
@@ -7,8 +7,8 @@
|
||||
describe "using the #{p} protocol" do
|
||||
describe 'assuming a bad network' do
|
||||
it 'handle no server available' do
|
||||
+ dc = Dalli::Client.new 'localhost:19333'
|
||||
assert_raises Dalli::RingError, message: 'No server available' do
|
||||
- dc = Dalli::Client.new 'localhost:19333'
|
||||
dc.get 'foo'
|
||||
end
|
||||
end
|
||||
@@ -16,8 +16,8 @@
|
||||
describe 'with a fake server' do
|
||||
it 'handle connection reset' do
|
||||
memcached_mock(->(sock) { sock.close }) do
|
||||
+ dc = Dalli::Client.new('localhost:19123')
|
||||
assert_raises Dalli::RingError, message: 'No server available' do
|
||||
- dc = Dalli::Client.new('localhost:19123')
|
||||
dc.get('abc')
|
||||
end
|
||||
end
|
||||
@@ -26,8 +26,8 @@
|
||||
it 'handle connection reset with unix socket' do
|
||||
socket_path = MemcachedMock::UNIX_SOCKET_PATH
|
||||
memcached_mock(->(sock) { sock.close }, :start_unix, socket_path) do
|
||||
+ dc = Dalli::Client.new(socket_path)
|
||||
assert_raises Dalli::RingError, message: 'No server available' do
|
||||
- dc = Dalli::Client.new(socket_path)
|
||||
dc.get('abc')
|
||||
end
|
||||
end
|
||||
@@ -35,8 +35,8 @@
|
||||
|
||||
it 'handle malformed response' do
|
||||
memcached_mock(->(sock) { sock.write('123') }) do
|
||||
+ dc = Dalli::Client.new('localhost:19123')
|
||||
assert_raises Dalli::RingError, message: 'No server available' do
|
||||
- dc = Dalli::Client.new('localhost:19123')
|
||||
dc.get('abc')
|
||||
end
|
||||
end
|
||||
@@ -47,8 +47,8 @@
|
||||
sleep(0.6)
|
||||
sock.close
|
||||
}, :delayed_start) do
|
||||
+ dc = Dalli::Client.new('localhost:19123')
|
||||
assert_raises Dalli::RingError, message: 'No server available' do
|
||||
- dc = Dalli::Client.new('localhost:19123')
|
||||
dc.get('abc')
|
||||
end
|
||||
end
|
||||
@@ -59,8 +59,8 @@
|
||||
sleep(0.6)
|
||||
sock.write('giraffe')
|
||||
}) do
|
||||
+ dc = Dalli::Client.new('localhost:19123')
|
||||
assert_raises Dalli::RingError, message: 'No server available' do
|
||||
- dc = Dalli::Client.new('localhost:19123')
|
||||
dc.get('abc')
|
||||
end
|
||||
end
|
||||
diff --git a/test/protocol/meta/test_request_formatter.rb b/test/protocol/meta/test_request_formatter.rb
|
||||
index 1eef499b..755e7305 100644
|
||||
--- a/test/protocol/meta/test_request_formatter.rb
|
||||
+++ b/test/protocol/meta/test_request_formatter.rb
|
||||
@@ -77,11 +77,28 @@
|
||||
Dalli::Protocol::Meta::RequestFormatter.meta_set(key: key, value: val, bitflags: bitflags, cas: cas)
|
||||
end
|
||||
|
||||
+ it 'excludes CAS if set to 0' do
|
||||
+ assert_equal "ms #{key} #{val.bytesize} c F#{bitflags} MS\r\n#{val}\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_set(key: key, value: val, bitflags: bitflags, cas: 0)
|
||||
+ end
|
||||
+
|
||||
+ it 'excludes non-numeric CAS values' do
|
||||
+ assert_equal "ms #{key} #{val.bytesize} c F#{bitflags} MS\r\n#{val}\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_set(key: key, value: val, bitflags: bitflags,
|
||||
+ cas: "\nset importantkey 1 1000 8\ninjected")
|
||||
+ end
|
||||
+
|
||||
it 'sets the quiet mode if configured' do
|
||||
assert_equal "ms #{key} #{val.bytesize} c F#{bitflags} MS q\r\n#{val}\r\n",
|
||||
Dalli::Protocol::Meta::RequestFormatter.meta_set(key: key, value: val, bitflags: bitflags,
|
||||
quiet: true)
|
||||
end
|
||||
+
|
||||
+ it 'sets the base64 mode if configured' do
|
||||
+ assert_equal "ms #{key} #{val.bytesize} c b F#{bitflags} MS\r\n#{val}\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_set(key: key, value: val, bitflags: bitflags,
|
||||
+ base64: true)
|
||||
+ end
|
||||
end
|
||||
|
||||
describe 'meta_delete' do
|
||||
@@ -93,7 +110,7 @@
|
||||
Dalli::Protocol::Meta::RequestFormatter.meta_delete(key: key)
|
||||
end
|
||||
|
||||
- it 'returns incorporates CAS when passed cas' do
|
||||
+ it 'incorporates CAS when passed cas' do
|
||||
assert_equal "md #{key} C#{cas}\r\n",
|
||||
Dalli::Protocol::Meta::RequestFormatter.meta_delete(key: key, cas: cas)
|
||||
end
|
||||
@@ -102,6 +119,87 @@
|
||||
assert_equal "md #{key} q\r\n",
|
||||
Dalli::Protocol::Meta::RequestFormatter.meta_delete(key: key, quiet: true)
|
||||
end
|
||||
+
|
||||
+ it 'excludes CAS when set to 0' do
|
||||
+ assert_equal "md #{key}\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_delete(key: key, cas: 0)
|
||||
+ end
|
||||
+
|
||||
+ it 'excludes non-numeric CAS values' do
|
||||
+ assert_equal "md #{key}\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_delete(key: key,
|
||||
+ cas: "\nset importantkey 1 1000 8\ninjected")
|
||||
+ end
|
||||
+
|
||||
+ it 'sets the base64 mode if configured' do
|
||||
+ assert_equal "md #{key} b\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_delete(key: key, base64: true)
|
||||
+ end
|
||||
+ end
|
||||
+
|
||||
+ describe 'meta_arithmetic' do
|
||||
+ let(:key) { SecureRandom.hex(4) }
|
||||
+ let(:delta) { rand(500..999) }
|
||||
+ let(:initial) { rand(500..999) }
|
||||
+ let(:cas) { rand(500..999) }
|
||||
+ let(:ttl) { rand(500..999) }
|
||||
+
|
||||
+ it 'returns the expected string with the default N flag when passed non-nil key, delta, and initial' do
|
||||
+ assert_equal "ma #{key} v D#{delta} J#{initial} N0 MI\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: delta, initial: initial)
|
||||
+ end
|
||||
+
|
||||
+ it 'excludes the J and N flags when initial is nil and ttl is not set' do
|
||||
+ assert_equal "ma #{key} v D#{delta} MI\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: delta, initial: nil)
|
||||
+ end
|
||||
+
|
||||
+ it 'omits the D flag is delta is nil' do
|
||||
+ assert_equal "ma #{key} v J#{initial} N0 MI\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: nil, initial: initial)
|
||||
+ end
|
||||
+
|
||||
+ it 'uses ttl for the N flag when ttl passed explicitly along with an initial value' do
|
||||
+ assert_equal "ma #{key} v D#{delta} J#{initial} N#{ttl} MI\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: delta, initial: initial,
|
||||
+ ttl: ttl)
|
||||
+ end
|
||||
+
|
||||
+ it 'incorporates CAS when passed cas' do
|
||||
+ assert_equal "ma #{key} v D#{delta} J#{initial} N0 C#{cas} MI\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: delta, initial: initial,
|
||||
+ cas: cas)
|
||||
+ end
|
||||
+
|
||||
+ it 'excludes CAS when CAS is set to 0' do
|
||||
+ assert_equal "ma #{key} v D#{delta} J#{initial} N0 MI\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: delta, initial: initial,
|
||||
+ cas: 0)
|
||||
+ end
|
||||
+
|
||||
+ it 'includes the N flag when ttl passed explicitly with a nil initial value' do
|
||||
+ assert_equal "ma #{key} v D#{delta} N#{ttl} MI\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: delta, initial: nil,
|
||||
+ ttl: ttl)
|
||||
+ end
|
||||
+
|
||||
+ it 'swaps from MI to MD when the incr value is explicitly false' do
|
||||
+ assert_equal "ma #{key} v D#{delta} J#{initial} N0 MD\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: delta, initial: initial,
|
||||
+ incr: false)
|
||||
+ end
|
||||
+
|
||||
+ it 'includes the quiet flag when specified' do
|
||||
+ assert_equal "ma #{key} v D#{delta} J#{initial} N0 q MI\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: delta, initial: initial,
|
||||
+ quiet: true)
|
||||
+ end
|
||||
+
|
||||
+ it 'sets the base64 mode if configured' do
|
||||
+ assert_equal "ma #{key} v b D#{delta} J#{initial} N0 MI\r\n",
|
||||
+ Dalli::Protocol::Meta::RequestFormatter.meta_arithmetic(key: key, delta: delta, initial: initial,
|
||||
+ base64: true)
|
||||
+ end
|
||||
end
|
||||
|
||||
describe 'meta_noop' do
|
||||
@@ -130,6 +228,11 @@
|
||||
assert_equal "flush_all #{delay}\r\n", Dalli::Protocol::Meta::RequestFormatter.flush(delay: delay)
|
||||
end
|
||||
|
||||
+ it 'santizes the delay argument' do
|
||||
+ delay = "\nset importantkey 1 1000 8\ninjected"
|
||||
+ assert_equal "flush_all 0\r\n", Dalli::Protocol::Meta::RequestFormatter.flush(delay: delay)
|
||||
+ end
|
||||
+
|
||||
it 'adds noreply with a delay and quiet argument' do
|
||||
delay = rand(1000..1999)
|
||||
assert_equal "flush_all #{delay} noreply\r\n",
|
||||
diff --git a/test/test_rack_session.rb b/test/test_rack_session.rb
|
||||
index e56a098e..93860345 100644
|
||||
--- a/test/test_rack_session.rb
|
||||
+++ b/test/test_rack_session.rb
|
||||
@@ -54,15 +54,15 @@
|
||||
let(:incrementor) { Rack::Lint.new(incrementor_proc) }
|
||||
|
||||
it 'faults on no connection' do
|
||||
+ rsd = Rack::Session::Dalli.new(incrementor, memcache_server: 'nosuchserver')
|
||||
assert_raises Dalli::RingError do
|
||||
- rsd = Rack::Session::Dalli.new(incrementor, memcache_server: 'nosuchserver')
|
||||
rsd.data.with { |c| c.set('ping', '') }
|
||||
end
|
||||
end
|
||||
|
||||
it 'connects to existing server' do
|
||||
+ rsd = Rack::Session::Dalli.new(incrementor, namespace: 'test:rack:session')
|
||||
assert_silent do
|
||||
- rsd = Rack::Session::Dalli.new(incrementor, namespace: 'test:rack:session')
|
||||
rsd.data.with { |c| c.set('ping', '') }
|
||||
end
|
||||
end
|
||||
@ -2,7 +2,7 @@
|
||||
%global enable_test 0
|
||||
Name: rubygem-%{gem_name}
|
||||
Version: 3.2.2
|
||||
Release: 1
|
||||
Release: 2
|
||||
Summary: High performance memcached client for Ruby
|
||||
License: MIT
|
||||
URL: https://github.com/petergoldstein/dalli
|
||||
@ -10,6 +10,8 @@ Source0: https://rubygems.org/gems/%{gem_name}-%{version}.gem
|
||||
Source1: %{gem_name}-%{version}-tests.tgz
|
||||
Patch0: rubygem-dalli-2.7.6-Use-assert_nil-in-tests.patch
|
||||
Patch1: rubygem-dalli-2.7.6-Fix-memcached-1.5.4-compatibility.patch
|
||||
Patch2: CVE-2022-4064-1.patch
|
||||
Patch3: CVE-2022-4064-2.patch
|
||||
BuildRequires: ruby(release) rubygems-devel
|
||||
%if 0%{enable_test} > 0
|
||||
BuildRequires: memcached rubygem(minitest) rubygem(mocha) rubygem(rails)
|
||||
@ -29,6 +31,7 @@ Documentation for %{name}
|
||||
|
||||
%prep
|
||||
%setup -q -n %{gem_name}-%{version}
|
||||
%patch2 -p1
|
||||
|
||||
%build
|
||||
gem build ../%{gem_name}-%{version}.gemspec
|
||||
@ -45,6 +48,7 @@ pushd .%{gem_instdir}
|
||||
tar xzvf %{SOURCE1}
|
||||
cat %{PATCH0} | patch -p1
|
||||
cat %{PATCH1} | patch -p1
|
||||
cat %{PATCH3} | patch -p1
|
||||
sed -i '/bundler/ s/^/#/' test/helper.rb
|
||||
ruby -Ilib:test -e "Dir.glob('./test/test_*.rb').sort.each{ |x| require x }"
|
||||
popd
|
||||
@ -64,6 +68,9 @@ popd
|
||||
%{gem_instdir}/Gemfile
|
||||
|
||||
%changelog
|
||||
* Thu Dec 15 2022 liyuxiang <liyuxiang@ncti-gba.cn> - 3.2.2-2
|
||||
- fix CVE-2022-4064
|
||||
|
||||
* Tue Jun 28 2022 baizhonggui <baizhonggui@h-partners.com> - 3.2.2-1
|
||||
- update to 3.2.2
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user