dalli 3.2.8 → 3.2.10

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: c7d8b3dd9e76a224d876f901dc44c3cf8016326209df3efc7fe522053a4a3c22
4
- data.tar.gz: 0ced058a6a170cadd4b74268de5417c4a1e700baf5767fc8f260db9477e2b735
3
+ metadata.gz: d9cebd01e657a541e7685974157dc2ab4a6e497a721ee7d4f74a35c377eca642
4
+ data.tar.gz: 8ee63be1f4883d090f76ce4ab9d906ee44b7175b2d3a94940a1833feb221d7f3
5
5
  SHA512:
6
- metadata.gz: 3e316a4d60c3327cecec46a0a34c52536130199124035c375bf1933676d85fbf09e99a985ae44faf4e27b0fb1f8b8faef1656a812e6bdfc387406c5e18874461
7
- data.tar.gz: bce3e0e41c280e99889bea6835c1b2f701cbcb5e4f398203ae2b4d6ebc05cdc505ee5955365715f8e00441d69701ceac84de37a98eac8581d003d1ab411a33e9
6
+ metadata.gz: 5dc86292a8a53254969b27a055fbb211e9f3d883788f9e52a546dcba415a764919b6d770afb17597ffda6e5f1411e25c6297201dfdb8ea078c3bf13737e81208
7
+ data.tar.gz: 1dc924140f6b5ca737467079a100971589d79ba912e91f0e460d67507366a08c03e73806710c92251f9e3cc20bda574df0b0e268a3e7c7413150fb3d38dbd23c
data/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ Dalli Changelog
4
4
  Unreleased
5
5
  ==========
6
6
 
