about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-08-30 22:27:25 -0700
committerEric Wong <normalperson@yhbt.net>2009-09-01 11:30:23 -0700
commita6e410b7f85f22e6adbc55eb9dd3a494ca7200b2 (patch)
treed92ed989d4bbb7a5764d2bd7d3c9aba69158b7d2
parenta6978053b9e9f4eff3e54bda6b4aa0c06f707075 (diff)
downloadclogger-a6e410b7f85f22e6adbc55eb9dd3a494ca7200b2.tar.gz
We're not Rack::Lint, but we still need to take steps to
avoid segfaulting if we host non-Rack::Lint-compliant
applications.

This also updates the pure variant to fail on bad applications,
too.
-rw-r--r--ext/clogger_ext/clogger.c11
-rw-r--r--lib/clogger/pure.rb7
-rw-r--r--test/test_clogger.rb7
3 files changed, 23 insertions, 2 deletions
diff --git a/ext/clogger_ext/clogger.c b/ext/clogger_ext/clogger.c
index 369baf6..19386e5 100644
--- a/ext/clogger_ext/clogger.c
+++ b/ext/clogger_ext/clogger.c
@@ -185,7 +185,7 @@ static int str_case_eq(VALUE a, VALUE b)
 struct response_ops { long nr; VALUE ops; };
 
 /* this can be worse than O(M*N) :<... but C loops are fast ... */
-static VALUE swap_sent_headers(VALUE kv, VALUE memo)
+static VALUE swap_sent_headers_unsafe(VALUE kv, VALUE memo)
 {
         struct response_ops *tmp = (struct response_ops *)memo;
         VALUE key = rb_obj_as_string(RARRAY_PTR(kv)[0]);
@@ -214,6 +214,15 @@ static VALUE swap_sent_headers(VALUE kv, VALUE memo)
         return Qnil;
 }
 
+static VALUE swap_sent_headers(VALUE kv, VALUE memo)
+{
+        if (TYPE(kv) != T_ARRAY)
+                rb_raise(rb_eTypeError, "headers not returning pairs");
+        if (RARRAY_LEN(kv) < 2)
+                rb_raise(rb_eTypeError, "headers not returning pairs");
+        return swap_sent_headers_unsafe(kv, memo);
+}
+
 static VALUE sent_headers_ops(struct clogger *c)
 {
         struct response_ops tmp;
diff --git a/lib/clogger/pure.rb b/lib/clogger/pure.rb
index f593af0..0a7aa24 100644
--- a/lib/clogger/pure.rb
+++ b/lib/clogger/pure.rb
@@ -133,7 +133,12 @@ private
   end
 
   def get_sent_header(headers, match)
-    headers.each { |key, value| match == key.downcase and return value }
+    headers.each do |pair|
+      Array === pair && pair.size >= 2 or
+        raise TypeError, "headers not returning pairs"
+      key, value = pair
+      match == key.downcase and return value
+    end
     "-"
   end
 
diff --git a/test/test_clogger.rb b/test/test_clogger.rb
index d2121da..9cb494a 100644
--- a/test/test_clogger.rb
+++ b/test/test_clogger.rb
@@ -373,4 +373,11 @@ class TestClogger < Test::Unit::TestCase
     assert_match %r{#{e}$}m, str
   end
 
+  def test_broken_header_response
+    str = StringIO.new
+    app = lambda { |env| [302, [ %w(a) ], []] }
+    cl = Clogger.new(app, :logger => str, :format => '$sent_http_set_cookie')
+    assert_raise(TypeError) { cl.call(@req) }
+  end
+
 end