puma 4.3.3 → 4.3.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd20b1ca1b6236f1b1677f9bc40f4ea8f980ae678e1f57e6b20987d2322f7f4a
4
- data.tar.gz: bb416036092bb4657a4f30dda5c72dc6a9ff8dda391e41950f7ece18230a4a5f
3
+ metadata.gz: 0133cf43153c495af4daa489fd6db234a14fb0d7b72201b71260d4d57dfb1211
4
+ data.tar.gz: a1a369772eaf8e3e0efa2931c4cdfdc1880314540c260d6c01226f4b0fd2a863
5
5
  SHA512:
6
- metadata.gz: d6ce2871efeed834b717174a744ac45db359efd9969efb51b13a83f260d01def32d25fe3ac91a9a0f99483c054c89f4c40aaef988e2a7b46cb9cb54201200abc
7
- data.tar.gz: c55618f49982d8c1a9161a4b8bce15878b75b960c9a28fb49c81d8934336c22023608082ba649414767d67a59436d580a12719660fa8710174dcb59823bb935d
6
+ metadata.gz: 6dfe3a8aa4e40676eb2c70822dac050c75f9bf9ec5270626e2b282a5971f323b2661d5792a4d24982e236f378a13ddf8408080e18bf7f4957cfd5971a7d8d034
7
+ data.tar.gz: 95706c08d6b746d82af99474001664b282bf760fbbef14860b5e6897dd4eaedc3f4b49a5da2a1809dcfcf0a23fe5f62baabe5da88c631c8228889c615248fe03
data/History.md CHANGED
@@ -1,11 +1,23 @@
1
- ## Master
1
+ ## 4.3.8 / 2021-05-11
2
2
 
