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
|
%global enable_test 0
|
||||||
Name: rubygem-%{gem_name}
|
Name: rubygem-%{gem_name}
|
||||||
Version: 3.2.2
|
Version: 3.2.2
|
||||||
Release: 1
|
Release: 2
|
||||||
Summary: High performance memcached client for Ruby
|
Summary: High performance memcached client for Ruby
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: https://github.com/petergoldstein/dalli
|
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
|
Source1: %{gem_name}-%{version}-tests.tgz
|
||||||
Patch0: rubygem-dalli-2.7.6-Use-assert_nil-in-tests.patch
|
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
|
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
|
BuildRequires: ruby(release) rubygems-devel
|
||||||
%if 0%{enable_test} > 0
|
%if 0%{enable_test} > 0
|
||||||
BuildRequires: memcached rubygem(minitest) rubygem(mocha) rubygem(rails)
|
BuildRequires: memcached rubygem(minitest) rubygem(mocha) rubygem(rails)
|
||||||
@ -29,6 +31,7 @@ Documentation for %{name}
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{gem_name}-%{version}
|
%setup -q -n %{gem_name}-%{version}
|
||||||
|
%patch2 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
gem build ../%{gem_name}-%{version}.gemspec
|
gem build ../%{gem_name}-%{version}.gemspec
|
||||||
@ -45,6 +48,7 @@ pushd .%{gem_instdir}
|
|||||||
tar xzvf %{SOURCE1}
|
tar xzvf %{SOURCE1}
|
||||||
cat %{PATCH0} | patch -p1
|
cat %{PATCH0} | patch -p1
|
||||||
cat %{PATCH1} | patch -p1
|
cat %{PATCH1} | patch -p1
|
||||||
|
cat %{PATCH3} | patch -p1
|
||||||
sed -i '/bundler/ s/^/#/' test/helper.rb
|
sed -i '/bundler/ s/^/#/' test/helper.rb
|
||||||
ruby -Ilib:test -e "Dir.glob('./test/test_*.rb').sort.each{ |x| require x }"
|
ruby -Ilib:test -e "Dir.glob('./test/test_*.rb').sort.each{ |x| require x }"
|
||||||
popd
|
popd
|
||||||
@ -64,6 +68,9 @@ popd
|
|||||||
%{gem_instdir}/Gemfile
|
%{gem_instdir}/Gemfile
|
||||||
|
|
||||||
%changelog
|
%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
|
* Tue Jun 28 2022 baizhonggui <baizhonggui@h-partners.com> - 3.2.2-1
|
||||||
- update to 3.2.2
|
- update to 3.2.2
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user