public
Description: A very fast & simple Ruby web server
Homepage: http://code.macournoyer.com/thin/
Clone URL: git://github.com/macournoyer/thin.git
Search Repo:
Fix server crash when header too large.
macournoyer (author)
Sat Apr 05 21:21:08 -0700 2008
commit  f450ccf6a84941860d7884e94f061c7bc50623aa
tree    7a242b7d01592e85a251e025d3e258ef96c8056d
parent  a3a783e2ffe03eebde8c329479b8e15dc0b3d21a
...
1
 
2
3
4
...
1
2
3
4
5
0
@@ -1,4 +1,5 @@
0
 == 0.8.0 Dodgy Dentist release
0
+ * Fix server crash when header too large.
0
  * Add --require (-r) option to require a library, before executing your script.
0
  * Rename --rackup short option to -R, warn and load as rackup when file ends with .ru.
0
  * List supported adapters in command usage.
...
12
13
14
 
15
16
17
...
69
70
71
 
 
72
73
74
...
12
13
14
15
16
17
18
...
70
71
72
73
74
75
76
77
0
@@ -12,6 +12,7 @@
0
     # and into a tempfile for reading.
0
     MAX_BODY = 1024 * (80 + 32)
0
     BODY_TMPFILE = 'thin-body'.freeze
0
+ MAX_HEADER = 1024 * (80 + 32)
0
     
0
     # Freeze some HTTP header names & values
0
     SERVER_SOFTWARE = 'SERVER_SOFTWARE'.freeze
0
@@ -69,6 +70,8 @@
0
         body << data
0
       else # Parse more header using the super parser
0
         @data << data
0
+ raise InvalidRequest, 'Header longer than allowed' if @data.size > MAX_HEADER
0
+
0
         @nparsed = @parser.execute(@env, @data, @nparsed)
0
 
0
         # Transfert to a tempfile if body is very big
...
172
173
174
 
 
 
 
175
...
172
173
174
175
176
177
178
179
0
@@ -172,5 +172,9 @@
0
       parser.should_not have_error
0
     end
0
   end
0
+
0
+ it "should fails on heders larger then MAX_HEADER" do
0
+ proc { R("GET / HTTP/1.1\r\nFoo: #{'X' * Request::MAX_HEADER}\r\n\r\n") }.should raise_error(InvalidRequest)
0
+ end
0
 end
...
15
16
17
 
18
19
20
 
 
21
22
 
23
24
25
26
27
28
29
30
31
32
33
34
35
 
 
 
 
 
36
37
38
...
15
16
17
18
19
 
 
20
21
22
 
23
24
25
26
27
28
29
 
 
 
 
 
 
 
30
31
32
33
34
35
36
37
0
@@ -15,24 +15,23 @@
0
   end
0
 
0
   it "should move body to tempfile when too big" do
0
+ len = Request::MAX_BODY + 2
0
     request = Request.new
0
- request.parse("POST /postit HTTP/1.1\r\nContent-Length: #{Request::MAX_BODY*2}\r\n\r\n#{'X' * Request::MAX_BODY}")
0
- request.parse('X' * Request::MAX_BODY)
0
+ request.parse("POST /postit HTTP/1.1\r\nContent-Length: #{len}\r\n\r\n#{'X' * (len/2)}")
0
+ request.parse('X' * (len/2))
0
 
0
- request.body.size.should == Request::MAX_BODY * 2
0
+ request.body.size.should == len
0
     request.should be_finished
0
     request.body.class.should == Tempfile
0
   end
0
 
0
   it "should delete body tempfile when closing" do
0
     body = 'X' * (Request::MAX_BODY + 1)
0
-
0
- request = R(<<-EOS.chomp, true)
0
-POST /postit HTTP/1.1
0
-Content-Length: #{body.size}
0
-
0
-#{body}
0
-EOS
0
+
0
+ request = Request.new
0
+ request.parse("POST /postit HTTP/1.1\r\n")
0
+ request.parse("Content-Length: #{body.size}\r\n\r\n")
0
+ request.parse(body)
0
 
0
     request.body.path.should_not be_nil
0
     request.close
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
0
@@ -1 +1,35 @@
0
+require File.dirname(__FILE__) + '/../spec_helper'
0
+
0
+describe Server, 'robustness' do
0
+ before do
0
+ start_server do |env|
0
+ body = 'hello!'
0
+ [200, { 'Content-Type' => 'text/html', 'Content-Length' => body.size.to_s }, body]
0
+ end
0
+ end
0
+
0
+ it "should not crash when header too large" do
0
+ 100.times do
0
+ begin
0
+ socket = TCPSocket.new(DEFAULT_TEST_ADDRESS, DEFAULT_TEST_PORT)
0
+ socket.write("GET / HTTP/1.1\r\n")
0
+ socket.write("Host: localhost\r\n")
0
+ socket.write("Connection: close\r\n")
0
+ 10000.times do
0
+ socket.write("X-Foo: #{'x' * 100}\r\n")
0
+ socket.flush
0
+ end
0
+ socket.write("\r\n")
0
+ socket.read
0
+ socket.close
0
+ rescue Errno::EPIPE, Errno::ECONNRESET
0
+ # Ignore.
0
+ end
0
+ end
0
+ end
0
+
0
+ after do
0
+ stop_server
0
+ end
0
+end

Comments

    No one has commented yet.