7
+ 3.2.10
8
+ ==========
9
+
10
+ - Fix `Rack::Session::Dalli` with connection_pool 3.x, which only accepts keyword arguments (backport of #1051)
11
+ - Add `logger` as a runtime dependency, since it is no longer a default gem as of Ruby 4.0 (backport of #1010, olleolleolle)
12
+ - CI: patch memcached 1.5.22 so it builds on ubuntu-22.04, and run tests there (backport of #1033)
13
+
14
+ 3.2.9
15
+ ==========
16
+
17
+ Security:
18
+
19
+ - Fix memcached command injection through the `incr`/`decr` default with the meta protocol (GHSA-6wmv-xq9m-fmp7)
20
+ - With `protocol: :meta`, the `default` argument of `incr`/`decr` was written into the command without conversion, so a String containing CRLF injected additional memcached commands (e.g. `set`, `flush_all`) on the connection. The default binary protocol is not affected
21
+ - `default` must now be an Integer, or a String of decimal digits; anything else raises `ArgumentError` before a request is sent
22
+ - As defense in depth, the meta `RequestFormatter` now converts every numeric flag it writes (`D`, `J`, `N`, `T`) to an Integer
23
+ - Thanks to oss-security-shop for the report
24
+
7
25
  3.2.8
8
26
  ==========
9
27
 
data/lib/dalli/client.rb CHANGED
@@ -257,6 +257,8 @@ module Dalli
257
257
  ##
258
258
  # Incr adds the given amount to the counter on the memcached server.
259
259
  # Amt must be a positive integer value.
260
+ # Default, if given, must be an Integer (or a String of decimal digits);
261
+ # anything else raises ArgumentError.
260
262
  #
261
263
  # If default is nil, the counter must already exist or the operation
262
264
  # will fail and will return nil. Otherwise this method will return
@@ -269,6 +271,7 @@ module Dalli
269
271
  # If the value already exists, it must have been set with raw: true
270
272
  def incr(key, amt = 1, ttl = nil, default = nil)
271
273
  check_positive!(amt)
274
+ validate_integer!(:default, default)
272
275
 
273
276
  perform(:incr, key, amt.to_i, ttl_or_default(ttl), default)
274
277
  end
@@ -276,6 +279,8 @@ module Dalli
276
279
  ##
277
280
  # Decr subtracts the given amount from the counter on the memcached server.
278
281
  # Amt must be a positive integer value.
282
+ # Default, if given, must be an Integer (or a String of decimal digits);
283
+ # anything else raises ArgumentError.
279
284
  #
280
285
  # memcached counters are unsigned and cannot hold negative values. Calling
281
286
  # decr on a counter which is 0 will just return 0.
@@ -291,6 +296,7 @@ module Dalli
291
296
  # If the value already exists, it must have been set with raw: true
292
297
  def decr(key, amt = 1, ttl = nil, default = nil)
293
298
  check_positive!(amt)
299
+ validate_integer!(:default, default)
294
300
 
295
301
  perform(:decr, key, amt.to_i, ttl_or_default(ttl), default)
296
302
  end
@@ -373,6 +379,14 @@ module Dalli
373
379
  raise ArgumentError, "Positive values only: #{amt}" if amt.negative?
374
380
  end
375
381
 
382
+ # Numeric arguments that become meta protocol flags (GHSA-6wmv-xq9m-fmp7).
383
+ # Checked before the request starts so a bad value raises a clean
384
+ # ArgumentError, instead of Protocol::Base#request logging it as
385
+ # unexpected and closing the connection.
386
+ def validate_integer!(name, value)
387
+ Dalli::Protocol::Meta::RequestFormatter.integer_flag(name, value) unless value.nil?
388
+ end
389
+
376
390
  def cas_core(key, always_set, ttl = nil, req_options = nil)
377
391
  (value, cas) = perform(:cas, key)
378
392
  return if value.nil? && !always_set
@@ -21,7 +21,7 @@ module Dalli
21
21
  cmd << ' v f' if value
22
22
  cmd << ' c' if return_cas
23
23
  cmd << ' b' if base64
24
- cmd << " T#{ttl}" if ttl
24
+ cmd << " T#{integer_flag(:ttl, ttl)}" if ttl
25
25
  cmd << ' k q s' if quiet # Return the key in the response if quiet
26
26
  cmd + TERMINATOR
27
27
  end
@@ -32,7 +32,7 @@ module Dalli
32
32
  cmd << ' b' if base64
33
33
  cmd << " F#{bitflags}" if bitflags
34
34
  cmd << cas_string(cas)
35
- cmd << " T#{ttl}" if ttl
35
+ cmd << " T#{integer_flag(:ttl, ttl)}" if ttl
36
36
  cmd << " M#{mode_to_token(mode)}"
37
37
  cmd << ' q' if quiet
38
38
  cmd << TERMINATOR
@@ -44,7 +44,7 @@ module Dalli
44
44
  cmd = "md #{key}"
45
45
  cmd << ' b' if base64
46
46
  cmd << cas_string(cas)
47
- cmd << " T#{ttl}" if ttl
47
+ cmd << " T#{integer_flag(:ttl, ttl)}" if ttl
48
48
  cmd << ' q' if quiet
49
49
  cmd + TERMINATOR
50
50
  end
@@ -52,10 +52,10 @@ module Dalli
52
52
  def self.meta_arithmetic(key:, delta:, initial:, incr: true, cas: nil, ttl: nil, base64: false, quiet: false)
53
53
  cmd = "ma #{key} v"
54
54
  cmd << ' b' if base64
55
- cmd << " D#{delta}" if delta
56
- cmd << " J#{initial}" if initial
55
+ cmd << " D#{integer_flag(:delta, delta)}" if delta
56
+ cmd << " J#{integer_flag(:initial, initial)}" if initial
57
57
  # Always set a TTL if an initial value is specified
58
- cmd << " N#{ttl || 0}" if ttl || initial
58
+ cmd << " N#{ttl ? integer_flag(:ttl, ttl) : 0}" if ttl || initial
59
59
  cmd << cas_string(cas)
60
60
  cmd << ' q' if quiet
61
61
  cmd << " M#{incr ? 'I' : 'D'}"
@@ -104,6 +104,18 @@ module Dalli
104
104
  end
105
105
  # rubocop:enable Metrics/MethodLength
106
106
 
107
+ # Numeric flag values are written straight into the command line, so a
108
+ # value that isn't an integer -- e.g. a String carrying CRLF -- would let
109
+ # the caller inject further memcached commands (GHSA-6wmv-xq9m-fmp7).
110
+ # Converting to Integer means only digits ever reach the wire. Strings
111
+ # are parsed as base 10 so "010" means 10, as memcached would read it,
112
+ # rather than octal 8.
113
+ def self.integer_flag(name, value)
114
+ value.is_a?(String) ? Integer(value, 10) : Integer(value)
115
+ rescue ArgumentError, TypeError, FloatDomainError
116
+ raise ArgumentError, "#{name} must be an Integer, got #{value.inspect}"
117
+ end
118
+
107
119
  def self.cas_string(cas)
108
120
  cas = parse_to_64_bit_int(cas, nil)
109
121
  cas.nil? || cas.zero? ? '' : " C#{cas}"
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.8'
4
+ VERSION = '3.2.10'
5
5
 
6
6
  MIN_SUPPORTED_MEMCACHED_VERSION = '1.4'
7
7
  end
@@ -139,7 +139,7 @@ module Rack
139
139
  ::Dalli::Client.new(server_configurations, client_options)
140
140
  else
141
141
  ensure_connection_pool_added!
142
- ConnectionPool.new(pool_options) do
142
+ ConnectionPool.new(**pool_options) do
143
143
  ::Dalli::Client.new(server_configurations, client_options.merge(threadsafe: false))
144
144
  end
145
145
  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.8
4
+ version: 3.2.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter M. Goldstein
@@ -9,8 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-02-12 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2026-09-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: logger
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
14
28
  description: High performance memcached client for Ruby
15
29
  email:
16
30
  - peter.m.goldstein@gmail.com
@@ -77,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
91
  - !ruby/object:Gem::Version
78
92
  version: '0'
79
93
  requirements: []
80
- rubygems_version: 3.5.6
94
+ rubygems_version: 3.5.4
81
95
  signing_key:
82
96
  specification_version: 4
83
97
  summary: High performance memcached client for Ruby