summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-11-19 20:51:57 +0000
committerEric Wong <normalperson@yhbt.net>2010-11-20 06:51:58 +0800
commit5bc239fd154a7eaebeb024394f8e0b507bbf4c5a (patch)
tree1962f3f02e5fb7dfe0b3f533e053b8d1bee330fb
parentd12e10ea88c7adeb97094e4b835201e4c2ce52ab (diff)
No need to accept any number of args, that could hide bugs in
applications that could give three or more arguments.  We also
raise ArgumentError when given a negative length argument to
read.
-rw-r--r--lib/unicorn/stream_input.rb37
-rw-r--r--test/unit/test_stream_input.rb7
2 files changed, 20 insertions, 24 deletions
diff --git a/lib/unicorn/stream_input.rb b/lib/unicorn/stream_input.rb
index ef8997e..45d1336 100644
--- a/lib/unicorn/stream_input.rb
+++ b/lib/unicorn/stream_input.rb
@@ -39,28 +39,25 @@ class Unicorn::StreamInput
   # ios.read(length [, buffer]) will return immediately if there is
   # any data and only block when nothing is available (providing
   # IO#readpartial semantics).
-  def read(*args)
-    length = args.shift
-    rv = args.shift || ''
-    if length.nil?
-      read_all(rv)
-    else
+  def read(length = nil, rv = '')
+    if length
       if length <= @rbuf.size
-        rv.replace(@rbuf.slice(0, length))
-        @rbuf.replace(@rbuf.slice(length, @rbuf.size) || '')
+        length < 0 and raise ArgumentError, "negative length #{length} given"
+        rv.replace(@rbuf.slice!(0, length))
       else
-        rv.replace(@rbuf)
-        length -= @rbuf.size
-        @rbuf.replace('')
-        until length == 0 || eof? || (rv.size > 0 && @chunked)
-          @socket.kgio_read(length, @buf) or eof!
+        to_read = length - @rbuf.size
+        rv.replace(@rbuf.slice!(0, @rbuf.size))
+        until to_read == 0 || eof? || (rv.size > 0 && @chunked)
+          @socket.kgio_read(to_read, @buf) or eof!
           filter_body(@rbuf, @buf)
           rv << @rbuf
-          length -= @rbuf.size
-          @rbuf.replace('')
+          to_read -= @rbuf.size
         end
+        @rbuf.replace('')
       end
       rv = nil if rv.empty? && length != 0
+    else
+      read_all(rv)
     end
     rv
   end
@@ -84,15 +81,7 @@ class Unicorn::StreamInput
 
     begin
       @rbuf.gsub!(re, '') and return $1
-      if eof?
-        if @rbuf.empty?
-          return nil
-        else
-          rv = @rbuf.dup
-          @rbuf.replace('')
-          return rv
-        end
-      end
+      return @rbuf.empty? ? nil : @rbuf.slice!(0, @rbuf.size) if eof?
       @socket.kgio_read(@@io_chunk_size, @buf) or eof!
       filter_body(once = '', @buf)
       @rbuf << once
diff --git a/test/unit/test_stream_input.rb b/test/unit/test_stream_input.rb
index adf4571..0c4ec98 100644
--- a/test/unit/test_stream_input.rb
+++ b/test/unit/test_stream_input.rb
@@ -21,6 +21,13 @@ class TestStreamInput < Test::Unit::TestCase
     Process.waitall
   end
 
+  def test_read_negative
+    r = init_request('hello')
+    si = Unicorn::StreamInput.new(@rd, r)
+    assert_raises(ArgumentError) { si.read(-1) }
+    assert_equal 'hello', si.read
+  end
+
   def test_read_small
     r = init_request('hello')
     si = Unicorn::StreamInput.new(@rd, r)