3
- * Features
4
- * Your feature goes here (#Github Number)
3
+ * Security
4
+ * Close keepalive connections after the maximum number of fast inlined requests (#2625)
5
+
6
+ ## 4.3.7 / 2020-11-30
5
7
 
6
8
  * Bugfixes
7
- * Your bugfix goes here (#Github Number)
9
+ * Backport set CONTENT_LENGTH for chunked requests (Originally: #2287, backport: #2496)
10
+
11
+ ## 4.3.6 / 2020-09-05
12
+
13
+ * Bugfixes
14
+ * Explicitly include ctype.h to fix compilation warning and build error on macOS with Xcode 12 (#2304)
15
+ * Don't require json at boot (#2269)
16
+ * Set `CONTENT_LENGTH` for chunked requests (#2287)
17
+
18
+ ## 4.3.4/4.3.5 and 3.12.5/3.12.6 / 2020-05-22
8
19
 
20
+ Each patchlevel release contains a separate security fix. We recommend simply upgrading to 4.3.5/3.12.6.
9
21
 
10
22
  ## 4.3.3 and 3.12.4 / 2020-02-28
11
23
  * Bugfixes
@@ -1,7 +1,7 @@
1
1
  require 'mkmf'
2
2
 
3
3
  dir_config("puma_http11")
4
- if RUBY_PLATFORM[/mingw32/]
4
+ if $mingw && RUBY_VERSION >= '2.4'
5
5
  append_cflags '-D_FORTIFY_SOURCE=2'
6
6
  append_ldflags '-fstack-protector'
7
7
  have_library 'ssp'
@@ -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
  }
@@ -10,6 +10,7 @@
10
10
  #include "ext_help.h"
11
11
  #include <assert.h>
12
12
  #include <string.h>
13
+ #include <ctype.h>
13
14
  #include "http11_parser.h"
14
15
 
15
16
  #ifndef MANAGED_STRINGS
@@ -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
@@ -153,7 +153,7 @@ module Puma
153
153
 
154
154
  begin
155
155
  data = @io.read_nonblock(CHUNK_SIZE)
156
- rescue Errno::EAGAIN
156
+ rescue IO::WaitReadable
157
157
  return false
158
158
  rescue SystemCallError, IOError, EOFError
159
159
  raise ConnectionError, "Connection error detected during read"
@@ -285,8 +285,16 @@ module Puma
285
285
 
286
286
  te = @env[TRANSFER_ENCODING2]
287
287
 
288
- if te && CHUNKED.casecmp(te) == 0
289
- return setup_chunked_body(body)
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
@@ -343,7 +351,7 @@ module Puma
343
351
 
344
352
  begin
345
353
  chunk = @io.read_nonblock(want)
346
- rescue Errno::EAGAIN
354
+ rescue IO::WaitReadable
347
355
  return false
348
356
  rescue SystemCallError, IOError
349
357
  raise ConnectionError, "Connection error detected during read"
@@ -389,7 +397,10 @@ module Puma
389
397
  raise EOFError
390
398
  end
391
399
 
392
- return true if decode_chunk(chunk)
400
+ if decode_chunk(chunk)
401
+ @env[CONTENT_LENGTH] = @chunked_content_length
402
+ return true
403
+ end
393
404
  end
394
405
  end
395
406
 
@@ -402,19 +413,28 @@ module Puma
402
413
  @body.binmode
403
414
  @tempfile = @body
404
415
 
405
- return decode_chunk(body)
416
+ @chunked_content_length = 0
417
+
418
+ if decode_chunk(body)
419
+ @env[CONTENT_LENGTH] = @chunked_content_length
420
+ return true
421
+ end
422
+ end
423
+
424
+ def write_chunk(str)
425
+ @chunked_content_length += @body.write(str)
406
426
  end
407
427
 
408
428
  def decode_chunk(chunk)
409
429
  if @partial_part_left > 0
410
430
  if @partial_part_left <= chunk.size
411
431
  if @partial_part_left > 2
412
- @body << chunk[0..(@partial_part_left-3)] # skip the \r\n
432
+ write_chunk(chunk[0..(@partial_part_left-3)]) # skip the \r\n
413
433
  end
414
434
  chunk = chunk[@partial_part_left..-1]
415
435
  @partial_part_left = 0
416
436
  else
417
- @body << chunk if @partial_part_left > 2 # don't include the last \r\n
437
+ write_chunk(chunk) if @partial_part_left > 2 # don't include the last \r\n
418
438
  @partial_part_left -= chunk.size
419
439
  return false
420
440
  end
@@ -461,12 +481,12 @@ module Puma
461
481
 
462
482
  case
463
483
  when got == len
464
- @body << part[0..-3] # to skip the ending \r\n
484
+ write_chunk(part[0..-3]) # to skip the ending \r\n
465
485
  when got <= len - 2
466
- @body << part
486
+ write_chunk(part)
467
487
  @partial_part_left = len - part.size
468
488
  when got == len - 1 # edge where we get just \r but not \n
469
- @body << part[0..-2]
489
+ write_chunk(part[0..-2])
470
490
  @partial_part_left = len - part.size
471
491
  end
472
492
  else
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.3".freeze
103
+ PUMA_VERSION = VERSION = "4.3.8".freeze
104
104
  CODE_NAME = "Mysterious Traveller".freeze
105
105
  PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
106
106
 
data/lib/puma/server.rb CHANGED
@@ -483,15 +483,20 @@ module Puma
483
483
 
484
484
  requests += 1
485
485
 
486
- check_for_more_data = @status == :run
486
+ # Closing keepalive sockets after they've made a reasonable
487
+ # number of requests allows Puma to service many connections
488
+ # fairly, even when the number of concurrent connections exceeds
489
+ # the size of the threadpool. It also allows cluster mode Pumas
490
+ # to keep load evenly distributed across workers, because clients
491
+ # are randomly assigned a new worker when opening a new connection.
492
+ #
493
+ # Previously, Puma would kick connections in this conditional back
494
+ # to the reactor. However, because this causes the todo set to increase
495
+ # in size, the wait_until_full mutex would never unlock, leaving
496
+ # any additional connections unserviced.
497
+ break if requests >= MAX_FAST_INLINE
487
498
 
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
499
+ check_for_more_data = @status == :run
495
500
 
496
501
  unless client.reset(check_for_more_data)
497
502
  close_socket = false
@@ -672,6 +677,37 @@ module Puma
672
677
  }
673
678
  end
674
679
 
680
+ # Fixup any headers with , in the name to have _ now. We emit
681
+ # headers with , in them during the parse phase to avoid ambiguity
682
+ # with the - to _ conversion for critical headers. But here for
683
+ # compatibility, we'll convert them back. This code is written to
684
+ # avoid allocation in the common case (ie there are no headers
685
+ # with , in their names), that's why it has the extra conditionals.
686
+
687
+ to_delete = nil
688
+ to_add = nil
689
+
690
+ env.each do |k,v|
691
+ if k.start_with?("HTTP_") and k.include?(",") and k != "HTTP_TRANSFER,ENCODING"
692
+ if to_delete
693
+ to_delete << k
694
+ else
695
+ to_delete = [k]
696
+ end
697
+
698
+ unless to_add
699
+ to_add = {}
700
+ end
701
+
702
+ to_add[k.tr(",", "_")] = v
703
+ end
704
+ end
705
+
706
+ if to_delete
707
+ to_delete.each { |k| env.delete(k) }
708
+ env.merge! to_add
709
+ end
710
+
675
711
  # A rack extension. If the app writes #call'ables to this
676
712
  # array, we will invoke them when the request is done.
677
713
  #
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.3
4
+ version: 4.3.8
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: 2020-02-28 00:00:00.000000000 Z
11
+ date: 2021-05-11 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.1.2
140
- signing_key:
139
+ rubygems_version: 3.2.3
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