Skip to content

Encoding::CompatibilityError in Rack::MethodOverride #2414

@bquorning

Description

@bquorning

When a multipart request is handled by Rack::MethodOverride, and one of the parts is using an encoding that is not compatible with ASCII (as per Encoding#ascii_compatible?), an Encoding::CompatibilityError exceptionis raised.

I wrote the following script to show which encodings cause the error:

gem "rack", "3.2.4"

require "rack/mock_request"
require "rack/method_override"

APP = Rack::MethodOverride.new(
  proc do
    [200, { "content-type" => "text/plain" }, []]
  end
)

def multipart_request_with_encoding(encoding)
  input = <<~EOF
    --AaB03x\r
    content-type: text/plain; charset=#{encoding.name}\r
    \r
    contents\r
    --AaB03x--\r
  EOF

  env = Rack::MockRequest.env_for(
    "/",
    "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
    "CONTENT_LENGTH" => input.size.to_s,
    :method => "POST",
    :input => input
  )
  APP.call(env)

  return env
end

puts "\n== ASCII compatible"
Encoding.list.select(&:ascii_compatible?).each do |encoding|
  response = multipart_request_with_encoding(encoding)
  puts "Success: #{encoding}"
rescue
  puts "Failed: #{encoding}"
end

puts "\n== ASCII incompatible"
Encoding.list.reject(&:ascii_compatible?).each do |encoding|
  multipart_request_with_encoding(encoding)
  puts "Success: #{encoding}"
rescue
  puts "Failed: #{encoding}"
end

puts "\n== Show the backtrace"
begin
  multipart_request_with_encoding(Encoding::UTF_16LE)
rescue => e
  puts e.backtrace.map { |line| line.sub(%r{^.*/gems/}, ".../gems/") }
end

The script’s output, ending with the full stacktrace:

== ASCII compatible
Success: ASCII-8BIT
Success: UTF-8
Success: US-ASCII
Success: UTF8-MAC
Success: EUC-JP
Success: Windows-31J
Success: Big5
Success: Big5-HKSCS
Success: Big5-UAO
Success: CESU-8
Success: CP949
Success: Emacs-Mule
Success: EUC-KR
Success: EUC-TW
Success: GB18030
Success: GBK
Success: ISO-8859-1
Success: ISO-8859-2
Success: ISO-8859-3
Success: ISO-8859-4
Success: ISO-8859-5
Success: ISO-8859-6
Success: ISO-8859-7
Success: ISO-8859-8
Success: ISO-8859-9
Success: ISO-8859-10
Success: ISO-8859-11
Success: ISO-8859-13
Success: ISO-8859-14
Success: ISO-8859-15
Success: ISO-8859-16
Success: KOI8-R
Success: KOI8-U
Success: Shift_JIS
Success: Windows-1250
Success: Windows-1251
Success: Windows-1252
Success: Windows-1253
Success: Windows-1254
Success: Windows-1257
Success: IBM437
Success: IBM720
Success: IBM737
Success: IBM775
Success: CP850
Success: IBM852
Success: CP852
Success: IBM855
Success: CP855
Success: IBM857
Success: IBM860
Success: IBM861
Success: IBM862
Success: IBM863
Success: IBM864
Success: IBM865
Success: IBM866
Success: IBM869
Success: Windows-1258
Success: GB1988
Success: macCentEuro
Success: macCroatian
Success: macCyrillic
Success: macGreek
Success: macIceland
Success: macRoman
Success: macRomania
Success: macThai
Success: macTurkish
Success: macUkraine
Success: CP950
Success: CP951
Success: stateless-ISO-2022-JP
Success: eucJP-ms
Success: CP51932
Success: EUC-JIS-2004
Success: GB2312
Success: GB12345
Success: Windows-1256
Success: Windows-1255
Success: TIS-620
Success: Windows-874
Success: MacJapanese
Success: UTF8-DoCoMo
Success: SJIS-DoCoMo
Success: UTF8-KDDI
Success: SJIS-KDDI
Success: stateless-ISO-2022-JP-KDDI
Success: UTF8-SoftBank
Success: SJIS-SoftBank

== ASCII incompatible
Failed: UTF-16BE
Failed: UTF-16LE
Failed: UTF-32BE
Failed: UTF-32LE
Failed: UTF-16
Failed: UTF-32
Failed: IBM037
Success: ISO-2022-JP
Failed: ISO-2022-JP-2
Failed: CP50220
Failed: CP50221
Failed: UTF-7
Failed: ISO-2022-JP-KDDI

== Show the backtrace
.../gems/rack-3.2.4/lib/rack/query_parser.rb:136:in 'String#index'
.../gems/rack-3.2.4/lib/rack/query_parser.rb:136:in 'Rack::QueryParser#_normalize_params'
.../gems/rack-3.2.4/lib/rack/query_parser.rb:125:in 'Rack::QueryParser#normalize_params'
.../gems/rack-3.2.4/lib/rack/request.rb:686:in 'block in Rack::Request::Helpers#expand_param_pairs'
.../gems/rack-3.2.4/lib/rack/request.rb:685:in 'Array#each'
.../gems/rack-3.2.4/lib/rack/request.rb:685:in 'Rack::Request::Helpers#expand_param_pairs'
.../gems/rack-3.2.4/lib/rack/request.rb:550:in 'Rack::Request::Helpers#POST'
.../gems/rack-3.2.4/lib/rack/method_override.rb:49:in 'Rack::MethodOverride#method_override_param'
.../gems/rack-3.2.4/lib/rack/method_override.rb:33:in 'Rack::MethodOverride#method_override'
.../gems/rack-3.2.4/lib/rack/method_override.rb:21:in 'Rack::MethodOverride#call'
test_rack_multipart_request.rb:28:in 'Object#multipart_request_with_encoding'
test_rack_multipart_request.rb:51:in '<main>'

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions