dalli 3.2.1 → 3.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f81141d870bf96f502734833c9e63678c4f034a2e5cdb6a28bf1fe54b5a6f8f2
4
- data.tar.gz: abbb39311cd429b8546397b1c5ba0555024f104e49a6b23fd97b3386408cb5e6
3
+ metadata.gz: f0ef39f4ff4e9e465b2522707f3c4eea85a94373ba0d3de4b9d940830001b118
4
+ data.tar.gz: 35cb362ec6075818f062106769481e92c90752936ecaf9a00fae25725ee4ea94
5
5
  SHA512:
6
- metadata.gz: 1a6af753aa61a1e80ed734eabb2fa70b8c14e2c1d2fd43a8f95f600732c02d2de08018cb9f41ce776d7796815f8da52fff4a95b05fccb732fe58506d6c38cb2f
7
- data.tar.gz: 1724f003506854bc011c90402584a898534059b022de87385e0f8f2b24879897f23d33219f732489212aaf86b58eaa3c6d6ceb4e86c028daacd5180bc3be07ae
6
+ metadata.gz: 0c6b2b205551fb10fb2e49ab7c3c3eba3c552c0bc4b8132783b51f6cdc7a9ddd4c272bd24ed13f9d78e29353e3b84daec001b2691ad630bdfd517bb7af86fd54
7
+ data.tar.gz: 6ef9f6733d8e6d5f8a6bf8fb7d782e99c450494e03d4e5fe46037b77665682df63eaa9a3eb05007d1720b175564c8e91524c0df92d0856dc1f68066501732a06
@@ -4,6 +4,20 @@ Dalli Changelog
4
4
  Unreleased
5
5
  ==========
6
6
 
7
+ 3.2.3
8
+ ==========
9
+
10
+ - Sanitize CAS inputs to ensure additional commands are not passed to memcached (xhzeem / petergoldstein)
11
+ - Sanitize input to flush command to ensure additional commands are not passed to memcached (xhzeem / petergoldstein)
12
+ - Namespaces passed as procs are now evaluated every time, as opposed to just on initialization (nrw505)
13
+ - Fix missing require of uri in ServerConfigParser (adam12)
14
+ - Fix link to the CHANGELOG.md file in README.md (rud)
15
+
16
+ 3.2.2
17
+ ==========
18
+
19
+ - Ensure apps are resilient against old session ids (kbrock)
20
+
7
21
  3.2.1
8
22
  ==========
9
23
 
@@ -118,6 +132,9 @@ Unreleased
118
132
  * The Rack session adapter has been refactored to remove support for thread-unsafe
119
133
  configurations. You will need to include the `connection_pool` gem in
120
134
  your Gemfile to ensure session operations are thread-safe.
135
+ * When using namespaces, the algorithm for calculating truncated keys was
136
+ changed. Non-truncated keys and truncated keys for the non-namespace
137
+ case were left unchanged.
121
138
 
