puma 4.3.0 → 4.3.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +23 -5
- data/ext/puma_http11/http11_parser.c +3 -1
- data/ext/puma_http11/http11_parser.rl +3 -1
- data/ext/puma_http11/puma_http11.c +1 -0
- data/lib/puma/app/status.rb +4 -2
- data/lib/puma/client.rb +10 -2
- data/lib/puma/const.rb +9 -1
- data/lib/puma/server.rb +54 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d378ab70a4eac21fe4bf571b95b655d6cbc590b2b91ac323f849986bf8f7ad6c
|
4
|
+
data.tar.gz: 1b288cc39f5d80119dde26e844490e572b5f1043060060a1a1d70180743123c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b63ddad40bdeae9c86d62af5bf044238e273cbf8e95ff944d7b0a736dd39532dfe3b562a77c97b14f86d8e3f916b7cb94ccdbf898e75c4088d075d20e83744d5
|
7
|
+
data.tar.gz: abc975210626407c096848540f068a9731ecdc5191327b3ad87355ef4b88b6ac2605ccc7e31ca5398cd787cf9a34efdffc501afe61a2542cc322768af7b26830
|
data/History.md
CHANGED
@@ -1,10 +1,28 @@
|
|
1
|
-
##
|
2
|
-
|
3
|
-
* Features
|
4
|
-
* Your feature goes here (#Github Number)
|
1
|
+
## 4.3.6 / 2020-09-05
|
5
2
|
|
6
3
|
* Bugfixes
|
7
|
-
*
|
4
|
+
* Explicitly include ctype.h to fix compilation warning and build error on macOS with Xcode 12 (#2304)
|
5
|
+
* Don't require json at boot (#2269)
|
6
|
+
|
7
|
+
## 4.3.4/4.3.5 and 3.12.5/3.12.6 / 2020-05-22
|
8
|
+
|
9
|
+
Each patchlevel release contains a separate security fix. We recommend simply upgrading to 4.3.5/3.12.6.
|
10
|
+
|
11
|
+
## 4.3.3 and 3.12.4 / 2020-02-28
|
12
|
+
* Bugfixes
|
13
|
+
* Fix: Fixes a problem where we weren't splitting headers correctly on newlines (#2132)
|
14
|
+
* Security
|
15
|
+
* Fix: Prevent HTTP Response splitting via CR in early hints.
|
16
|
+
|
17
|
+
## 4.3.2 and 3.12.3 / 2020-02-27
|
18
|
+
|
19
|
+
* Security
|
20
|
+
* Fix: Prevent HTTP Response splitting via CR/LF in header values. CVE-2020-5247.
|
21
|
+
|
22
|
+
## 4.3.1 and 3.12.2 / 2019-12-05
|
23
|
+
|
24
|
+
* Security
|
25
|
+
* Fix: a poorly-behaved client could use keepalive requests to monopolize Puma's reactor and create a denial of service attack. CVE-2019-16770.
|
8
26
|
|
9
27
|
## 4.3.0 / 2019-11-07
|
10
28
|
|
@@ -14,12 +14,14 @@
|
|
14
14
|
|
15
15
|
/*
|
16
16
|
* capitalizes all lower-case ASCII characters,
|
17
|
-
* converts dashes to underscores.
|
17
|
+
* converts dashes to underscores, and underscores to commas.
|
18
18
|
*/
|
19
19
|
static void snake_upcase_char(char *c)
|
20
20
|
{
|
21
21
|
if (*c >= 'a' && *c <= 'z')
|
22
22
|
*c &= ~0x20;
|
23
|
+
else if (*c == '_')
|
24
|
+
*c = ',';
|
23
25
|
else if (*c == '-')
|
24
26
|
*c = '_';
|
25
27
|
}
|
@@ -12,12 +12,14 @@
|
|
12
12
|
|
13
13
|
/*
|
14
14
|
* capitalizes all lower-case ASCII characters,
|
15
|
-
* converts dashes to underscores.
|
15
|
+
* converts dashes to underscores, and underscores to commas.
|
16
16
|
*/
|
17
17
|
static void snake_upcase_char(char *c)
|
18
18
|
{
|
19
19
|
if (*c >= 'a' && *c <= 'z')
|
20
20
|
*c &= ~0x20;
|
21
|
+
else if (*c == '_')
|
22
|
+
*c = ',';
|
21
23
|
else if (*c == '-')
|
22
24
|
*c = '_';
|
23
25
|
}
|
data/lib/puma/app/status.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'json'
|
4
|
-
|
5
3
|
module Puma
|
6
4
|
module App
|
7
5
|
# Check out {#call}'s source code to see what actions this web application
|
@@ -19,6 +17,10 @@ module Puma
|
|
19
17
|
return rack_response(403, 'Invalid auth token', 'text/plain')
|
20
18
|
end
|
21
19
|
|
20
|
+
if env['PATH_INFO'] =~ /\/(gc-stats|stats|thread-backtraces)$/
|
21
|
+
require 'json'
|
22
|
+
end
|
23
|
+
|
22
24
|
case env['PATH_INFO']
|
23
25
|
when /\/stop$/
|
24
26
|
@cli.stop
|
data/lib/puma/client.rb
CHANGED
@@ -285,8 +285,16 @@ module Puma
|
|
285
285
|
|
286
286
|
te = @env[TRANSFER_ENCODING2]
|
287
287
|
|
288
|
-
if te
|
289
|
-
|
288
|
+
if te
|
289
|
+
if te.include?(",")
|
290
|
+
te.split(",").each do |part|
|
291
|
+
if CHUNKED.casecmp(part.strip) == 0
|
292
|
+
return setup_chunked_body(body)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
elsif CHUNKED.casecmp(te) == 0
|
296
|
+
return setup_chunked_body(body)
|
297
|
+
end
|
290
298
|
end
|
291
299
|
|
292
300
|
@chunked_body = false
|
data/lib/puma/const.rb
CHANGED
@@ -100,7 +100,7 @@ module Puma
|
|
100
100
|
# too taxing on performance.
|
101
101
|
module Const
|
102
102
|
|
103
|
-
PUMA_VERSION = VERSION = "4.3.
|
103
|
+
PUMA_VERSION = VERSION = "4.3.6".freeze
|
104
104
|
CODE_NAME = "Mysterious Traveller".freeze
|
105
105
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
106
106
|
|
@@ -118,6 +118,13 @@ module Puma
|
|
118
118
|
# sending data back
|
119
119
|
WRITE_TIMEOUT = 10
|
120
120
|
|
121
|
+
# How many requests to attempt inline before sending a client back to
|
122
|
+
# the reactor to be subject to normal ordering. The idea here is that
|
123
|
+
# we amortize the cost of going back to the reactor for a well behaved
|
124
|
+
# but very "greedy" client across 10 requests. This prevents a not
|
125
|
+
# well behaved client from monopolizing the thread forever.
|
126
|
+
MAX_FAST_INLINE = 10
|
127
|
+
|
121
128
|
# The original URI requested by the client.
|
122
129
|
REQUEST_URI= 'REQUEST_URI'.freeze
|
123
130
|
REQUEST_PATH = 'REQUEST_PATH'.freeze
|
@@ -221,6 +228,7 @@ module Puma
|
|
221
228
|
COLON = ": ".freeze
|
222
229
|
|
223
230
|
NEWLINE = "\n".freeze
|
231
|
+
HTTP_INJECTION_REGEX = /[\r\n]/.freeze
|
224
232
|
|
225
233
|
HIJACK_P = "rack.hijack?".freeze
|
226
234
|
HIJACK = "rack.hijack".freeze
|
data/lib/puma/server.rb
CHANGED
@@ -466,6 +466,8 @@ module Puma
|
|
466
466
|
clean_thread_locals = @options[:clean_thread_locals]
|
467
467
|
close_socket = true
|
468
468
|
|
469
|
+
requests = 0
|
470
|
+
|
469
471
|
while true
|
470
472
|
case handle_request(client, buffer)
|
471
473
|
when false
|
@@ -479,7 +481,19 @@ module Puma
|
|
479
481
|
|
480
482
|
ThreadPool.clean_thread_locals if clean_thread_locals
|
481
483
|
|
482
|
-
|
484
|
+
requests += 1
|
485
|
+
|
486
|
+
check_for_more_data = @status == :run
|
487
|
+
|
488
|
+
if requests >= MAX_FAST_INLINE
|
489
|
+
# This will mean that reset will only try to use the data it already
|
490
|
+
# has buffered and won't try to read more data. What this means is that
|
491
|
+
# every client, independent of their request speed, gets treated like a slow
|
492
|
+
# one once every MAX_FAST_INLINE requests.
|
493
|
+
check_for_more_data = false
|
494
|
+
end
|
495
|
+
|
496
|
+
unless client.reset(check_for_more_data)
|
483
497
|
close_socket = false
|
484
498
|
client.set_timeout @persistent_timeout
|
485
499
|
@reactor.add client
|
@@ -643,6 +657,7 @@ module Puma
|
|
643
657
|
headers.each_pair do |k, vs|
|
644
658
|
if vs.respond_to?(:to_s) && !vs.to_s.empty?
|
645
659
|
vs.to_s.split(NEWLINE).each do |v|
|
660
|
+
next if possible_header_injection?(v)
|
646
661
|
fast_write client, "#{k}: #{v}\r\n"
|
647
662
|
end
|
648
663
|
else
|
@@ -657,6 +672,37 @@ module Puma
|
|
657
672
|
}
|
658
673
|
end
|
659
674
|
|
675
|
+
# Fixup any headers with , in the name to have _ now. We emit
|
676
|
+
# headers with , in them during the parse phase to avoid ambiguity
|
677
|
+
# with the - to _ conversion for critical headers. But here for
|
678
|
+
# compatibility, we'll convert them back. This code is written to
|
679
|
+
# avoid allocation in the common case (ie there are no headers
|
680
|
+
# with , in their names), that's why it has the extra conditionals.
|
681
|
+
|
682
|
+
to_delete = nil
|
683
|
+
to_add = nil
|
684
|
+
|
685
|
+
env.each do |k,v|
|
686
|
+
if k.start_with?("HTTP_") and k.include?(",") and k != "HTTP_TRANSFER,ENCODING"
|
687
|
+
if to_delete
|
688
|
+
to_delete << k
|
689
|
+
else
|
690
|
+
to_delete = [k]
|
691
|
+
end
|
692
|
+
|
693
|
+
unless to_add
|
694
|
+
to_add = {}
|
695
|
+
end
|
696
|
+
|
697
|
+
to_add[k.gsub(",", "_")] = v
|
698
|
+
end
|
699
|
+
end
|
700
|
+
|
701
|
+
if to_delete
|
702
|
+
to_delete.each { |k| env.delete(k) }
|
703
|
+
env.merge! to_add
|
704
|
+
end
|
705
|
+
|
660
706
|
# A rack extension. If the app writes #call'ables to this
|
661
707
|
# array, we will invoke them when the request is done.
|
662
708
|
#
|
@@ -744,6 +790,7 @@ module Puma
|
|
744
790
|
headers.each do |k, vs|
|
745
791
|
case k.downcase
|
746
792
|
when CONTENT_LENGTH2
|
793
|
+
next if possible_header_injection?(vs)
|
747
794
|
content_length = vs
|
748
795
|
next
|
749
796
|
when TRANSFER_ENCODING
|
@@ -756,6 +803,7 @@ module Puma
|
|
756
803
|
|
757
804
|
if vs.respond_to?(:to_s) && !vs.to_s.empty?
|
758
805
|
vs.to_s.split(NEWLINE).each do |v|
|
806
|
+
next if possible_header_injection?(v)
|
759
807
|
lines.append k, colon, v, line_ending
|
760
808
|
end
|
761
809
|
else
|
@@ -1026,5 +1074,10 @@ module Puma
|
|
1026
1074
|
def shutting_down?
|
1027
1075
|
@status == :stop || @status == :restart
|
1028
1076
|
end
|
1077
|
+
|
1078
|
+
def possible_header_injection?(header_value)
|
1079
|
+
HTTP_INJECTION_REGEX =~ header_value.to_s
|
1080
|
+
end
|
1081
|
+
private :possible_header_injection?
|
1029
1082
|
end
|
1030
1083
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.3.
|
4
|
+
version: 4.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nio4r
|
@@ -121,7 +121,7 @@ licenses:
|
|
121
121
|
metadata:
|
122
122
|
msys2_mingw_dependencies: openssl
|
123
123
|
changelog_uri: https://github.com/puma/puma/blob/master/History.md
|
124
|
-
post_install_message:
|
124
|
+
post_install_message:
|
125
125
|
rdoc_options: []
|
126
126
|
require_paths:
|
127
127
|
- lib
|
@@ -136,8 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
136
|
- !ruby/object:Gem::Version
|
137
137
|
version: '0'
|
138
138
|
requirements: []
|
139
|
-
rubygems_version: 3.
|
140
|
-
signing_key:
|
139
|
+
rubygems_version: 3.1.2
|
140
|
+
signing_key:
|
141
141
|
specification_version: 4
|
142
142
|
summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
|
143
143
|
Ruby/Rack applications
|