@@ -336,6 +336,9 @@ def encode_multipart_form_data(out, params, opt)
336336 boundary = opt [ :boundary ]
337337 require 'securerandom' unless defined? ( SecureRandom )
338338 boundary ||= SecureRandom . urlsafe_base64 ( 40 )
339+ if /[\r \n ]/ . match? ( boundary . to_s )
340+ raise ArgumentError , "multipart boundary cannot include CR/LF"
341+ end
339342 chunked_p = chunked?
340343
341344 buf = +''
@@ -349,7 +352,10 @@ def encode_multipart_form_data(out, params, opt)
349352 buf << "--#{ boundary } \r \n "
350353 if filename
351354 filename = quote_string ( filename , charset )
352- type = h [ :content_type ] || 'application/octet-stream'
355+ type = ( h [ :content_type ] || 'application/octet-stream' ) . to_s
356+ if /[\r \n ]/ . match? ( type )
357+ raise ArgumentError , "field content type cannot include CR/LF"
358+ end
353359 buf << "Content-Disposition: form-data; " \
354360 "name=\" #{ key } \" ; filename=\" #{ filename } \" \r \n " \
355361 "Content-Type: #{ type } \r \n \r \n "
@@ -384,6 +390,9 @@ def encode_multipart_form_data(out, params, opt)
384390
385391 def quote_string ( str , charset )
386392 str = str . encode ( charset , fallback :-> ( c ) { '&#%d;' %c . encode ( "UTF-8" ) . ord } ) if charset
393+ if /[\r \n ]/ . match? ( str )
394+ raise ArgumentError , "multipart field name or filename cannot include CR/LF"
395+ end
387396 str . gsub ( /[\\ "]/ , '\\\\\&' )
388397 end
389398
0 commit comments