File CVE-2019-16770.patch of Package rubygem-puma.15815

commit 5481c73aac215432bd09451d02985b3f89eec85c
Author: Nate Berkopec <nate.berkopec@gmail.com>
Date:   Thu Dec 5 14:19:32 2019 +0700

    Merge pull request from GHSA-7xx3-m584-x994
    
    could monopolize a thread. Previously, this could make a DoS attack more
    severe.
    
    Co-authored-by: Evan Phoenix <evan@phx.io>
    (cherry picked from commit 06053e60908074bb38293d4449ea261cb009b53e)

diff --git a/lib/puma/const.rb b/lib/puma/const.rb
index d63d145db07c..f302dfd32b14 100644
--- a/lib/puma/const.rb
+++ b/lib/puma/const.rb
@@ -120,6 +120,13 @@ module Puma
 
     SCRIPT_NAME = "SCRIPT_NAME".freeze
 
+    # How many requests to attempt inline before sending a client back to
+    # the reactor to be subject to normal ordering. The idea here is that
+    # we amortize the cost of going back to the reactor for a well behaved
+    # but very "greedy" client across 10 requests. This prevents a not
+    # well behaved client from monopolizing the thread forever.
+    MAX_FAST_INLINE = 10
+
     # The original URI requested by the client.
     REQUEST_URI= 'REQUEST_URI'.freeze
     REQUEST_PATH = 'REQUEST_PATH'.freeze
diff --git a/lib/puma/server.rb b/lib/puma/server.rb
index 7ebe0eedfe7a..f6aa7e0024d1 100644
--- a/lib/puma/server.rb
+++ b/lib/puma/server.rb
@@ -400,6 +400,8 @@ module Puma
       begin
         close_socket = true
 
+        requests = 0
+
         while true
           case handle_request(client, buffer)
           when false
@@ -411,7 +413,19 @@ module Puma
             return unless @queue_requests
             buffer.reset
 
-            unless client.reset(@status == :run)
+            requests += 1
+
+            check_for_more_data = @status == :run
+
+            if requests >= MAX_FAST_INLINE
+              # This will mean that reset will only try to use the data it already
+              # has buffered and won't try to read more data. What this means is that
+              # every client, independent of their request speed, gets treated like a slow
+              # one once every MAX_FAST_INLINE requests.
+              check_for_more_data = false
+            end
+
+            unless client.reset(check_for_more_data)
               close_socket = false
               client.set_timeout @persistent_timeout
               @reactor.add client
openSUSE Build Service is sponsored by