Tuesday, January 22, 2008

read_multipart fault with "bad boundary end of body part"

Intro

This one has been bugging be for ages, My application would fault at random times with, "bad boundary end of body part" from the read_multipart in ActionController. I finally took a very close look.

I have a form, with a quite few fields, uses can also add attachments so the post is via multipart.

I worked out the odds of this happening (once I found a solution) are approx 1 in 120, and was suprised this has not cropped up before. There cant be many rails apps, with large data entry screens using multipart out there

What happens in read_multipart

  • If your post content is greater than 10240 bytes, read_multipart fills up buff with 10240 bytes
  • The code to extract params, will see the "--boundary[CR][LF]" and extract the param and delete up to the bounday, and then loop for the next param
  • But if the buff ends with "--boundary[CR][LF]", on extracing the param the buff is zero length
  • But for some reason, If buff is zero a break is issued and then a fault happens

What wrong

  • A check for zero bytes read, is performed previously in the code, why do it again??
  • I cant figure out why you would check the buff for zero length??, when it is valid to be zero.

The fix

  • Dont break if buff is zero length !!

Edit /ruby/lib/ruby/gems/1.8/gems/actionpack-2.x.x/lib/action_controller/request.rb


def read_multipart(body, boundary, content_length, env)

  etc ...

 buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
    content.print $1
    if "--" == $2
      content_length = -1
    end
    boundary_end = $2.dup
    ""
  end
  
  etc ...

  # break if buf.size == 0 # Dont break on zero, as buf could end on a boundary !!! resulting in empty buff
  break if content_length == -1
  
  etc...

Rails Ticket

Checkout rails ticket 10886 just lodged for updates.

Finally

If some one knows why the buff zero length is/was needed, I would like to know

Google