diff --git a/spec/std/http/cookie_spec.cr b/spec/std/http/cookie_spec.cr index 28174021f908..08d2e91c7b16 100644 --- a/spec/std/http/cookie_spec.cr +++ b/spec/std/http/cookie_spec.cr @@ -38,34 +38,33 @@ module HTTP expect_raises IO::Error, "Invalid cookie name" do HTTP::Cookie.new("\t", "") end - # more extensive specs on #name= end it "raises on invalid value" do expect_raises IO::Error, "Invalid cookie value" do HTTP::Cookie.new("x", %(foo\rbar)) end - # more extensive specs on #value= end end describe "#name=" do it "raises on invalid name" do cookie = HTTP::Cookie.new("x", "") - expect_raises IO::Error, "Invalid cookie name" do - cookie.name = "" - end - expect_raises IO::Error, "Invalid cookie name" do - cookie.name = "\t" - end - expect_raises IO::Error, "Invalid cookie name" do - cookie.name = "\r" - end - expect_raises IO::Error, "Invalid cookie name" do - cookie.name = "a\nb" - end - expect_raises IO::Error, "Invalid cookie name" do - cookie.name = "a\rb" + invalid_names = [ + '"', '(', ')', ',', '/', + ' ', '\r', '\t', '\n', + '{', '}', + (':'..'@').each, + ('['..']').each, + ].flat_map { |c| "a#{c}b" } + + # name cannot be empty + invalid_names << "" + + invalid_names.each do |invalid_name| + expect_raises IO::Error, "Invalid cookie name" do + cookie.name = invalid_name + end end end end @@ -73,26 +72,15 @@ module HTTP describe "#value=" do it "raises on invalid value" do cookie = HTTP::Cookie.new("x", "") - expect_raises IO::Error, "Invalid cookie value" do - cookie.value = %(foo\rbar) - end - expect_raises IO::Error, "Invalid cookie value" do - cookie.value = %(foo"bar) - end - expect_raises IO::Error, "Invalid cookie value" do - cookie.value = "foo;bar" - end - expect_raises IO::Error, "Invalid cookie value" do - cookie.value = "foo\\bar" - end - expect_raises IO::Error, "Invalid cookie value" do - cookie.value = "foo\\bar" - end - expect_raises IO::Error, "Invalid cookie value" do - cookie.value = "foo bar" - end - expect_raises IO::Error, "Invalid cookie value" do - cookie.value = "foo,bar" + invalid_values = { + '"', ',', ';', '\\', # invalid printable ascii characters + ' ', '\r', '\t', '\n', # non-printable ascii characters + }.map { |c| "foo#{c}bar" } + + invalid_values.each do |invalid_value| + expect_raises IO::Error, "Invalid cookie value" do + cookie.value = invalid_value + end end end end diff --git a/src/base64.cr b/src/base64.cr index 2457768daa00..ddb783dfe49e 100644 --- a/src/base64.cr +++ b/src/base64.cr @@ -262,7 +262,7 @@ module Base64 break if bytes > fin # Move the pointer by one byte until there is a valid base64 character - while bytes.value == NL || bytes.value == NR + while bytes.value.in?(NL, NR) bytes += 1 end break if bytes > fin @@ -272,7 +272,7 @@ module Base64 end # Move the pointer by one byte until there is a valid base64 character or the end of `bytes` was reached - while (bytes < fin + 4) && (bytes.value == NL || bytes.value == NR) + while (bytes < fin + 4) && bytes.value.in?(NL, NR) bytes += 1 end diff --git a/src/http/cookie.cr b/src/http/cookie.cr index d22fdf1419d0..9dc5517fa05d 100644 --- a/src/http/cookie.cr +++ b/src/http/cookie.cr @@ -58,7 +58,11 @@ module HTTP # valid characters for cookie-name per https://tools.ietf.org/html/rfc6265#section-4.1.1 # and https://tools.ietf.org/html/rfc2616#section-2.2 # "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~" - unless (0x21...0x7f).includes?(byte) && byte != 0x22 && byte != 0x28 && byte != 0x29 && byte != 0x2c && byte != 0x2f && !(0x3a..0x40).includes?(byte) && !(0x5b..0x5d).includes?(byte) && byte != 0x7b && byte != 0x7d + if !byte.in?(0x21...0x7f) || # Non-printable ASCII character + byte.in?(0x22, 0x28, 0x29, 0x2c, 0x2f) || # '"', '(', ')', ',', '/' + byte.in?(0x3a..0x40) || # ':', ';', '<', '=', '>', '?', '@' + byte.in?(0x5b..0x5d) || # '[', '\\', ']' + byte.in?(0x7b, 0x7d) # '{', '}' raise IO::Error.new("Invalid cookie name") end end @@ -76,7 +80,7 @@ module HTTP value.each_byte do |byte| # valid characters for cookie-value per https://tools.ietf.org/html/rfc6265#section-4.1.1 # all printable ASCII characters except ' ', ',', '"', ';' and '\\' - unless (0x21...0x7f).includes?(byte) && byte != 0x22 && byte != 0x2c && byte != 0x3b && byte != 0x5c + if !byte.in?(0x21...0x7f) || byte.in?(0x22, 0x2c, 0x3b, 0x5c) raise IO::Error.new("Invalid cookie value") end end