Skip to content

v5.1.1

Latest

Choose a tag to compare

@petergoldstein petergoldstein released this 24 Sep 23:09
· 16 commits to main since this release
7bd7daf

Security release. Fixes GHSA-6wmv-xq9m-fmp7, a memcached command injection through numeric arguments. Upgrading is recommended.

Security:

  • Fix memcached command injection through numeric arguments (GHSA-6wmv-xq9m-fmp7)
    • The default argument of incr/decr, and fetch_with_lock's lock_ttl and recache_threshold, were written into the meta protocol command without conversion, so a String containing CRLF injected additional memcached commands (e.g. set, flush_all) on the connection
    • These arguments must now be Integers, or Strings of decimal digits; anything else raises ArgumentError before a request is sent
    • As defense in depth, RequestFormatter now converts every numeric flag it writes (D, J, N, R, T) to an Integer
    • Affects 3.2.0 and later (3.2.x only with protocol: :meta); fixed in 5.1.1 and 4.3.4
    • Thanks to oss-security-shop for the report

Performance:

  • Reduce Ruby overhead on the single-key get path by about 28% (#1160)
    • A plain get builds its mg request with one string interpolation instead of going through meta_get's keyword arguments, and skips option handling when called without options
    • A VA <size> f<flags> hit line is parsed in place instead of being split into tokens
    • The key check for control characters and whitespace uses a byte class that matches the same ASCII bytes as [\p{Cntrl}\s], about 5x faster; this applies to every operation that sends a key
    • Allocations per get hit drop from 23 to 16
    • Thanks to Julian Richard Contreras for this contribution
  • Speed up multi-server get_multi by about 30% (4 servers, 100 keys), and bring small batches in line with 2.7.11 (#1161)
    • Each server's queries and terminating noop are sent before the next server's are built, so memcached answers earlier servers while later ones are prepared
    • A server's queries are built in one pass with RequestFormatter.multi_meta_get, and plain get_multi no longer requests the CAS value it discards (get_multi_cas still does)
    • Pipelined replies are parsed in one pass over the returned flags
    • Routing many keys checks each server's alive? once per call instead of twice per key, and the ring's binary search runs over plain integers
    • Thanks to Julian Richard Contreras for this contribution

Development:

  • Fix offenses reported by RuboCop 1.91 and require rubocop >= 1.91 (#1162)
    • RuboCop 1.91 adds Style/DirectiveScope; single-statement disable/enable pairs become disable-next directives, which older RuboCop versions do not recognize
    • Removes a misplaced # encoding: ascii comment in client.rb that Ruby had always ignored