dalli 5.1.7 → 5.1.8

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: 9cda501a8348a7a2b6f897fca7bbda70695197458a62211dda0f4f5d8d00e586
4
- data.tar.gz: fd4967e4402a20c57aab078ed9fa45b79a1422c1d88f4929a0c91420e482efed
3
+ metadata.gz: aedfdf5af128f44424f0d21689f66a86813b9714677716854889788fe3b62546
4
+ data.tar.gz: 4375bcb70c31f53ac8fbf13cc4bc16171756a87148f95c024d214d8028216795
5
5
  SHA512:
6
- metadata.gz: db5ea127a20751261ab19606deab18c4da1736268d0ea37ce8f2de306ae0745617d0d7d9764c886d2a0a035cb72d0b5ecf3c967803241824efcd93235fef6065
7
- data.tar.gz: 905bc444c1c090337e799371099b481b54ce1863d286652572032c9c21dc55f703d19b8adaca34a615fe6d2933adc9033f8d0e9cc49c4cc283e1637443409568
6
+ metadata.gz: ea2568b866c13f7d3bb9bf7d0c305c2164503df325c029d5aa160edb1316bc8ff01f97ec30d46e8a5113ed49350f6813c915f6202a093c7d28b21f9aed690cf0
7
+ data.tar.gz: 2dac25033ab69bc1819eae18a94e2f7b4b672e540438e94f6aa8d73fe414baa47b17d77a65137b667ee1a9d0c57927477e30563b34c08d1cf4dbfde5f760ca1f
data/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ Dalli Changelog
4
4
  Unreleased
5
5
  ==========
6
6
 
7
+ 5.1.8
8
+ ==========
9
+
10
+ Bug fixes:
11
+
12
+ - Raw values in an encoding that isn't ASCII-compatible, such as UTF-16, raised `Encoding::CompatibilityError` from `set`, `add`, `replace`, `append`, `prepend` and `set_multi`, as did a single-server `set_multi` mixing non-ASCII UTF-8 values with binary ones (such as raw Strings of both kinds, or with a JSON serializer, a value containing `é` next to a compressed one). A `p_token` or `l_token` with non-ASCII characters, such as `é`, did the same for any binary value, including every Marshal-serialized one. The error also closed the connection, so in a `quiet` block, or within one server's part of a multi-server `set_multi`, writes buffered before it were silently lost. Values are now sent as their bytes, which is what memcached stores (#1269)
13
+
7
14
  5.1.7
8
15
  ==========
9
16
 
@@ -162,7 +162,7 @@ module Dalli
162
162
  bitflags: bitflags, cas: cas,
163
163
  ttl: ttl, mode: mode, quiet: quiet,
164
164
  **routing_token_kwargs(options))
165
- write("#{req}#{value}#{TERMINATOR}")
165
+ write(request_with_value(req, value))
166
166
  @connection_manager.flush unless quiet
167
167
  end
168
168
  # rubocop:enable Metrics/ParameterLists
@@ -183,10 +183,20 @@ module Dalli
183
183
  req = RequestFormatter.meta_set(key: key, value: value,
184
184
  cas: cas, ttl: ttl, mode: mode, quiet: quiet?,
185
185
  **routing_token_kwargs(options))
186
- write("#{req}#{value}#{TERMINATOR}")
186
+ write(request_with_value(req, value))
187
187
  @connection_manager.flush unless quiet?
188
188
  end
189
189
 
190
+ # Ruby refuses to join Strings whose encodings clash, such as a raw
191
+ # UTF-16 value, or a routing token with non-ASCII characters next to a
192
+ # binary value. memcached stores bytes, so join the bytes then.
193
+ # Joining the Strings first keeps the common case free of extra checks.
194
+ def request_with_value(req, value)
195
+ "#{req}#{value}#{TERMINATOR}"
196
+ rescue Encoding::CompatibilityError
197
+ "#{req.b}#{value.b}#{TERMINATOR}"
198
+ end
199
+
190
200
  # Delete Commands
191
201
  #
192
202
  # `options` supports the meta-delete keys :invalidate, :tombstone_ttl and
@@ -107,8 +107,9 @@ module Dalli
107
107
 
108
108
  def multi_meta_set(entries, ttl: nil, p_token: nil, l_token: nil)
109
109
  # Routing tokens apply to every entry in the batch, so the suffix is
110
- # built once rather than per entry.
111
- token_suffix = routing_tokens(p_token: p_token, l_token: l_token)
110
+ # built once rather than per entry. It's binary, like the buffer, so
111
+ # a token with non-ASCII characters doesn't turn the buffer UTF-8.
112
+ token_suffix = routing_tokens(p_token: p_token, l_token: l_token).b
112
113
  ttl = integer_flag(:ttl, ttl) if ttl
113
114
 
114
115
  buffer = ''.b
@@ -123,11 +124,29 @@ module Dalli
123
124
  buffer << ' b' if base64
124
125
  buffer << " F#{bitflags}" if bitflags
125
126
  buffer << " T#{ttl}" if ttl
126
- buffer << ' MS q' << token_suffix << TERMINATOR << value << TERMINATOR
127
+ buffer << ' MS q' << token_suffix << TERMINATOR
128
+ append_bytes(buffer, value)
129
+ buffer << TERMINATOR
127
130
  end
128
131
  buffer << META_NOOP
129
132
  end
130
133
 
134
+ # Values are appended as bytes. One batch can hold UTF-8 and binary
135
+ # values, which String#<< refuses to combine, and a raw value can be in
136
+ # an encoding that isn't ASCII-compatible, such as UTF-16.
137
+ # Don't chain on the result: TruffleRuby's append_as_bytes returns its
138
+ # arguments rather than the buffer.
139
+ if String.method_defined?(:append_as_bytes)
140
+ def append_bytes(buffer, value)
141
+ buffer.append_as_bytes(value)
142
+ end
143
+ else
144
+ def append_bytes(buffer, value)
145
+ buffer << (value.encoding == Encoding::BINARY ? value : value.b)
146
+ end
147
+ end
148
+ private :append_bytes
149
+
131
150
  # Thundering herd protection flag:
132
151
  # - stale (I flag): Instead of deleting the item, mark it as stale. Other clients
133
152
  # using N/R flags will see the X flag and know the item is being regenerated.
data/lib/dalli/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dalli
4
- VERSION = '5.1.7'
4
+ VERSION = '5.1.8'
5
5
 
6
6
  MIN_SUPPORTED_MEMCACHED_VERSION = '1.6.27'
7
7
  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: 5.1.7
4
+ version: 5.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter M. Goldstein