122
139
  - Raise NetworkError when multi response gets into corrupt state (mervync, #783)
123
140
  - Validate servers argument (semaperepelitsa, petergoldstein, #776)
data/Gemfile CHANGED
@@ -5,12 +5,5 @@ source 'https://rubygems.org'
5
5
  gemspec
6
6
 
7
7
  group :test do
8
- gem 'minitest'
9
- gem 'rake'
10
- gem 'rubocop'
11
- gem 'rubocop-minitest'
12
- gem 'rubocop-performance'
13
- gem 'rubocop-rake'
14
8
  gem 'ruby-prof', platform: :mri
15
- gem 'simplecov'
16
9
  end
data/README.md CHANGED
@@ -23,11 +23,11 @@ The name is a variant of Salvador Dali for his famous painting [The Persistence
23
23
  * [Announcements](https://github.com/petergoldstein/dalli/discussions/categories/announcements) - Announcements of interest to the Dalli community will be posted here.
24
24
  * [Bug Reports](https://github.com/petergoldstein/dalli/issues) - If you discover a problem with Dalli, please submit a bug report in the tracker.
25
25
  * [Forum](https://github.com/petergoldstein/dalli/discussions/categories/q-a) - If you have questions about Dalli, please post them here.
26
- * [Client API](https://www.rubydoc.info/github/petergoldstein/dalli/master/Dalli/Client) - Ruby documentation for the `Dalli::Client` API
26
+ * [Client API](https://rubydoc.info/github/petergoldstein/dalli/Dalli/Client) - Ruby documentation for the `Dalli::Client` API
27
27
 
28
28
  ## Contributing
29
29
 
30
- If you have a fix you wish to provide, please fork the code, fix in your local project and then send a pull request on github. Please ensure that you include a test which verifies your fix and update `History.md` with a one sentence description of your fix so you get credit as a contributor.
30
+ If you have a fix you wish to provide, please fork the code, fix in your local project and then send a pull request on github. Please ensure that you include a test which verifies your fix and update the [changelog](CHANGELOG.md) with a one sentence description of your fix so you get credit as a contributor.
31
31
 
32
32
  ## Appreciation
33
33
 
@@ -61,7 +61,7 @@ module Dalli
61
61
  def key_with_namespace(key)
62
62
  return key if namespace.nil?
63
63
 
64
- "#{namespace}#{NAMESPACE_SEPARATOR}#{key}"
64
+ "#{evaluate_namespace}#{NAMESPACE_SEPARATOR}#{key}"
65
65
  end
66
66
 
67
67
  def key_without_namespace(key)
@@ -75,6 +75,8 @@ module Dalli
75
75
  end
76
76
 
77
77
  def namespace_regexp
78
+ return /\A#{Regexp.escape(evaluate_namespace)}:/ if namespace.is_a?(Proc)
79
+
78
80
  @namespace_regexp ||= /\A#{Regexp.escape(namespace)}:/.freeze unless namespace.nil?
79
81
  end
80
82
 
@@ -87,9 +89,15 @@ module Dalli
87
89
  def namespace_from_options
88
90
  raw_namespace = @key_options[:namespace]
89
91
  return nil unless raw_namespace
90
- return raw_namespace.call.to_s if raw_namespace.is_a?(Proc)
92
+ return raw_namespace.to_s unless raw_namespace.is_a?(Proc)
93
+
94
+ raw_namespace
95
+ end
96
+
97
+ def evaluate_namespace
98
+ return namespace.call.to_s if namespace.is_a?(Proc)
91
99
 
92
- raw_namespace.to_s
100
+ namespace
93
101
  end
94
102
 
95
103
  ##
@@ -167,7 +167,7 @@ module Dalli
167
167
  groups = @ring.keys_grouped_by_server(keys)
168
168
  if (unfound_keys = groups.delete(nil))
169
169
  Dalli.logger.debug do
170
- "unable to get keys for #{unfound_keys.length} keys "\
170
+ "unable to get keys for #{unfound_keys.length} keys " \
171
171
  'because no matching server was found'
172
172
  end
173
173
  end
@@ -127,11 +127,11 @@ module Dalli
127
127
  end
128
128
 
129
129
  def username
130
- @options[:username] || ENV['MEMCACHE_USERNAME']
130
+ @options[:username] || ENV.fetch('MEMCACHE_USERNAME', nil)
131
131
  end
132
132
 
133
133
  def password
134
- @options[:password] || ENV['MEMCACHE_PASSWORD']
134
+ @options[:password] || ENV.fetch('MEMCACHE_PASSWORD', nil)
135
135
  end
136
136
 
137
137
  def require_auth?
@@ -31,7 +31,7 @@ module Dalli
31
31
  cmd << ' c' unless %i[append prepend].include?(mode)
32
32
  cmd << ' b' if base64
33
33
  cmd << " F#{bitflags}" if bitflags
34
- cmd << " C#{cas}" if cas && !cas.zero?
34
+ cmd << cas_string(cas)
35
35
  cmd << " T#{ttl}" if ttl
36
36
  cmd << " M#{mode_to_token(mode)}"
37
37
  cmd << ' q' if quiet
@@ -43,7 +43,7 @@ module Dalli
43
43
  def self.meta_delete(key:, cas: nil, ttl: nil, base64: false, quiet: false)
44
44
  cmd = "md #{key}"
45
45
  cmd << ' b' if base64
46
- cmd << " C#{cas}" if cas && !cas.zero?
46
+ cmd << cas_string(cas)
47
47
  cmd << " T#{ttl}" if ttl
48
48
  cmd << ' q' if quiet
49
49
  cmd + TERMINATOR
@@ -54,8 +54,9 @@ module Dalli
54
54
  cmd << ' b' if base64
55
55
  cmd << " D#{delta}" if delta
56
56
  cmd << " J#{initial}" if initial
57
- cmd << " C#{cas}" if cas && !cas.zero?
58
- cmd << " N#{ttl}" if ttl
57
+ # Always set a TTL if an initial value is specified
58
+ cmd << " N#{ttl || 0}" if ttl || initial
59
+ cmd << cas_string(cas)
59
60
  cmd << ' q' if quiet
60
61
  cmd << " M#{incr ? 'I' : 'D'}"
61
62
  cmd + TERMINATOR
@@ -75,7 +76,7 @@ module Dalli
75
76
 
76
77
  def self.flush(delay: nil, quiet: false)
77
78
  cmd = +'flush_all'
78
- cmd << " #{delay}" if delay
79
+ cmd << " #{parse_to_64_bit_int(delay, 0)}" if delay
79
80
  cmd << ' noreply' if quiet
80
81
  cmd + TERMINATOR
81
82
  end
@@ -102,6 +103,18 @@ module Dalli
102
103
  end
103
104
  end
104
105
  # rubocop:enable Metrics/MethodLength
106
+
107
+ def self.cas_string(cas)
108
+ cas = parse_to_64_bit_int(cas, nil)
109
+ cas.nil? || cas.zero? ? '' : " C#{cas}"
110
+ end
111
+
112
+ def self.parse_to_64_bit_int(val, default)
113
+ val.nil? ? nil : Integer(val)
114
+ rescue ArgumentError
115
+ # Sanitize to default if it isn't parsable as an integer
116
+ default
117
+ end
105
118
  end
106
119
  end
107
120
  end
@@ -44,6 +44,7 @@ module Dalli
44
44
  end
45
45
 
46
46
  def touch(key, ttl)
47
+ ttl = TtlSanitizer.sanitize(ttl)
47
48
  encoded_key, base64 = KeyRegularizer.encode(key)
48
49
  req = RequestFormatter.meta_get(key: encoded_key, ttl: ttl, value: false, base64: base64)
49
50
  write(req)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'uri'
4
+
3
5
  module Dalli
4
6
  module Protocol
5
7
  ##
@@ -40,7 +40,7 @@ module Dalli
40
40
  def self.apply_defaults(arg)
41
41
  return arg unless arg.nil?
42
42
 
43
- ENV[ENV_VAR_NAME] || DEFAULT_SERVERS
43
+ ENV.fetch(ENV_VAR_NAME, nil) || DEFAULT_SERVERS
44
44
  end
45
45
 
46
46
  def self.validate_type(arg)
data/lib/dalli/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dalli
4
- VERSION = '3.2.1'
4
+ VERSION = '3.2.3'
5
5
 
6
6
  MIN_SUPPORTED_MEMCACHED_VERSION = '1.4'
7
7
  end
@@ -82,6 +82,9 @@ module Rack
82
82
  def write_session(_req, sid, session, options)
83
83
  return false unless sid
84
84
 
85
+ key = memcached_key_from_sid(sid)
86
+ return false unless key
87
+
85
88
  with_dalli_client(false) do |dc|
86
89
  dc.set(memcached_key_from_sid(sid), session, ttl(options[:expire_after]))
87
90
  sid
@@ -90,7 +93,8 @@ module Rack
90
93
 
91
94
  def delete_session(_req, sid, options)
92
95
  with_dalli_client do |dc|
93
- dc.delete(memcached_key_from_sid(sid))
96
+ key = memcached_key_from_sid(sid)
97
+ dc.delete(key) if key
94
98
  generate_sid_with(dc) unless options[:drop]
95
99
  end
96
100
  end
@@ -98,20 +102,24 @@ module Rack
98
102
  private
99
103
 
100
104
  def memcached_key_from_sid(sid)
101
- sid.private_id
105
+ sid.private_id if sid.respond_to?(:private_id)
102
106
  end
103
107
 
104
108
  def existing_session_for_sid(client, sid)
105
109
  return nil unless sid && !sid.empty?
106
110
 
107
- client.get(memcached_key_from_sid(sid))
111
+ key = memcached_key_from_sid(sid)
112
+ return nil if key.nil?
113
+
114
+ client.get(key)
108
115
  end
109
116
 
110
117
  def create_sid_with_empty_session(client)
111
118
  loop do
112
119
  sid = generate_sid_with(client)
120
+ key = memcached_key_from_sid(sid)
113
121
 
114
- break sid if client.add(memcached_key_from_sid(sid), {}, @default_ttl)
122
+ break sid if key && client.add(key, {}, @default_ttl)
115
123
  end
116
124
  end
117
125
 
@@ -119,7 +127,8 @@ module Rack
119
127
  loop do
120
128
  raw_sid = generate_sid
121
129
  sid = raw_sid.is_a?(String) ? Rack::Session::SessionId.new(raw_sid) : raw_sid
122
- break sid unless client.get(memcached_key_from_sid(sid))
130
+ key = memcached_key_from_sid(sid)
131
+ break sid unless key && client.get(key)
123
132
  end
124
133
  end
125
134
 
@@ -161,7 +170,7 @@ module Rack
161
170
  def ensure_connection_pool_added!
162
171
  require 'connection_pool'
163
172
  rescue LoadError => e
164
- warn "You don't have connection_pool installed in your application. "\
173
+ warn "You don't have connection_pool installed in your application. " \
165
174
  'Please add it to your Gemfile and run bundle install'
166
175
  raise e
167
176
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dalli
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter M. Goldstein
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-02-14 00:00:00.000000000 Z
12
+ date: 2022-10-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: connection_pool
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: minitest
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '5'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '5'
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: rack
30
44
  requirement: !ruby/object:Gem::Requirement
@@ -45,6 +59,20 @@ dependencies:
45
59
  - - ">="
46
60
  - !ruby/object:Gem::Version
47
61
  version: 2.2.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '13.0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '13.0'
48
76
  - !ruby/object:Gem::Dependency
49
77
  name: rubocop
50
78
  requirement: !ruby/object:Gem::Requirement
@@ -101,6 +129,20 @@ dependencies:
101
129
  - - ">="
102
130
  - !ruby/object:Gem::Version
103
131
  version: '0'
132
+ - !ruby/object:Gem::Dependency
133
+ name: simplecov
134
+ requirement: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ type: :development
140
+ prerelease: false
141
+ version_requirements: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
104
146
  description: High performance memcached client for Ruby
105
147
  email:
106
148
  - peter.m.goldstein@gmail.com
@@ -109,8 +151,8 @@ executables: []
109
151
  extensions: []
110
152
  extra_rdoc_files: []
111
153
  files:
154
+ - CHANGELOG.md
112
155
  - Gemfile
113
- - History.md
114
156
  - LICENSE
115
157
  - README.md
116
158
  - lib/dalli.rb
@@ -164,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
206
  - !ruby/object:Gem::Version
165
207
  version: '0'
166
208
  requirements: []
167
- rubygems_version: 3.3.7
209
+ rubygems_version: 3.3.24
168
210
  signing_key:
169
211
  specification_version: 4
170
212
  summary: High performance memcached client for Ruby