Version in base suite: 4.3.8-1 Base version: puma_4.3.8-1 Target version: puma_4.3.8-1+deb11u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/puma/puma_4.3.8-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/puma/puma_4.3.8-1+deb11u2.dsc changelog | 15 gbp.conf | 3 patches/security-fix-cve-2021-41136.patch | 627 ++++++++++++++++++++++++++++++ patches/security-fix-cve-2022-23634.patch | 27 + patches/security-fix-cve-2022-24790.patch | 421 ++++++++++++++++++++ patches/series | 3 salsa-ci.yml | 4 7 files changed, 1100 insertions(+) diff -Nru puma-4.3.8/debian/changelog puma-4.3.8/debian/changelog --- puma-4.3.8/debian/changelog 2021-05-26 04:54:19.000000000 +0000 +++ puma-4.3.8/debian/changelog 2022-04-14 10:05:32.000000000 +0000 @@ -1,3 +1,18 @@ +puma (4.3.8-1+deb11u2) bullseye-security; urgency=medium + + * Team upload. + * d/p: Add security patch for CVE-2021-41136 + + -- Mohammed Bilal Thu, 14 Apr 2022 10:05:32 +0000 + +puma (4.3.8-1+deb11u1) bullseye-security; urgency=medium + + * Team upload. + * d/p: Add security patch for CVE-2022-23634 (closes: #1005391) + * d/p: Add security patch for CVE-2022-24790 (closes: #1008723) + + -- Mohammed Bilal Wed, 13 Apr 2022 01:13:45 +0000 + puma (4.3.8-1) unstable; urgency=medium * New upstream version 4.3.8 (Closes: #989054) (Fixes: CVE-2021-29509) diff -Nru puma-4.3.8/debian/gbp.conf puma-4.3.8/debian/gbp.conf --- puma-4.3.8/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 +++ puma-4.3.8/debian/gbp.conf 2021-06-20 20:26:46.000000000 +0000 @@ -0,0 +1,3 @@ +[DEFAULT] +pristine-tar = true +verbose = true diff -Nru puma-4.3.8/debian/patches/security-fix-cve-2021-41136.patch puma-4.3.8/debian/patches/security-fix-cve-2021-41136.patch --- puma-4.3.8/debian/patches/security-fix-cve-2021-41136.patch 1970-01-01 00:00:00.000000000 +0000 +++ puma-4.3.8/debian/patches/security-fix-cve-2021-41136.patch 2022-04-14 09:55:37.000000000 +0000 @@ -0,0 +1,627 @@ +Description: Applies security patch for CVE-2021-41136 +Author: Mohammed Bilal +Applied-Upstream: https://github.com/puma/puma/commit/acdc3ae571dfae0e045cf09a295280127db65c7f +Last-Update: 2022-04-13 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- a/ext/puma_http11/http11_parser.c ++++ b/ext/puma_http11/http11_parser.c +@@ -33,20 +33,18 @@ + /** Machine **/ + + +-#line 79 "ext/puma_http11/http11_parser.rl" ++#line 81 "ext/puma_http11/http11_parser.rl" + + + /** Data **/ + +-#line 40 "ext/puma_http11/http11_parser.c" ++#line 42 "ext/puma_http11/http11_parser.c" + static const int puma_parser_start = 1; + static const int puma_parser_first_final = 46; + static const int puma_parser_error = 0; + +-static const int puma_parser_en_main = 1; + +- +-#line 83 "ext/puma_http11/http11_parser.rl" ++#line 85 "ext/puma_http11/http11_parser.rl" + + int puma_parser_init(puma_parser *parser) { + int cs = 0; +@@ -56,7 +54,7 @@ + cs = puma_parser_start; + } + +-#line 87 "ext/puma_http11/http11_parser.rl" ++#line 89 "ext/puma_http11/http11_parser.rl" + parser->cs = cs; + parser->body_start = 0; + parser->content_len = 0; +@@ -109,7 +107,7 @@ + cs = 0; + goto _out; + tr0: +-#line 35 "ext/puma_http11/http11_parser.rl" ++#line 37 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } + goto st2; + st2: +@@ -132,7 +130,7 @@ + goto st27; + goto st0; + tr2: +-#line 48 "ext/puma_http11/http11_parser.rl" ++#line 50 "ext/puma_http11/http11_parser.rl" + { + parser->request_method(parser, PTR_TO(mark), LEN(mark, p)); + } +@@ -158,7 +156,7 @@ + goto tr5; + goto st0; + tr4: +-#line 35 "ext/puma_http11/http11_parser.rl" ++#line 37 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } + goto st4; + st4: +@@ -172,53 +170,53 @@ + } + goto st0; + tr8: +-#line 51 "ext/puma_http11/http11_parser.rl" ++#line 53 "ext/puma_http11/http11_parser.rl" + { + parser->request_uri(parser, PTR_TO(mark), LEN(mark, p)); + } + goto st5; + tr31: +-#line 35 "ext/puma_http11/http11_parser.rl" ++#line 37 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } +-#line 54 "ext/puma_http11/http11_parser.rl" ++#line 56 "ext/puma_http11/http11_parser.rl" + { + parser->fragment(parser, PTR_TO(mark), LEN(mark, p)); + } + goto st5; + tr33: +-#line 54 "ext/puma_http11/http11_parser.rl" ++#line 56 "ext/puma_http11/http11_parser.rl" + { + parser->fragment(parser, PTR_TO(mark), LEN(mark, p)); + } + goto st5; + tr37: +-#line 67 "ext/puma_http11/http11_parser.rl" ++#line 69 "ext/puma_http11/http11_parser.rl" + { + parser->request_path(parser, PTR_TO(mark), LEN(mark,p)); + } +-#line 51 "ext/puma_http11/http11_parser.rl" ++#line 53 "ext/puma_http11/http11_parser.rl" + { + parser->request_uri(parser, PTR_TO(mark), LEN(mark, p)); + } + goto st5; + tr41: +-#line 58 "ext/puma_http11/http11_parser.rl" ++#line 60 "ext/puma_http11/http11_parser.rl" + { MARK(query_start, p); } +-#line 59 "ext/puma_http11/http11_parser.rl" ++#line 61 "ext/puma_http11/http11_parser.rl" + { + parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p)); + } +-#line 51 "ext/puma_http11/http11_parser.rl" ++#line 53 "ext/puma_http11/http11_parser.rl" + { + parser->request_uri(parser, PTR_TO(mark), LEN(mark, p)); + } + goto st5; + tr44: +-#line 59 "ext/puma_http11/http11_parser.rl" ++#line 61 "ext/puma_http11/http11_parser.rl" + { + parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p)); + } +-#line 51 "ext/puma_http11/http11_parser.rl" ++#line 53 "ext/puma_http11/http11_parser.rl" + { + parser->request_uri(parser, PTR_TO(mark), LEN(mark, p)); + } +@@ -232,7 +230,7 @@ + goto tr10; + goto st0; + tr10: +-#line 35 "ext/puma_http11/http11_parser.rl" ++#line 37 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } + goto st6; + st6: +@@ -297,21 +295,21 @@ + goto st13; + goto st0; + tr18: +-#line 63 "ext/puma_http11/http11_parser.rl" ++#line 65 "ext/puma_http11/http11_parser.rl" + { + parser->http_version(parser, PTR_TO(mark), LEN(mark, p)); + } + goto st14; + tr26: +-#line 44 "ext/puma_http11/http11_parser.rl" ++#line 46 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } +-#line 45 "ext/puma_http11/http11_parser.rl" ++#line 47 "ext/puma_http11/http11_parser.rl" + { + parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p)); + } + goto st14; + tr29: +-#line 45 "ext/puma_http11/http11_parser.rl" ++#line 47 "ext/puma_http11/http11_parser.rl" + { + parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p)); + } +@@ -360,7 +358,7 @@ + goto tr22; + goto st0; + tr22: +-#line 71 "ext/puma_http11/http11_parser.rl" ++#line 73 "ext/puma_http11/http11_parser.rl" + { + parser->body_start = p - buffer + 1; + parser->header_done(parser, p + 1, pe - p - 1); +@@ -374,13 +372,13 @@ + #line 373 "ext/puma_http11/http11_parser.c" + goto st0; + tr21: +-#line 38 "ext/puma_http11/http11_parser.rl" ++#line 40 "ext/puma_http11/http11_parser.rl" + { MARK(field_start, p); } +-#line 39 "ext/puma_http11/http11_parser.rl" ++#line 41 "ext/puma_http11/http11_parser.rl" + { snake_upcase_char((char *)p); } + goto st17; + tr23: +-#line 39 "ext/puma_http11/http11_parser.rl" ++#line 41 "ext/puma_http11/http11_parser.rl" + { snake_upcase_char((char *)p); } + goto st17; + st17: +@@ -413,13 +411,13 @@ + goto tr23; + goto st0; + tr24: +-#line 40 "ext/puma_http11/http11_parser.rl" ++#line 42 "ext/puma_http11/http11_parser.rl" + { + parser->field_len = LEN(field_start, p); + } + goto st18; + tr27: +-#line 44 "ext/puma_http11/http11_parser.rl" ++#line 46 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } + goto st18; + st18: +@@ -428,56 +426,63 @@ + case 18: + #line 428 "ext/puma_http11/http11_parser.c" + switch( (*p) ) { ++ case 9: goto tr25; + case 13: goto tr26; + case 32: goto tr27; + } +- goto tr25; ++ if ( 33 <= (*p) && (*p) <= 126 ) ++ goto tr25; ++ goto st0; + tr25: +-#line 44 "ext/puma_http11/http11_parser.rl" ++#line 46 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } + goto st19; + st19: + if ( ++p == pe ) + goto _test_eof19; + case 19: +-#line 442 "ext/puma_http11/http11_parser.c" +- if ( (*p) == 13 ) +- goto tr29; +- goto st19; ++#line 445 "ext/puma_http11/http11_parser.c" ++ switch( (*p) ) { ++ case 9: goto st19; ++ case 13: goto tr29; ++ } ++ if ( 32 <= (*p) && (*p) <= 126 ) ++ goto st19; ++ goto st0; + tr9: +-#line 51 "ext/puma_http11/http11_parser.rl" ++#line 53 "ext/puma_http11/http11_parser.rl" + { + parser->request_uri(parser, PTR_TO(mark), LEN(mark, p)); + } + goto st20; + tr38: +-#line 67 "ext/puma_http11/http11_parser.rl" ++#line 69 "ext/puma_http11/http11_parser.rl" + { + parser->request_path(parser, PTR_TO(mark), LEN(mark,p)); + } +-#line 51 "ext/puma_http11/http11_parser.rl" ++#line 53 "ext/puma_http11/http11_parser.rl" + { + parser->request_uri(parser, PTR_TO(mark), LEN(mark, p)); + } + goto st20; + tr42: +-#line 58 "ext/puma_http11/http11_parser.rl" ++#line 60 "ext/puma_http11/http11_parser.rl" + { MARK(query_start, p); } +-#line 59 "ext/puma_http11/http11_parser.rl" ++#line 61 "ext/puma_http11/http11_parser.rl" + { + parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p)); + } +-#line 51 "ext/puma_http11/http11_parser.rl" ++#line 53 "ext/puma_http11/http11_parser.rl" + { + parser->request_uri(parser, PTR_TO(mark), LEN(mark, p)); + } + goto st20; + tr45: +-#line 59 "ext/puma_http11/http11_parser.rl" ++#line 61 "ext/puma_http11/http11_parser.rl" + { + parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p)); + } +-#line 51 "ext/puma_http11/http11_parser.rl" ++#line 53 "ext/puma_http11/http11_parser.rl" + { + parser->request_uri(parser, PTR_TO(mark), LEN(mark, p)); + } +@@ -486,7 +491,7 @@ + if ( ++p == pe ) + goto _test_eof20; + case 20: +-#line 488 "ext/puma_http11/http11_parser.c" ++#line 495 "ext/puma_http11/http11_parser.c" + switch( (*p) ) { + case 32: goto tr31; + case 60: goto st0; +@@ -500,14 +505,14 @@ + goto st0; + goto tr30; + tr30: +-#line 35 "ext/puma_http11/http11_parser.rl" ++#line 37 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } + goto st21; + st21: + if ( ++p == pe ) + goto _test_eof21; + case 21: +-#line 509 "ext/puma_http11/http11_parser.c" ++#line 516 "ext/puma_http11/http11_parser.c" + switch( (*p) ) { + case 32: goto tr33; + case 60: goto st0; +@@ -521,14 +526,14 @@ + goto st0; + goto st21; + tr5: +-#line 35 "ext/puma_http11/http11_parser.rl" ++#line 37 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } + goto st22; + st22: + if ( ++p == pe ) + goto _test_eof22; + case 22: +-#line 530 "ext/puma_http11/http11_parser.c" ++#line 537 "ext/puma_http11/http11_parser.c" + switch( (*p) ) { + case 43: goto st22; + case 58: goto st23; +@@ -546,14 +551,14 @@ + goto st22; + goto st0; + tr7: +-#line 35 "ext/puma_http11/http11_parser.rl" ++#line 37 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } + goto st23; + st23: + if ( ++p == pe ) + goto _test_eof23; + case 23: +-#line 555 "ext/puma_http11/http11_parser.c" ++#line 562 "ext/puma_http11/http11_parser.c" + switch( (*p) ) { + case 32: goto tr8; + case 34: goto st0; +@@ -566,14 +571,14 @@ + goto st0; + goto st23; + tr6: +-#line 35 "ext/puma_http11/http11_parser.rl" ++#line 37 "ext/puma_http11/http11_parser.rl" + { MARK(mark, p); } + goto st24; + st24: + if ( ++p == pe ) + goto _test_eof24; + case 24: +-#line 575 "ext/puma_http11/http11_parser.c" ++#line 582 "ext/puma_http11/http11_parser.c" + switch( (*p) ) { + case 32: goto tr37; + case 34: goto st0; +@@ -587,7 +592,7 @@ + goto st0; + goto st24; + tr39: +-#line 67 "ext/puma_http11/http11_parser.rl" ++#line 69 "ext/puma_http11/http11_parser.rl" + { + parser->request_path(parser, PTR_TO(mark), LEN(mark,p)); + } +@@ -596,7 +601,7 @@ + if ( ++p == pe ) + goto _test_eof25; + case 25: +-#line 598 "ext/puma_http11/http11_parser.c" ++#line 605 "ext/puma_http11/http11_parser.c" + switch( (*p) ) { + case 32: goto tr41; + case 34: goto st0; +@@ -609,14 +614,14 @@ + goto st0; + goto tr40; + tr40: +-#line 58 "ext/puma_http11/http11_parser.rl" ++#line 60 "ext/puma_http11/http11_parser.rl" + { MARK(query_start, p); } + goto st26; + st26: + if ( ++p == pe ) + goto _test_eof26; + case 26: +-#line 618 "ext/puma_http11/http11_parser.c" ++#line 625 "ext/puma_http11/http11_parser.c" + switch( (*p) ) { + case 32: goto tr44; + case 34: goto st0; +@@ -1010,7 +1015,7 @@ + _out: {} + } + +-#line 115 "ext/puma_http11/http11_parser.rl" ++#line 117 "ext/puma_http11/http11_parser.rl" + + if (!puma_parser_has_error(parser)) + parser->cs = cs; +--- a/ext/puma_http11/http11_parser_common.rl ++++ b/ext/puma_http11/http11_parser_common.rl +@@ -43,7 +43,7 @@ + + field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field; + +- field_value = any* >start_value %write_value; ++ field_value = ( print | "\t" )* >start_value %write_value; + + message_header = field_name ":" " "* field_value :> CRLF; + +--- a/ext/puma_http11/org/jruby/puma/Http11Parser.java ++++ b/ext/puma_http11/org/jruby/puma/Http11Parser.java +@@ -34,9 +34,9 @@ + { + return new short [] { + 0, 0, 8, 17, 27, 29, 30, 31, 32, 33, 34, 36, +- 39, 41, 44, 45, 61, 62, 78, 80, 81, 89, 97, 107, +- 115, 124, 132, 140, 149, 158, 167, 176, 185, 194, 203, 212, +- 221, 230, 239, 248, 257, 266, 275, 284, 293, 302, 303 ++ 39, 41, 44, 45, 61, 62, 78, 83, 87, 95, 103, 113, ++ 121, 130, 138, 146, 155, 164, 173, 182, 191, 200, 209, 218, ++ 227, 236, 245, 254, 263, 272, 281, 290, 299, 308, 309 + }; + } + +@@ -52,14 +52,13 @@ + 46, 48, 57, 48, 57, 13, 48, 57, 10, 13, 33, 124, + 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, + 122, 10, 33, 58, 124, 126, 35, 39, 42, 43, 45, 46, +- 48, 57, 65, 90, 94, 122, 13, 32, 13, 32, 60, 62, +- 127, 0, 31, 34, 35, 32, 60, 62, 127, 0, 31, 34, +- 35, 43, 58, 45, 46, 48, 57, 65, 90, 97, 122, 32, +- 34, 35, 60, 62, 127, 0, 31, 32, 34, 35, 60, 62, +- 63, 127, 0, 31, 32, 34, 35, 60, 62, 127, 0, 31, +- 32, 34, 35, 60, 62, 127, 0, 31, 32, 36, 95, 45, +- 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, +- 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, ++ 48, 57, 65, 90, 94, 122, 9, 13, 32, 33, 126, 9, ++ 13, 32, 126, 32, 60, 62, 127, 0, 31, 34, 35, 32, ++ 60, 62, 127, 0, 31, 34, 35, 43, 58, 45, 46, 48, ++ 57, 65, 90, 97, 122, 32, 34, 35, 60, 62, 127, 0, ++ 31, 32, 34, 35, 60, 62, 63, 127, 0, 31, 32, 34, ++ 35, 60, 62, 127, 0, 31, 32, 34, 35, 60, 62, 127, ++ 0, 31, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, + 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, + 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, + 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, +@@ -71,7 +70,8 @@ + 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, + 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, + 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, +- 65, 90, 32, 0 ++ 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, ++ 36, 95, 45, 46, 48, 57, 65, 90, 32, 0 + }; + } + +@@ -82,7 +82,7 @@ + { + return new byte [] { + 0, 2, 3, 4, 2, 1, 1, 1, 1, 1, 0, 1, +- 0, 1, 1, 4, 1, 4, 2, 1, 4, 4, 2, 6, ++ 0, 1, 1, 4, 1, 4, 3, 2, 4, 4, 2, 6, + 7, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 0 + }; +@@ -95,7 +95,7 @@ + { + return new byte [] { + 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1, +- 1, 1, 0, 6, 0, 6, 0, 0, 2, 2, 4, 1, ++ 1, 1, 0, 6, 0, 6, 1, 1, 2, 2, 4, 1, + 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0 + }; +@@ -108,9 +108,9 @@ + { + return new short [] { + 0, 0, 6, 13, 21, 24, 26, 28, 30, 32, 34, 36, +- 39, 41, 44, 46, 57, 59, 70, 73, 75, 82, 89, 96, +- 104, 113, 121, 129, 136, 143, 150, 157, 164, 171, 178, 185, +- 192, 199, 206, 213, 220, 227, 234, 241, 248, 255, 257 ++ 39, 41, 44, 46, 57, 59, 70, 75, 79, 86, 93, 100, ++ 108, 117, 125, 133, 140, 147, 154, 161, 168, 175, 182, 189, ++ 196, 203, 210, 217, 224, 231, 238, 245, 252, 259, 261 + }; + } + +@@ -125,23 +125,23 @@ + 10, 1, 11, 1, 12, 1, 13, 1, 14, 1, 15, 1, + 16, 15, 1, 17, 1, 18, 17, 1, 19, 1, 20, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 1, 22, 1, 23, +- 24, 23, 23, 23, 23, 23, 23, 23, 23, 1, 26, 27, +- 25, 29, 28, 30, 1, 1, 1, 1, 1, 31, 32, 1, +- 1, 1, 1, 1, 33, 34, 35, 34, 34, 34, 34, 1, +- 8, 1, 9, 1, 1, 1, 1, 35, 36, 1, 38, 1, +- 1, 39, 1, 1, 37, 40, 1, 42, 1, 1, 1, 1, +- 41, 43, 1, 45, 1, 1, 1, 1, 44, 2, 46, 46, +- 46, 46, 46, 1, 2, 47, 47, 47, 47, 47, 1, 2, +- 48, 48, 48, 48, 48, 1, 2, 49, 49, 49, 49, 49, +- 1, 2, 50, 50, 50, 50, 50, 1, 2, 51, 51, 51, +- 51, 51, 1, 2, 52, 52, 52, 52, 52, 1, 2, 53, +- 53, 53, 53, 53, 1, 2, 54, 54, 54, 54, 54, 1, +- 2, 55, 55, 55, 55, 55, 1, 2, 56, 56, 56, 56, +- 56, 1, 2, 57, 57, 57, 57, 57, 1, 2, 58, 58, +- 58, 58, 58, 1, 2, 59, 59, 59, 59, 59, 1, 2, +- 60, 60, 60, 60, 60, 1, 2, 61, 61, 61, 61, 61, +- 1, 2, 62, 62, 62, 62, 62, 1, 2, 63, 63, 63, +- 63, 63, 1, 2, 1, 1, 0 ++ 24, 23, 23, 23, 23, 23, 23, 23, 23, 1, 25, 26, ++ 27, 25, 1, 28, 29, 28, 1, 30, 1, 1, 1, 1, ++ 1, 31, 32, 1, 1, 1, 1, 1, 33, 34, 35, 34, ++ 34, 34, 34, 1, 8, 1, 9, 1, 1, 1, 1, 35, ++ 36, 1, 38, 1, 1, 39, 1, 1, 37, 40, 1, 42, ++ 1, 1, 1, 1, 41, 43, 1, 45, 1, 1, 1, 1, ++ 44, 2, 46, 46, 46, 46, 46, 1, 2, 47, 47, 47, ++ 47, 47, 1, 2, 48, 48, 48, 48, 48, 1, 2, 49, ++ 49, 49, 49, 49, 1, 2, 50, 50, 50, 50, 50, 1, ++ 2, 51, 51, 51, 51, 51, 1, 2, 52, 52, 52, 52, ++ 52, 1, 2, 53, 53, 53, 53, 53, 1, 2, 54, 54, ++ 54, 54, 54, 1, 2, 55, 55, 55, 55, 55, 1, 2, ++ 56, 56, 56, 56, 56, 1, 2, 57, 57, 57, 57, 57, ++ 1, 2, 58, 58, 58, 58, 58, 1, 2, 59, 59, 59, ++ 59, 59, 1, 2, 60, 60, 60, 60, 60, 1, 2, 61, ++ 61, 61, 61, 61, 1, 2, 62, 62, 62, 62, 62, 1, ++ 2, 63, 63, 63, 63, 63, 1, 2, 1, 1, 0 + }; + } + +@@ -182,8 +182,6 @@ + static final int puma_parser_first_final = 46; + static final int puma_parser_error = 0; + +-static final int puma_parser_en_main = 1; +- + + // line 62 "ext/puma_http11/http11_parser.java.rl" + +@@ -212,12 +210,12 @@ + cs = 0; + + +-// line 218 "ext/puma_http11/org/jruby/puma/Http11Parser.java" ++// line 214 "ext/puma_http11/org/jruby/puma/Http11Parser.java" + { + cs = puma_parser_start; + } + +-// line 90 "ext/puma_http11/http11_parser.java.rl" ++// line 88 "ext/puma_http11/http11_parser.java.rl" + + body_start = 0; + content_len = 0; +@@ -244,7 +242,7 @@ + parser.buffer = buffer; + + +-// line 250 "ext/puma_http11/org/jruby/puma/Http11Parser.java" ++// line 246 "ext/puma_http11/org/jruby/puma/Http11Parser.java" + { + int _klen; + int _trans = 0; +@@ -400,7 +398,7 @@ + { p += 1; _goto_targ = 5; if (true) continue _goto;} + } + break; +-// line 406 "ext/puma_http11/org/jruby/puma/Http11Parser.java" ++// line 402 "ext/puma_http11/org/jruby/puma/Http11Parser.java" + } + } + } +@@ -420,7 +418,7 @@ + break; } + } + +-// line 116 "ext/puma_http11/http11_parser.java.rl" ++// line 114 "ext/puma_http11/http11_parser.java.rl" + + parser.cs = cs; + parser.nread += (p - off); +--- a/test/test_http11.rb ++++ b/test/test_http11.rb +@@ -208,4 +208,34 @@ + + assert_equal "Strip This", req["HTTP_X_STRIP_ME"] + end ++ ++ def test_newline_smuggler ++ parser = Puma::HttpParser.new ++ req = {} ++ http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\nDummy2: y\r\n\r\n" ++ ++ parser.execute(req, http, 0) rescue nil # We test the raise elsewhere. ++ ++ assert parser.error?, "Parser SHOULD have error" ++ end ++ ++ def test_newline_smuggler_two ++ parser = Puma::HttpParser.new ++ req = {} ++ http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\r\nDummy: y\nDummy2: z\r\n\r\n" ++ ++ parser.execute(req, http, 0) rescue nil ++ ++ assert parser.error?, "Parser SHOULD have error" ++ end ++ ++ def test_htab_in_header_val ++ parser = Puma::HttpParser.new ++ req = {} ++ http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: Valid\tValue\r\n\r\n" ++ ++ parser.execute(req, http, 0) ++ ++ assert_equal "Valid\tValue", req['HTTP_DUMMY'] ++ end + end diff -Nru puma-4.3.8/debian/patches/security-fix-cve-2022-23634.patch puma-4.3.8/debian/patches/security-fix-cve-2022-23634.patch --- puma-4.3.8/debian/patches/security-fix-cve-2022-23634.patch 1970-01-01 00:00:00.000000000 +0000 +++ puma-4.3.8/debian/patches/security-fix-cve-2022-23634.patch 2022-04-14 09:55:37.000000000 +0000 @@ -0,0 +1,27 @@ +Description: Applies security patch for CVE-2022-23634 +Author: Mohammed Bilal +Applied-Upstream: https://github.com/puma/puma/pull/2822 +Last-Update: 2022-04-08 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- a/lib/puma/server.rb ++++ b/lib/puma/server.rb +@@ -873,11 +873,14 @@ + end + + ensure +- uncork_socket client ++ begin ++ uncork_socket client + +- body.close +- req.tempfile.unlink if req.tempfile +- res_body.close if res_body.respond_to? :close ++ body.close ++ req.tempfile.unlink if req.tempfile ++ ensure ++ res_body.close if res_body.respond_to? :close ++ end + + after_reply.each { |o| o.call } + end diff -Nru puma-4.3.8/debian/patches/security-fix-cve-2022-24790.patch puma-4.3.8/debian/patches/security-fix-cve-2022-24790.patch --- puma-4.3.8/debian/patches/security-fix-cve-2022-24790.patch 1970-01-01 00:00:00.000000000 +0000 +++ puma-4.3.8/debian/patches/security-fix-cve-2022-24790.patch 2022-04-14 09:55:37.000000000 +0000 @@ -0,0 +1,421 @@ +Description: Applies security patch for CVE-2022-27490 +Author: Mohammed Bilal +Applied-Upstream: https://github.com/puma/puma/commit/b8439ffc9d37f69c45bdca0a74cb49ebd9d09e66#diff-267386f55151c0f4e7f1f02c72881be7560baa1e80d6e2e63d30b074dda37cd1 +Last-Update: 2022-04-08 +--- +--- a/lib/puma/client.rb ++++ b/lib/puma/client.rb +@@ -23,6 +23,8 @@ + + class ConnectionError < RuntimeError; end + ++ class HttpParserError501 < IOError; end ++ + # An instance of this class represents a unique request from a client. + # For example, this could be a web request from a browser or from CURL. + # +@@ -35,7 +37,21 @@ + # Instances of this class are responsible for knowing if + # the header and body are fully buffered via the `try_to_finish` method. + # They can be used to "time out" a response via the `timeout_at` reader. ++ # + class Client ++ ++ # this tests all values but the last, which must be chunked ++ ALLOWED_TRANSFER_ENCODING = %w[compress deflate gzip].freeze ++ ++ # chunked body validation ++ CHUNK_SIZE_INVALID = /[^\h]/.freeze ++ CHUNK_VALID_ENDING = "\r\n".freeze ++ ++ # Content-Length header value validation ++ CONTENT_LENGTH_VALUE_INVALID = /[^\d]/.freeze ++ ++ TE_ERR_MSG = 'Invalid Transfer-Encoding' ++ + # The object used for a request with no body. All requests with + # no body share this one object since it has no state. + EmptyBody = NullIO.new +@@ -284,16 +300,27 @@ + body = @parser.body + + te = @env[TRANSFER_ENCODING2] +- + if te +- if te.include?(",") +- te.split(",").each do |part| +- if CHUNKED.casecmp(part.strip) == 0 +- return setup_chunked_body(body) +- end ++ te_lwr = te.downcase ++ if te.include? ',' ++ te_ary = te_lwr.split ',' ++ te_count = te_ary.count CHUNKED ++ te_valid = te_ary[0..-2].all? { |e| ALLOWED_TRANSFER_ENCODING.include? e } ++ if te_ary.last == CHUNKED && te_count == 1 && te_valid ++ @env.delete TRANSFER_ENCODING2 ++ return setup_chunked_body body ++ elsif te_count >= 1 ++ raise HttpParserError , "#{TE_ERR_MSG}, multiple chunked: '#{te}'" ++ elsif !te_valid ++ raise HttpParserError501, "#{TE_ERR_MSG}, unknown value: '#{te}'" + end +- elsif CHUNKED.casecmp(te) == 0 +- return setup_chunked_body(body) ++ elsif te_lwr == CHUNKED ++ @env.delete TRANSFER_ENCODING2 ++ return setup_chunked_body body ++ elsif ALLOWED_TRANSFER_ENCODING.include? te_lwr ++ raise HttpParserError , "#{TE_ERR_MSG}, single value must be chunked: '#{te}'" ++ else ++ raise HttpParserError501 , "#{TE_ERR_MSG}, unknown value: '#{te}'" + end + end + +@@ -301,7 +328,12 @@ + + cl = @env[CONTENT_LENGTH] + +- unless cl ++ if cl ++ # cannot contain characters that are not \d ++ if cl =~ CONTENT_LENGTH_VALUE_INVALID ++ raise HttpParserError, "Invalid Content-Length: #{cl.inspect}" ++ end ++ else + @buffer = body.empty? ? nil : body + @body = EmptyBody + set_ready +@@ -450,7 +482,13 @@ + while !io.eof? + line = io.gets + if line.end_with?("\r\n") +- len = line.strip.to_i(16) ++ # Puma doesn't process chunk extensions, but should parse if they're ++ # present, which is the reason for the semicolon regex ++ chunk_hex = line.strip[/\A[^;]+/] ++ if chunk_hex =~ CHUNK_SIZE_INVALID ++ raise HttpParserError, "Invalid chunk size: '#{chunk_hex}'" ++ end ++ len = chunk_hex.to_i(16) + if len == 0 + @in_last_chunk = true + @body.rewind +@@ -481,7 +519,12 @@ + + case + when got == len +- write_chunk(part[0..-3]) # to skip the ending \r\n ++ # proper chunked segment must end with "\r\n" ++ if part.end_with? CHUNK_VALID_ENDING ++ write_chunk(part[0..-3]) # to skip the ending \r\n ++ else ++ raise HttpParserError, "Chunk size mismatch" ++ end + when got <= len - 2 + write_chunk(part) + @partial_part_left = len - part.size +--- a/lib/puma/const.rb ++++ b/lib/puma/const.rb +@@ -76,7 +76,7 @@ + 508 => 'Loop Detected', + 510 => 'Not Extended', + 511 => 'Network Authentication Required' +- } ++ }.freeze + + # For some HTTP status codes the client only expects headers. + # +@@ -85,7 +85,7 @@ + 204 => true, + 205 => true, + 304 => true +- } ++ }.freeze + + # Frequently used constants when constructing requests or responses. Many times + # the constant just refers to a string with the same contents. Using these constants +@@ -144,9 +144,11 @@ + 408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\n".freeze, + # Indicate that there was an internal error, obviously. + 500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n".freeze, ++ # Incorrect or invalid header value ++ 501 => "HTTP/1.1 501 Not Implemented\r\n\r\n".freeze, + # A common header for indicating the server is too busy. Not used yet. + 503 => "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze +- } ++ }.freeze + + # The basic max request size we'll try to read. + CHUNK_SIZE = 16 * 1024 +--- a/lib/puma/server.rb ++++ b/lib/puma/server.rb +@@ -321,6 +321,10 @@ + client.close + + @events.parse_error self, client.env, e ++ rescue HttpParserError501 => e ++ client.write_error(501) ++ client.close ++ @events.parse_error self, client.env, e + rescue ConnectionError, EOFError + client.close + else +@@ -530,7 +534,12 @@ + client.write_error(400) + + @events.parse_error self, client.env, e ++ rescue HttpParserError501 => e ++ lowlevel_error(e, client.env) ++ ++ client.write_error(501) + ++ @events.parse_error self, client.env, e + # Server error + rescue StandardError => e + lowlevel_error(e, client.env) +--- a/test/test_puma_server.rb ++++ b/test/test_puma_server.rb +@@ -446,17 +446,20 @@ + def test_chunked_request + body = nil + content_length = nil ++ transfer_encoding = nil + server_run app: ->(env) { + body = env['rack.input'].read + content_length = env['CONTENT_LENGTH'] ++ transfer_encoding = env['HTTP_TRANSFER_ENCODING'] + [200, {}, [""]] + } + +- data = send_http_and_read "GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\n1\r\nh\r\n4\r\nello\r\n0\r\n\r\n" ++ data = send_http_and_read "GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: gzip,chunked\r\n\r\n1\r\nh\r\n4\r\nello\r\n0\r\n\r\n" + + assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data + assert_equal "hello", body + assert_equal 5, content_length ++ assert_nil transfer_encoding + end + + def test_chunked_request_pause_before_value +--- /dev/null ++++ b/test/test_request_invalid.rb +@@ -0,0 +1,218 @@ ++require_relative "helper" ++require "puma/events" ++ ++# These tests check for invalid request headers and metadata. ++# Content-Length, Transfer-Encoding, and chunked body size ++# values are checked for validity ++# ++# See https://datatracker.ietf.org/doc/html/rfc7230 ++# ++# https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2 Content-Length ++# https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.1 Transfer-Encoding ++# https://datatracker.ietf.org/doc/html/rfc7230#section-4.1 chunked body size ++# ++class TestRequestInvalid < Minitest::Test ++ # running parallel seems to take longer... ++ # parallelize_me! unless JRUBY_HEAD ++ ++ GET_PREFIX = "GET / HTTP/1.1\r\nConnection: close\r\n" ++ CHUNKED = "1\r\nH\r\n4\r\nello\r\n5\r\nWorld\r\n0\r\n\r\n" ++ ++ def setup ++ @host = '127.0.0.1' ++ ++ @ios = [] ++ ++ # this app should never be called, used for debugging ++ app = ->(env) { ++ body = ''.dup ++ env.each do |k,v| ++ body << "#{k} = #{v}\n" ++ if k == 'rack.input' ++ body << "#{v.read}\n" ++ end ++ end ++ [200, {}, [body]] ++ } ++ ++ events = Puma::Events.strings ++ @server = Puma::Server.new app, events ++ @port = (@server.add_tcp_listener @host, 0).addr[1] ++ @server.run ++ sleep 0.15 if Puma.jruby? ++ end ++ ++ def teardown ++ @server.stop(true) ++ @ios.each { |io| io.close if io && !io.closed? } ++ end ++ ++ def send_http_and_read(req) ++ send_http(req).read ++ end ++ ++ def send_http(req) ++ new_connection << req ++ end ++ ++ def new_connection ++ TCPSocket.new(@host, @port).tap {|sock| @ios << sock} ++ end ++ ++ def assert_status(str, status = 400) ++ assert str.start_with?("HTTP/1.1 #{status}"), "'#{str[/[^\r]+/]}' should be #{status}" ++ end ++ ++ # ──────────────────────────────────── below are invalid Content-Length ++ ++ def test_content_length_multiple ++ te = [ ++ 'Content-Length: 5', ++ 'Content-Length: 5' ++ ].join "\r\n" ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\nHello\r\n\r\n" ++ ++ assert_status data ++ end ++ ++ def test_content_length_bad_characters_1 ++ te = 'Content-Length: 5.01' ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\nHello\r\n\r\n" ++ ++ assert_status data ++ end ++ ++ def test_content_length_bad_characters_2 ++ te = 'Content-Length: +5' ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\nHello\r\n\r\n" ++ ++ assert_status data ++ end ++ ++ def test_content_length_bad_characters_3 ++ te = 'Content-Length: 5 test' ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\nHello\r\n\r\n" ++ ++ assert_status data ++ end ++ ++ # ──────────────────────────────────── below are invalid Transfer-Encoding ++ ++ def test_transfer_encoding_chunked_not_last ++ te = [ ++ 'Transfer-Encoding: chunked', ++ 'Transfer-Encoding: gzip' ++ ].join "\r\n" ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n#{CHUNKED}" ++ ++ assert_status data ++ end ++ ++ def test_transfer_encoding_chunked_multiple ++ te = [ ++ 'Transfer-Encoding: chunked', ++ 'Transfer-Encoding: gzip', ++ 'Transfer-Encoding: chunked' ++ ].join "\r\n" ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n#{CHUNKED}" ++ ++ assert_status data ++ end ++ ++ def test_transfer_encoding_invalid_single ++ te = 'Transfer-Encoding: xchunked' ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n#{CHUNKED}" ++ ++ assert_status data, 501 ++ end ++ ++ def test_transfer_encoding_invalid_multiple ++ te = [ ++ 'Transfer-Encoding: x_gzip', ++ 'Transfer-Encoding: gzip', ++ 'Transfer-Encoding: chunked' ++ ].join "\r\n" ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n#{CHUNKED}" ++ assert_status data, 501 ++ end ++ ++ def test_transfer_encoding_single_not_chunked ++ te = 'Transfer-Encoding: gzip' ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n#{CHUNKED}" ++ ++ assert_status data ++ end ++ ++ # ──────────────────────────────────── below are invalid chunked size ++ ++ def test_chunked_size_bad_characters_1 ++ te = 'Transfer-Encoding: chunked' ++ chunked ='5.01' ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n1\r\nh\r\n#{chunked}\r\nHello\r\n0\r\n\r\n" ++ ++ assert_status data ++ end ++ ++ def test_chunked_size_bad_characters_2 ++ te = 'Transfer-Encoding: chunked' ++ chunked ='+5' ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n1\r\nh\r\n#{chunked}\r\nHello\r\n0\r\n\r\n" ++ ++ assert_status data ++ end ++ ++ def test_chunked_size_bad_characters_3 ++ te = 'Transfer-Encoding: chunked' ++ chunked ='5 bad' ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n1\r\nh\r\n#{chunked}\r\nHello\r\n0\r\n\r\n" ++ ++ assert_status data ++ end ++ ++ def test_chunked_size_bad_characters_4 ++ te = 'Transfer-Encoding: chunked' ++ chunked ='0xA' ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n1\r\nh\r\n#{chunked}\r\nHelloHello\r\n0\r\n\r\n" ++ ++ assert_status data ++ end ++ ++ # size is less than bytesize ++ def test_chunked_size_mismatch_1 ++ te = 'Transfer-Encoding: chunked' ++ chunked = ++ "5\r\nHello\r\n" \ ++ "4\r\nWorld\r\n" \ ++ "0" ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n#{chunked}\r\n\r\n" ++ ++ assert_status data ++ end ++ ++ # size is greater than bytesize ++ def test_chunked_size_mismatch_2 ++ te = 'Transfer-Encoding: chunked' ++ chunked = ++ "5\r\nHello\r\n" \ ++ "6\r\nWorld\r\n" \ ++ "0" ++ ++ data = send_http_and_read "#{GET_PREFIX}#{te}\r\n\r\n#{chunked}\r\n\r\n" ++ ++ assert_status data ++ end ++end diff -Nru puma-4.3.8/debian/patches/series puma-4.3.8/debian/patches/series --- puma-4.3.8/debian/patches/series 2021-05-26 04:54:19.000000000 +0000 +++ puma-4.3.8/debian/patches/series 2022-04-14 09:55:37.000000000 +0000 @@ -3,3 +3,6 @@ 0012-disable-cli-ssl-tests.patch 0013-fix-test-term-not-accepts-new-connections.patch 0014-gitlab-puma.patch +security-fix-cve-2022-24790.patch +security-fix-cve-2022-23634.patch +security-fix-cve-2021-41136.patch diff -Nru puma-4.3.8/debian/salsa-ci.yml puma-4.3.8/debian/salsa-ci.yml --- puma-4.3.8/debian/salsa-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ puma-4.3.8/debian/salsa-ci.yml 2021-05-26 04:53:04.000000000 +0000 @@ -0,0 +1,4 @@ +--- +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml