Hello community,

here is the log from the commit of package rubygem-rack for openSUSE:Leap:15.2 
checked in at 2020-06-06 15:47:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.2/rubygem-rack (Old)
 and      /work/SRC/openSUSE:Leap:15.2/.rubygem-rack.new.3606 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-rack"

Sat Jun  6 15:47:48 2020 rev:12 rq:771825 version:2.0.8

Changes:
--------
--- /work/SRC/openSUSE:Leap:15.2/rubygem-rack/rubygem-rack.changes      
2020-01-15 15:59:37.411804720 +0100
+++ /work/SRC/openSUSE:Leap:15.2/.rubygem-rack.new.3606/rubygem-rack.changes    
2020-06-06 15:47:49.163918197 +0200
@@ -1,0 +2,50 @@
+Thu Dec 19 08:55:14 UTC 2019 - David Kang <[email protected]>
+
+- updated to version 2.0.8
+  * CVE-2019-16782: Possible information leak / session hijack vulnerability
+
+-------------------------------------------------------------------
+Sat Apr  6 17:52:23 UTC 2019 - manuel <[email protected]>
+
+- updated to version 2.0.7
+
+  no changelog found
+
+-------------------------------------------------------------------
+Tue Nov  6 23:24:32 UTC 2018 - Marcus Rueckert <[email protected]>
+
+- update to 2.0.6:
+  * CVE-2018-16471: cross-site scripting (XSS) flaw via the scheme
+    method on Rack::Request (bsc#1114828)
+
+-------------------------------------------------------------------
+Mon Apr 23 18:18:04 UTC 2018 - [email protected]
+
+- updated to version 2.0.5
+ see installed HISTORY.md
+
+-------------------------------------------------------------------
+Mon Apr 16 15:47:33 UTC 2018 - [email protected]
+
+- Only build against ruby versions 2.3.x, 2.4.x, and 2.5.x
+- Fix package build by removing the executable bit for 'test.gz' file in gem
+
+-------------------------------------------------------------------
+Thu Feb  8 06:21:32 UTC 2018 - [email protected]
+
+- updated to version 2.0.4
+ see installed HISTORY.md
+
+-------------------------------------------------------------------
+Tue Oct 31 14:09:19 UTC 2017 - [email protected]
+
+- only build for 2.3+ from now
+
+-------------------------------------------------------------------
+Wed Jun  7 16:24:31 UTC 2017 - [email protected]
+
+- re-add the rb_build_versions and rb_default_ruby_abi as otherwise
+  building on older distros fails.
+- add ruby 2.4
+
+-------------------------------------------------------------------

Old:
----
  rack-2.0.3.gem

New:
----
  rack-2.0.8.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-rack.spec ++++++
--- /var/tmp/diff_new_pack.FECRmK/_old  2020-06-06 15:47:49.755920294 +0200
+++ /var/tmp/diff_new_pack.FECRmK/_new  2020-06-06 15:47:49.759920307 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-rack
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -12,7 +12,7 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
@@ -24,19 +24,24 @@
 #
 
 Name:           rubygem-rack
-Version:        2.0.3
+Version:        2.0.8
 Release:        0
 %define mod_name rack
 %define mod_full_name %{mod_name}-%{version}
 # MANUAL
 BuildRequires:  fdupes
+
+%if 0%{?suse_version} && 0%{?suse_version} < 1330
+%define rb_build_versions ruby23 ruby24 ruby25
+%define rb_build_ruby_abi ruby:2.3.0 ruby:2.4.0 ruby:2.5.0
+%endif
 # /MANUAL
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildRequires:  %{ruby >= 2.2.2}
 BuildRequires:  %{rubygem gem2rpm}
 BuildRequires:  ruby-macros >= 5
 BuildRequires:  update-alternatives
-Url:            http://rack.github.io/
+URL:            https://rack.github.io/
 Source:         https://rubygems.org/gems/%{mod_full_name}.gem
 Source1:        rubygem-rack-rpmlintrc
 Source2:        gem2rpm.yml
@@ -51,7 +56,7 @@
 the simplest way possible, it unifies and distills the API for web
 servers, web frameworks, and software in between (the so-called
 middleware) into a single method call.
-Also see http://rack.github.io/.
+Also see https://rack.github.io/.
 
 %prep
 
@@ -64,6 +69,7 @@
   -f
 # MANUAL
 %fdupes %{buildroot}%{_libdir}/ruby/gems/*/gems/%{mod_name}-%{version}/
+chmod 644 
%{buildroot}%{_libdir}/ruby/gems/*/gems/%{mod_name}-%{version}/test/cgi/test.gz
 # /MANUAL
 
 %gem_packages

++++++ gem2rpm.yml ++++++
--- /var/tmp/diff_new_pack.FECRmK/_old  2020-06-06 15:47:49.823920534 +0200
+++ /var/tmp/diff_new_pack.FECRmK/_new  2020-06-06 15:47:49.823920534 +0200
@@ -76,8 +76,12 @@
 
 :preamble: |-
   BuildRequires:  fdupes
-#  %define rb_build_versions ruby22 ruby23
-#  %define rb_default_ruby_abi ruby:2.2.0 ruby:2.3.0
+
+  %if 0%{?suse_version} && 0%{?suse_version} < 1330
+  %define rb_build_versions ruby23 ruby24 ruby25
+  %define rb_build_ruby_abi ruby:2.3.0 ruby:2.4.0 ruby:2.5.0
+  %endif
 
 :post_install: |-
   %fdupes %{buildroot}%{_libdir}/ruby/gems/*/gems/%{mod_name}-%{version}/
+  chmod 644 
%{buildroot}%{_libdir}/ruby/gems/*/gems/%{mod_name}-%{version}/test/cgi/test.gz

++++++ rack-2.0.3.gem -> rack-2.0.8.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/README.rdoc new/README.rdoc
--- old/README.rdoc     2017-05-15 18:49:44.000000000 +0200
+++ new/README.rdoc     2019-12-18 19:05:05.000000000 +0100
@@ -228,7 +228,7 @@
 
 The Rack Core Team, consisting of
 
-* Christian Neukirchen (chneukirchen[https://github.com/chneukirchen])
+* Leah Neukirchen (chneukirchen[https://github.com/chneukirchen])
 * James Tucker (raggi[https://github.com/raggi])
 * Josh Peek (josh[https://github.com/josh])
 * José Valim (josevalim[https://github.com/josevalim])
@@ -295,10 +295,8 @@
 
 == Links
 
-Rack:: <http://rack.github.io/>
+Rack:: <https://rack.github.io/>
 Official Rack repositories:: <https://github.com/rack>
 Rack Bug Tracking:: <https://github.com/rack/rack/issues>
 rack-devel mailing list:: <https://groups.google.com/group/rack-devel>
 Rack's Rubyforge project:: <http://rubyforge.org/projects/rack>
-
-Christian Neukirchen:: <http://chneukirchen.org/>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SPEC new/SPEC
--- old/SPEC    2017-05-15 18:49:44.000000000 +0200
+++ new/SPEC    2019-12-18 19:05:05.000000000 +0100
@@ -60,8 +60,8 @@
                            the presence or absence of the
                            appropriate HTTP header in the
                            request. See
-                           {https://tools.ietf.org/html/rfc3875#section-4.1.18
-                           RFC3875 section 4.1.18} for
+                           <a 
href="https://tools.ietf.org/html/rfc3875#section-4.1.18";>
+                           RFC3875 section 4.1.18</a> for
                            specific behavior.
 In addition to this, the Rack environment must include these
 Rack-specific variables:
@@ -98,12 +98,13 @@
 Additional environment specifications have approved to
 standardized middleware APIs.  None of these are required to
 be implemented by the server.
-<tt>rack.session</tt>:: A hash like interface for storing request session data.
+<tt>rack.session</tt>:: A hash like interface for storing
+                        request session data.
                         The store must implement:
-                         store(key, value)         (aliased as []=);
-                         fetch(key, default = nil) (aliased as []);
-                         delete(key);
-                         clear;
+                        store(key, value)         (aliased as []=);
+                        fetch(key, default = nil) (aliased as []);
+                        delete(key);
+                        clear;
 <tt>rack.logger</tt>:: A common object interface for logging messages.
                        The object must implement:
                         info(message, &block)
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/chunked.rb new/lib/rack/chunked.rb
--- old/lib/rack/chunked.rb     2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/chunked.rb     2019-12-18 19:05:05.000000000 +0100
@@ -24,7 +24,7 @@
           size = chunk.bytesize
           next if size == 0
 
-          chunk = chunk.dup.force_encoding(Encoding::BINARY)
+          chunk = chunk.b
           yield [size.to_s(16), term, chunk, term].join
         end
         yield TAIL
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/etag.rb new/lib/rack/etag.rb
--- old/lib/rack/etag.rb        2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/etag.rb        2019-12-18 19:05:05.000000000 +0100
@@ -1,5 +1,5 @@
 require 'rack'
-require 'digest/md5'
+require 'digest/sha2'
 
 module Rack
   # Automatically sets the ETag header on all String bodies.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/lock.rb new/lib/rack/lock.rb
--- old/lib/rack/lock.rb        2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/lock.rb        2019-12-18 19:05:05.000000000 +0100
@@ -11,12 +11,21 @@
 
     def call(env)
       @mutex.lock
+      @env = env
+      @old_rack_multithread = env[RACK_MULTITHREAD]
       begin
-        response = @app.call(env.merge(RACK_MULTITHREAD => false))
-        returned = response << BodyProxy.new(response.pop) { @mutex.unlock }
+        response = @app.call(env.merge!(RACK_MULTITHREAD => false))
+        returned = response << BodyProxy.new(response.pop) { unlock }
       ensure
-        @mutex.unlock unless returned
+        unlock unless returned
       end
     end
+
+    private
+
+    def unlock
+      @mutex.unlock
+      @env[RACK_MULTITHREAD] = @old_rack_multithread
+    end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/method_override.rb 
new/lib/rack/method_override.rb
--- old/lib/rack/method_override.rb     2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/method_override.rb     2019-12-18 19:05:05.000000000 +0100
@@ -26,7 +26,11 @@
       req = Request.new(env)
       method = method_override_param(req) ||
         env[HTTP_METHOD_OVERRIDE_HEADER]
-      method.to_s.upcase
+      begin
+        method.to_s.upcase
+      rescue ArgumentError
+        env[RACK_ERRORS].puts "Invalid string for method"
+      end
     end
 
     private
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/mock.rb new/lib/rack/mock.rb
--- old/lib/rack/mock.rb        2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/mock.rb        2019-12-18 19:05:05.000000000 +0100
@@ -128,7 +128,7 @@
         end
       end
 
-      empty_str = String.new.force_encoding(Encoding::ASCII_8BIT)
+      empty_str = String.new
       opts[:input] ||= empty_str
       if String === opts[:input]
         rack_input = StringIO.new(opts[:input])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/multipart/parser.rb 
new/lib/rack/multipart/parser.rb
--- old/lib/rack/multipart/parser.rb    2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/multipart/parser.rb    2019-12-18 19:05:05.000000000 +0100
@@ -39,8 +39,6 @@
           str
         end
 
-        def eof?; @content_length == @cursor; end
-
         def rewind
           @io.rewind
         end
@@ -65,11 +63,11 @@
         io = BoundedIO.new(io, content_length) if content_length
 
         parser = new(boundary, tmpfile, bufsize, qp)
-        parser.on_read io.read(bufsize), io.eof?
+        parser.on_read io.read(bufsize)
 
         loop do
           break if parser.state == :DONE
-          parser.on_read io.read(bufsize), io.eof?
+          parser.on_read io.read(bufsize)
         end
 
         io.rewind
@@ -135,7 +133,7 @@
             klass = TempfilePart
             @open_files += 1
           else
-            body = ''.force_encoding(Encoding::ASCII_8BIT)
+            body = String.new
             klass = BufferPart
           end
 
@@ -165,15 +163,15 @@
       attr_reader :state
 
       def initialize(boundary, tempfile, bufsize, query_parser)
-        @buf            = "".force_encoding(Encoding::ASCII_8BIT)
+        @buf            = String.new
 
         @query_parser   = query_parser
         @params         = query_parser.make_params
         @boundary       = "--#{boundary}"
-        @boundary_size  = @boundary.bytesize + EOL.size
         @bufsize        = bufsize
 
         @rx = /(?:#{EOL})?#{Regexp.quote(@boundary)}(#{EOL}|--)/n
+        @rx_max_size = EOL.size + @boundary.bytesize + [EOL.size, 
'--'.size].max
         @full_boundary = @boundary
         @end_boundary = @boundary + '--'
         @state = :FAST_FORWARD
@@ -181,8 +179,8 @@
         @collector = Collector.new tempfile
       end
 
-      def on_read content, eof
-        handle_empty_content!(content, eof)
+      def on_read content
+        handle_empty_content!(content)
         @buf << content
         run_parser
       end
@@ -263,15 +261,17 @@
       end
 
       def handle_mime_body
-        if @buf =~ rx
+        if i = @buf.index(rx)
           # Save the rest.
-          if i = @buf.index(rx)
-            @collector.on_mime_body @mime_index, @buf.slice!(0, i)
-            @buf.slice!(0, 2) # Remove \r\n after the content
-          end
+          @collector.on_mime_body @mime_index, @buf.slice!(0, i)
+          @buf.slice!(0, 2) # Remove \r\n after the content
           @state = :CONSUME_TOKEN
           @mime_index += 1
         else
+          # Save the read body part.
+          if @rx_max_size < @buf.size
+            @collector.on_mime_body @mime_index, @buf.slice!(0, @buf.size - 
@rx_max_size)
+          end
           :want_read
         end
       end
@@ -356,10 +356,9 @@
       end
 
 
-      def handle_empty_content!(content, eof)
+      def handle_empty_content!(content)
         if content.nil? || content.empty?
-          raise EOFError if eof
-          return true
+          raise EOFError
         end
       end
     end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/request.rb new/lib/rack/request.rb
--- old/lib/rack/request.rb     2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/request.rb     2019-12-18 19:05:05.000000000 +0100
@@ -11,6 +11,8 @@
   #   req.params["data"]
 
   class Request
+    SCHEME_WHITELIST = %w(https http).freeze
+
     def initialize(env)
       @params = nil
       super(env)
@@ -188,10 +190,8 @@
           'https'
         elsif get_header(HTTP_X_FORWARDED_SSL) == 'on'
           'https'
-        elsif get_header(HTTP_X_FORWARDED_SCHEME)
-          get_header(HTTP_X_FORWARDED_SCHEME)
-        elsif get_header(HTTP_X_FORWARDED_PROTO)
-          get_header(HTTP_X_FORWARDED_PROTO).split(',')[0]
+        elsif forwarded_scheme
+          forwarded_scheme
         else
           get_header(RACK_URL_SCHEME)
         end
@@ -261,7 +261,7 @@
 
         forwarded_ips = split_ip_addresses(get_header('HTTP_X_FORWARDED_FOR'))
 
-        return reject_trusted_ip_addresses(forwarded_ips).last || 
get_header("REMOTE_ADDR")
+        return reject_trusted_ip_addresses(forwarded_ips).last || 
forwarded_ips.first || get_header("REMOTE_ADDR")
       end
 
       # The media type (type/subtype) portion of the CONTENT_TYPE header
@@ -479,6 +479,19 @@
       def reject_trusted_ip_addresses(ip_addresses)
         ip_addresses.reject { |ip| trusted_proxy?(ip) }
       end
+
+      def forwarded_scheme
+        scheme_headers = [
+          get_header(HTTP_X_FORWARDED_SCHEME),
+          get_header(HTTP_X_FORWARDED_PROTO).to_s.split(',')[0]
+        ]
+
+        scheme_headers.each do |header|
+          return header if SCHEME_WHITELIST.include?(header)
+        end
+
+        nil
+      end
     end
 
     include Env
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/session/abstract/id.rb 
new/lib/rack/session/abstract/id.rb
--- old/lib/rack/session/abstract/id.rb 2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/session/abstract/id.rb 2019-12-18 19:05:05.000000000 +0100
@@ -6,11 +6,38 @@
 require 'rack/request'
 require 'rack/response'
 require 'securerandom'
+require 'digest/sha2'
 
 module Rack
 
   module Session
 
+    class SessionId
+      ID_VERSION = 2
+
+      attr_reader :public_id
+
+      def initialize(public_id)
+        @public_id = public_id
+      end
+
+      def private_id
+        "#{ID_VERSION}::#{hash_sid(public_id)}"
+      end
+
+      alias :cookie_value :public_id
+
+      def empty?; false; end
+      def to_s; raise; end
+      def inspect; public_id.inspect; end
+
+      private
+
+      def hash_sid(sid)
+        Digest::SHA256.hexdigest(sid)
+      end
+    end
+
     module Abstract
       # SessionHash is responsible to lazily load the session from store.
 
@@ -357,7 +384,7 @@
             req.get_header(RACK_ERRORS).puts("Deferring cookie for 
#{session_id}") if $VERBOSE
           else
             cookie = Hash.new
-            cookie[:value] = data
+            cookie[:value] = cookie_value(data)
             cookie[:expires] = Time.now + options[:expire_after] if 
options[:expire_after]
             cookie[:expires] = Time.now + options[:max_age] if 
options[:max_age]
             set_cookie(req, res, cookie.merge!(options))
@@ -365,6 +392,10 @@
         end
         public :commit_session
 
+        def cookie_value(data)
+          data
+        end
+
         # Sets the cookie back to the client with session id. We skip the 
cookie
         # setting if the value didn't change (sid is the same) or expires was 
given.
 
@@ -406,6 +437,40 @@
         end
       end
 
+      class PersistedSecure < Persisted
+        class SecureSessionHash < SessionHash
+          def [](key)
+            if key == "session_id"
+              load_for_read!
+              id.public_id
+            else
+              super
+            end
+          end
+        end
+
+        def generate_sid(*)
+          public_id = super
+
+          SessionId.new(public_id)
+        end
+
+        def extract_session_id(*)
+          public_id = super
+          public_id && SessionId.new(public_id)
+        end
+
+        private
+
+        def session_class
+          SecureSessionHash
+        end
+
+        def cookie_value(data)
+          data.cookie_value
+        end
+      end
+
       class ID < Persisted
         def self.inherited(klass)
           k = klass.ancestors.find { |kl| kl.respond_to?(:superclass) && 
kl.superclass == ID }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/session/cookie.rb 
new/lib/rack/session/cookie.rb
--- old/lib/rack/session/cookie.rb      2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/session/cookie.rb      2019-12-18 19:05:05.000000000 +0100
@@ -45,7 +45,7 @@
     #   })
     #
 
-    class Cookie < Abstract::Persisted
+    class Cookie < Abstract::PersistedSecure
       # Encode session cookies as Base64
       class Base64
         def encode(str)
@@ -153,6 +153,15 @@
         data
       end
 
+      class SessionId < DelegateClass(Session::SessionId)
+        attr_reader :cookie_value
+
+        def initialize(session_id, cookie_value)
+          super(session_id)
+          @cookie_value = cookie_value
+        end
+      end
+
       def write_session(req, session_id, session, options)
         session = session.merge("session_id" => session_id)
         session_data = coder.encode(session)
@@ -165,7 +174,7 @@
           req.get_header(RACK_ERRORS).puts("Warning! Rack::Session::Cookie 
data size exceeds 4K.")
           nil
         else
-          session_data
+          SessionId.new(session_id, session_data)
         end
       end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/session/memcache.rb 
new/lib/rack/session/memcache.rb
--- old/lib/rack/session/memcache.rb    2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/session/memcache.rb    2019-12-18 19:05:05.000000000 +0100
@@ -19,7 +19,7 @@
     # Note that memcache does drop data before it may be listed to expire. For
     # a full description of behaviour, please see memcache's documentation.
 
-    class Memcache < Abstract::ID
+    class Memcache < Abstract::PersistedSecure
       attr_reader :mutex, :pool
 
       DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge \
@@ -42,15 +42,15 @@
       def generate_sid
         loop do
           sid = super
-          break sid unless @pool.get(sid, true)
+          break sid unless @pool.get(sid.private_id, true)
         end
       end
 
-      def get_session(env, sid)
-        with_lock(env) do
-          unless sid and session = @pool.get(sid)
+      def find_session(req, sid)
+        with_lock(req) do
+          unless sid and session = get_session_with_fallback(sid)
             sid, session = generate_sid, {}
-            unless /^STORED/ =~ @pool.add(sid, session)
+            unless /^STORED/ =~ @pool.add(sid.private_id, session)
               raise "Session collision on '#{sid.inspect}'"
             end
           end
@@ -58,25 +58,26 @@
         end
       end
 
-      def set_session(env, session_id, new_session, options)
+      def write_session(req, session_id, new_session, options)
         expiry = options[:expire_after]
         expiry = expiry.nil? ? 0 : expiry + 1
 
-        with_lock(env) do
-          @pool.set session_id, new_session, expiry
+        with_lock(req) do
+          @pool.set session_id.private_id, new_session, expiry
           session_id
         end
       end
 
-      def destroy_session(env, session_id, options)
-        with_lock(env) do
-          @pool.delete(session_id)
+      def delete_session(req, session_id, options)
+        with_lock(req) do
+          @pool.delete(session_id.public_id)
+          @pool.delete(session_id.private_id)
           generate_sid unless options[:drop]
         end
       end
 
-      def with_lock(env)
-        @mutex.lock if env[RACK_MULTITHREAD]
+      def with_lock(req)
+        @mutex.lock if req.multithread?
         yield
       rescue MemCache::MemCacheError, Errno::ECONNREFUSED
         if $VERBOSE
@@ -88,6 +89,11 @@
         @mutex.unlock if @mutex.locked?
       end
 
+      private
+
+      def get_session_with_fallback(sid)
+        @pool.get(sid.private_id) || @pool.get(sid.public_id)
+      end
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/session/pool.rb new/lib/rack/session/pool.rb
--- old/lib/rack/session/pool.rb        2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/session/pool.rb        2019-12-18 19:05:05.000000000 +0100
@@ -24,7 +24,7 @@
     #   )
     #   Rack::Handler::WEBrick.run sessioned
 
-    class Pool < Abstract::Persisted
+    class Pool < Abstract::PersistedSecure
       attr_reader :mutex, :pool
       DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge :drop => false
 
@@ -37,15 +37,15 @@
       def generate_sid
         loop do
           sid = super
-          break sid unless @pool.key? sid
+          break sid unless @pool.key? sid.private_id
         end
       end
 
       def find_session(req, sid)
         with_lock(req) do
-          unless sid and session = @pool[sid]
+          unless sid and session = get_session_with_fallback(sid)
             sid, session = generate_sid, {}
-            @pool.store sid, session
+            @pool.store sid.private_id, session
           end
           [sid, session]
         end
@@ -53,14 +53,15 @@
 
       def write_session(req, session_id, new_session, options)
         with_lock(req) do
-          @pool.store session_id, new_session
+          @pool.store session_id.private_id, new_session
           session_id
         end
       end
 
       def delete_session(req, session_id, options)
         with_lock(req) do
-          @pool.delete(session_id)
+          @pool.delete(session_id.public_id)
+          @pool.delete(session_id.private_id)
           generate_sid unless options[:drop]
         end
       end
@@ -71,6 +72,12 @@
       ensure
         @mutex.unlock if @mutex.locked?
       end
+
+      private
+
+      def get_session_with_fallback(sid)
+        @pool[sid.private_id] || @pool[sid.public_id]
+      end
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/show_exceptions.rb 
new/lib/rack/show_exceptions.rb
--- old/lib/rack/show_exceptions.rb     2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack/show_exceptions.rb     2019-12-18 19:05:05.000000000 +0100
@@ -46,7 +46,7 @@
     end
 
     def prefers_plaintext?(env)
-      !accepts_html(env)
+      !accepts_html?(env)
     end
 
     def accepts_html?(env)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack.rb new/lib/rack.rb
--- old/lib/rack.rb     2017-05-15 18:49:44.000000000 +0200
+++ new/lib/rack.rb     2019-12-18 19:05:05.000000000 +0100
@@ -18,7 +18,7 @@
     VERSION.join(".")
   end
 
-  RELEASE = "2.0.3"
+  RELEASE = "2.0.8"
 
   # Return the Rack release as a dotted string.
   def self.release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2017-05-15 18:49:44.000000000 +0200
+++ new/metadata        2019-12-18 19:05:05.000000000 +0100
@@ -1,14 +1,14 @@
 --- !ruby/object:Gem::Specification
 name: rack
 version: !ruby/object:Gem::Version
-  version: 2.0.3
+  version: 2.0.8
 platform: ruby
 authors:
-- Christian Neukirchen
+- Leah Neukirchen
 autorequire: 
 bindir: bin
 cert_chain: []
-date: 2017-05-15 00:00:00.000000000 Z
+date: 2019-12-18 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: minitest
@@ -39,20 +39,6 @@
       - !ruby/object:Gem::Version
         version: '0'
 - !ruby/object:Gem::Dependency
-  name: concurrent-ruby
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
   name: rake
   requirement: !ruby/object:Gem::Requirement
     requirements:
@@ -73,8 +59,8 @@
   servers, web frameworks, and software in between (the so-called
   middleware) into a single method call.
 
-  Also see http://rack.github.io/.
-email: [email protected]
+  Also see https://rack.github.io/.
+email: [email protected]
 executables:
 - rackup
 extensions: []
@@ -269,7 +255,7 @@
 - test/testrequest.rb
 - test/unregistered_handler/rack/handler/unregistered.rb
 - test/unregistered_handler/rack/handler/unregistered_long_one.rb
-homepage: http://rack.github.io/
+homepage: https://rack.github.io/
 licenses:
 - MIT
 metadata: {}
@@ -288,60 +274,59 @@
     - !ruby/object:Gem::Version
       version: '0'
 requirements: []
-rubyforge_project: 
-rubygems_version: 2.6.8
+rubygems_version: 3.0.3
 signing_key: 
 specification_version: 4
 summary: a modular Ruby webserver interface
 test_files:
-- test/spec_auth_basic.rb
-- test/spec_auth_digest.rb
-- test/spec_body_proxy.rb
-- test/spec_builder.rb
-- test/spec_cascade.rb
-- test/spec_cgi.rb
-- test/spec_chunked.rb
-- test/spec_common_logger.rb
-- test/spec_conditional_get.rb
-- test/spec_config.rb
-- test/spec_content_length.rb
-- test/spec_content_type.rb
+- test/spec_multipart.rb
 - test/spec_deflater.rb
-- test/spec_directory.rb
+- test/spec_static.rb
+- test/spec_session_cookie.rb
+- test/spec_session_pool.rb
 - test/spec_etag.rb
-- test/spec_events.rb
-- test/spec_fastcgi.rb
-- test/spec_file.rb
+- test/spec_version.rb
 - test/spec_handler.rb
-- test/spec_head.rb
-- test/spec_lint.rb
-- test/spec_lobster.rb
-- test/spec_lock.rb
-- test/spec_logger.rb
-- test/spec_media_type.rb
-- test/spec_method_override.rb
+- test/spec_thin.rb
+- test/spec_session_abstract_id.rb
 - test/spec_mime.rb
-- test/spec_mock.rb
-- test/spec_multipart.rb
-- test/spec_null_logger.rb
 - test/spec_recursive.rb
+- test/spec_null_logger.rb
+- test/spec_media_type.rb
+- test/spec_cgi.rb
+- test/spec_method_override.rb
+- test/spec_content_type.rb
+- test/spec_session_abstract_session_hash.rb
 - test/spec_request.rb
-- test/spec_response.rb
-- test/spec_rewindable_input.rb
+- test/spec_chunked.rb
+- test/spec_show_exceptions.rb
 - test/spec_runtime.rb
+- test/spec_fastcgi.rb
+- test/spec_common_logger.rb
+- test/spec_builder.rb
+- test/spec_config.rb
+- test/spec_utils.rb
 - test/spec_sendfile.rb
+- test/spec_lobster.rb
+- test/spec_lint.rb
+- test/spec_conditional_get.rb
+- test/spec_tempfile_reaper.rb
+- test/spec_mock.rb
 - test/spec_server.rb
-- test/spec_session_abstract_id.rb
-- test/spec_session_abstract_session_hash.rb
-- test/spec_session_cookie.rb
-- test/spec_session_memcache.rb
-- test/spec_session_pool.rb
-- test/spec_show_exceptions.rb
+- test/spec_directory.rb
+- test/spec_webrick.rb
+- test/spec_response.rb
+- test/spec_file.rb
 - test/spec_show_status.rb
-- test/spec_static.rb
-- test/spec_tempfile_reaper.rb
-- test/spec_thin.rb
+- test/spec_body_proxy.rb
+- test/spec_logger.rb
+- test/spec_auth_digest.rb
 - test/spec_urlmap.rb
-- test/spec_utils.rb
-- test/spec_version.rb
-- test/spec_webrick.rb
+- test/spec_events.rb
+- test/spec_cascade.rb
+- test/spec_auth_basic.rb
+- test/spec_head.rb
+- test/spec_lock.rb
+- test/spec_rewindable_input.rb
+- test/spec_session_memcache.rb
+- test/spec_content_length.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rack.gemspec new/rack.gemspec
--- old/rack.gemspec    2017-05-15 18:49:44.000000000 +0200
+++ new/rack.gemspec    2019-12-18 19:05:05.000000000 +0100
@@ -12,7 +12,7 @@
 servers, web frameworks, and software in between (the so-called
 middleware) into a single method call.
 
-Also see http://rack.github.io/.
+Also see https://rack.github.io/.
 EOF
 
   s.files           = Dir['{bin/*,contrib/*,example/*,lib/**/*,test/**/*}'] +
@@ -23,13 +23,12 @@
   s.extra_rdoc_files = ['README.rdoc', 'HISTORY.md']
   s.test_files      = Dir['test/spec_*.rb']
 
-  s.author          = 'Christian Neukirchen'
-  s.email           = '[email protected]'
-  s.homepage        = 'http://rack.github.io/'
+  s.author          = 'Leah Neukirchen'
+  s.email           = '[email protected]'
+  s.homepage        = 'https://rack.github.io/'
   s.required_ruby_version = '>= 2.2.2'
 
   s.add_development_dependency 'minitest', "~> 5.0"
   s.add_development_dependency 'minitest-sprint'
-  s.add_development_dependency 'concurrent-ruby'
   s.add_development_dependency 'rake'
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/spec_lock.rb new/test/spec_lock.rb
--- old/test/spec_lock.rb       2017-05-15 18:49:44.000000000 +0200
+++ new/test/spec_lock.rb       2019-12-18 19:05:05.000000000 +0100
@@ -147,7 +147,8 @@
     }, false)
     env = Rack::MockRequest.env_for("/")
     env['rack.multithread'].must_equal true
-    app.call(env)
+    _, _, body = app.call(env)
+    body.close
     env['rack.multithread'].must_equal true
   end
 
@@ -191,4 +192,13 @@
     lambda { app.call(env) }.must_raise Exception
     lock.synchronized.must_equal false
   end
+
+  it "not replace the environment" do
+    env  = Rack::MockRequest.env_for("/")
+    app  = lock_app(lambda { |inner_env| [200, {"Content-Type" => 
"text/plain"}, [inner_env.object_id.to_s]] })
+
+    _, _, body = app.call(env)
+
+    body.to_enum.to_a.must_equal [env.object_id.to_s]
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/spec_method_override.rb 
new/test/spec_method_override.rb
--- old/test/spec_method_override.rb    2017-05-15 18:49:44.000000000 +0200
+++ new/test/spec_method_override.rb    2019-12-18 19:05:05.000000000 +0100
@@ -17,6 +17,20 @@
     env["REQUEST_METHOD"].must_equal "GET"
   end
 
+  it "sets rack.errors for invalid UTF8 _method values" do
+    errors = StringIO.new
+    env = Rack::MockRequest.env_for("/",
+      :method => "POST",
+      :input => "_method=\xBF".b,
+      Rack::RACK_ERRORS => errors)
+
+    app.call env
+
+    errors.rewind
+    errors.read.must_equal "Invalid string for method\n"
+    env["REQUEST_METHOD"].must_equal "POST"
+  end
+
   it "modify REQUEST_METHOD for POST requests when _method parameter is set" do
     env = Rack::MockRequest.env_for("/", :method => "POST", :input => 
"_method=put")
     app.call env
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/spec_request.rb new/test/spec_request.rb
--- old/test/spec_request.rb    2017-05-15 18:49:44.000000000 +0200
+++ new/test/spec_request.rb    2019-12-18 19:05:05.000000000 +0100
@@ -572,6 +572,11 @@
     request.must_be :ssl?
   end
 
+  it "prevents scheme abuse" do
+    request = make_request(Rack::MockRequest.env_for("/", 
'HTTP_X_FORWARDED_SCHEME' => 'a."><script>alert(1)</script>'))
+    request.scheme.must_equal 'http'
+  end
+
   it "parse cookies" do
     req = make_request \
       Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
@@ -1281,7 +1286,16 @@
     res.body.must_equal '2.2.2.3'
   end
 
-  it "regard local addresses as proxies" do
+  it "preserves ip for trusted proxy chain" do
+    mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
+    res = mock.get '/',
+      'HTTP_X_FORWARDED_FOR' => '192.168.0.11, 192.168.0.7',
+      'HTTP_CLIENT_IP' => '127.0.0.1'
+    res.body.must_equal '192.168.0.11'
+
+  end
+
+  it "regards local addresses as proxies" do
     req = make_request(Rack::MockRequest.env_for("/"))
     req.trusted_proxy?('127.0.0.1').must_equal 0
     req.trusted_proxy?('10.0.0.1').must_equal 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/spec_session_memcache.rb 
new/test/spec_session_memcache.rb
--- old/test/spec_session_memcache.rb   2017-05-15 18:49:44.000000000 +0200
+++ new/test/spec_session_memcache.rb   2019-12-18 19:05:05.000000000 +0100
@@ -226,15 +226,52 @@
       req = Rack::MockRequest.new(pool)
 
       res0 = req.get("/")
-      session_id = (cookie = res0["Set-Cookie"])[session_match, 1]
-      ses0 = pool.pool.get(session_id, true)
+      session_id = Rack::Session::SessionId.new (cookie = 
res0["Set-Cookie"])[session_match, 1]
+      ses0 = pool.pool.get(session_id.private_id, true)
 
       req.get("/", "HTTP_COOKIE" => cookie)
-      ses1 = pool.pool.get(session_id, true)
+      ses1 = pool.pool.get(session_id.private_id, true)
 
       ses1.wont_equal ses0
     end
 
+    it "can read the session with the legacy id" do
+      pool = Rack::Session::Memcache.new(incrementor)
+      req = Rack::MockRequest.new(pool)
+
+      res0 = req.get("/")
+      cookie = res0["Set-Cookie"]
+      session_id = Rack::Session::SessionId.new cookie[session_match, 1]
+      ses0 = pool.pool.get(session_id.private_id, true)
+      pool.pool.set(session_id.public_id, ses0, 0, true)
+      pool.pool.delete(session_id.private_id)
+
+      res1 = req.get("/", "HTTP_COOKIE" => cookie)
+      res1["Set-Cookie"].must_be_nil
+      res1.body.must_equal '{"counter"=>2}'
+      pool.pool.get(session_id.private_id, true).wont_be_nil
+    end
+
+    it "drops the session in the legacy id as well" do
+      pool = Rack::Session::Memcache.new(incrementor)
+      req = Rack::MockRequest.new(pool)
+      drop = Rack::Utils::Context.new(pool, drop_session)
+      dreq = Rack::MockRequest.new(drop)
+
+      res0 = req.get("/")
+      cookie = res0["Set-Cookie"]
+      session_id = Rack::Session::SessionId.new cookie[session_match, 1]
+      ses0 = pool.pool.get(session_id.private_id, true)
+      pool.pool.set(session_id.public_id, ses0, 0, true)
+      pool.pool.delete(session_id.private_id)
+
+      res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
+      res2["Set-Cookie"].must_be_nil
+      res2.body.must_equal '{"counter"=>2}'
+      pool.pool.get(session_id.private_id, true).must_be_nil
+      pool.pool.get(session_id.public_id, true).must_be_nil
+    end
+
     # anyone know how to do this better?
     it "cleanly merges sessions when multithreaded" do
       skip unless $DEBUG
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/spec_session_pool.rb 
new/test/spec_session_pool.rb
--- old/test/spec_session_pool.rb       2017-05-15 18:49:45.000000000 +0200
+++ new/test/spec_session_pool.rb       2019-12-18 19:05:05.000000000 +0100
@@ -6,7 +6,7 @@
 
 describe Rack::Session::Pool do
   session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key]
-  session_match = /#{session_key}=[0-9a-fA-F]+;/
+  session_match = /#{session_key}=([0-9a-fA-F]+);/
 
   incrementor = lambda do |env|
     env["rack.session"]["counter"] ||= 0
@@ -14,7 +14,7 @@
     Rack::Response.new(env["rack.session"].inspect).to_a
   end
 
-  session_id = Rack::Lint.new(lambda do |env|
+  get_session_id = Rack::Lint.new(lambda do |env|
     Rack::Response.new(env["rack.session"].inspect).to_a
   end)
 
@@ -143,6 +143,43 @@
     pool.pool.size.must_equal 1
   end
 
+  it "can read the session with the legacy id" do
+    pool = Rack::Session::Pool.new(incrementor)
+    req = Rack::MockRequest.new(pool)
+
+    res0 = req.get("/")
+    cookie = res0["Set-Cookie"]
+    session_id = Rack::Session::SessionId.new cookie[session_match, 1]
+    ses0 = pool.pool[session_id.private_id]
+    pool.pool[session_id.public_id] = ses0
+    pool.pool.delete(session_id.private_id)
+
+    res1 = req.get("/", "HTTP_COOKIE" => cookie)
+    res1["Set-Cookie"].must_be_nil
+    res1.body.must_equal '{"counter"=>2}'
+    pool.pool[session_id.private_id].wont_be_nil
+  end
+
+  it "drops the session in the legacy id as well" do
+    pool = Rack::Session::Pool.new(incrementor)
+    req = Rack::MockRequest.new(pool)
+    drop = Rack::Utils::Context.new(pool, drop_session)
+    dreq = Rack::MockRequest.new(drop)
+
+    res0 = req.get("/")
+    cookie = res0["Set-Cookie"]
+    session_id = Rack::Session::SessionId.new cookie[session_match, 1]
+    ses0 = pool.pool[session_id.private_id]
+    pool.pool[session_id.public_id] = ses0
+    pool.pool.delete(session_id.private_id)
+
+    res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
+    res2["Set-Cookie"].must_be_nil
+    res2.body.must_equal '{"counter"=>2}'
+    pool.pool[session_id.private_id].must_be_nil
+    pool.pool[session_id.public_id].must_be_nil
+  end
+
   # anyone know how to do this better?
   it "should merge sessions when multithreaded" do
     unless $DEBUG
@@ -191,7 +228,7 @@
   end
 
   it "does not return a cookie if cookie was not written (only read)" do
-    app = Rack::Session::Pool.new(session_id)
+    app = Rack::Session::Pool.new(get_session_id)
     res = Rack::MockRequest.new(app).get("/")
     res["Set-Cookie"].must_be_nil
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/spec_show_exceptions.rb 
new/test/spec_show_exceptions.rb
--- old/test/spec_show_exceptions.rb    2017-05-15 18:49:45.000000000 +0200
+++ new/test/spec_show_exceptions.rb    2019-12-18 19:05:05.000000000 +0100
@@ -77,4 +77,17 @@
     assert_match(res, /ShowExceptions/)
     assert_match(res, /unknown location/)
   end
+
+  it "knows to prefer plaintext for non-html" do
+    # We don't need an app for this
+    exc = Rack::ShowExceptions.new(nil)
+
+    [
+      [{ "HTTP_ACCEPT" => "text/plain" }, true],
+      [{ "HTTP_ACCEPT" => "text/foo" }, true],
+      [{ "HTTP_ACCEPT" => "text/html" }, false]
+    ].each do |env, expected|
+      assert_equal(expected, exc.prefers_plaintext?(env))
+    end
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/spec_webrick.rb new/test/spec_webrick.rb
--- old/test/spec_webrick.rb    2017-05-15 18:49:45.000000000 +0200
+++ new/test/spec_webrick.rb    2019-12-18 19:05:05.000000000 +0100
@@ -1,7 +1,6 @@
 require 'minitest/autorun'
 require 'rack/mock'
-require 'concurrent/utility/native_integer'
-require 'concurrent/atomic/count_down_latch'
+require 'thread'
 require File.expand_path('../testrequest', __FILE__)
 
 Thread.abort_on_exception = true
@@ -120,8 +119,7 @@
   end
 
   it "provide a .run" do
-    block_ran = false
-    latch = Concurrent::CountDownLatch.new 1
+    queue = Queue.new
 
     t = Thread.new do
       Rack::Handler::WEBrick.run(lambda {},
@@ -132,13 +130,12 @@
                                    :AccessLog => []}) { |server|
         block_ran = true
         assert_kind_of WEBrick::HTTPServer, server
-        @s = server
-        latch.count_down
+        queue.push(server)
       }
     end
 
-    latch.wait
-    @s.shutdown
+    server = queue.pop
+    server.shutdown
     t.join
   end
 


Reply via email to