about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-01-21 04:01:02 +0000
committerEric Wong <normalperson@yhbt.net>2011-01-21 08:23:04 +0000
commitc4d77de381c40cf315e6f84791e3fb634bc10675 (patch)
tree46b6ea4df530d9c4cd1aa799126fd2ce03db3f75
parent4150a398a48b9bca96aa623380161229ac0f8622 (diff)
downloadunicorn-c4d77de381c40cf315e6f84791e3fb634bc10675.tar.gz
Rainbows! can then use this to bypass luserspace given
the correct offset is set before hand and the file
is unlinked.
-rw-r--r--lib/unicorn/app/exec_cgi.rb38
1 files changed, 20 insertions, 18 deletions
diff --git a/lib/unicorn/app/exec_cgi.rb b/lib/unicorn/app/exec_cgi.rb
index fea22f6..be89869 100644
--- a/lib/unicorn/app/exec_cgi.rb
+++ b/lib/unicorn/app/exec_cgi.rb
@@ -28,6 +28,24 @@ module Unicorn::App
       SERVER_SOFTWARE
     ).map { |x| x.freeze } # frozen strings are faster for Hash assignments
 
+    class Body < Unicorn::TmpIO
+      def body_offset=(n)
+        sysseek(@body_offset = n)
+      end
+
+      def each(&block)
+        sysseek @body_offset
+        # don't use a preallocated buffer for sysread since we can't
+        # guarantee an actual socket is consuming the yielded string
+        # (or if somebody is pushing to an array for eventual concatenation
+        begin
+          yield sysread(CHUNK_SIZE)
+        rescue EOFError
+          break
+        end while true
+      end
+    end
+
     # Intializes the app, example of usage in a config.ru
     #   map "/cgit" do
     #     run Unicorn::App::ExecCgi.new("/path/to/cgit.cgi")
@@ -43,7 +61,7 @@ module Unicorn::App
 
     # Calls the app
     def call(env)
-      out, err = Unicorn::TmpIO.new, Unicorn::TmpIO.new
+      out, err = Body.new, Unicorn::TmpIO.new
       inp = force_file_input(env)
       pid = fork { run_child(inp, out, err, env) }
       inp.close
@@ -87,23 +105,7 @@ module Unicorn::App
         offset = 4
       end
       offset += head.length
-
-      # Allows +out+ to be used as a Rack body.
-      out.instance_eval { class << self; self; end }.instance_eval {
-        define_method(:each) { |&blk|
-          sysseek(offset)
-
-          # don't use a preallocated buffer for sysread since we can't
-          # guarantee an actual socket is consuming the yielded string
-          # (or if somebody is pushing to an array for eventual concatenation
-          begin
-            blk.call(sysread(CHUNK_SIZE))
-          rescue EOFError
-            break
-          end while true
-        }
-      }
-
+      out.body_offset = offset
       size -= offset
       prev = nil
       headers = Rack::Utils::HeaderHash.new