Index: [Article Count Order] [Thread]

Date:  Wed, 7 Jul 2010 00:28:51 +0900
From:  とみたまさひろ <tommy@...>
Subject:  cgi.rb でアップロードファイルと同じサイズのメモリを使用する
To:  modruby-ja@...
Message-Id:  <20100707002851.b62b4e1b.tommy@...>
X-Mail-Count: 00473

とみたです。

# github の方に書いてしまったんですが、MLがあったのを思い出したので、こちらでも。

mod_ruby で cgi.rb を使用すると、CGI.new 時にアップロードしたファイルと
同じサイズのメモリを使用してしまいます。

request.c の read_client_block() で apr_palloc() でメモリを獲得していま
すが、これがアップロードファイルを全部読むまで繰り返し呼ばれるため、結
果としてアップロードファイルと同じサイズのメモリが獲得されてしまいます。

apr_palloc() で獲得しているメモリ buf は rb_str_cat() 後は不要なため、
apr_palloc() ではなくて、この関数内で malloc() & free() した方がいいの
ではないかと思うのですが、いかがでしょうか。

次のパッチのような感じで…。

# このままだと malloc() に失敗した時の処理とか、rb_str_cat() で例外が上
# がった時の free() のことを考慮してないので、イマイチですが…。

--- request.c.orig	2008-11-08 12:57:19.000000000 +0900
+++ request.c	2010-07-07 00:02:28.503923720 +0900
@@ -980,7 +980,7 @@
     if (ap_should_client_block(r)) {
 	if (len < 0)
 	    len = r->remaining;
-	buf = (char *) apr_palloc(r->pool, len);
+        buf = (char *) malloc(len);
 	result = rb_tainted_str_new("", 0);
 	while (len > 0) {
 	    nrd = ap_get_client_block(r, buf, len);
@@ -989,11 +989,13 @@
 	    }
 	    if (nrd == -1) {
 		r->read_length += old_read_length;
+                free(buf);
 		rb_raise(rb_eApachePrematureChunkEndError, "premature chunk end");
 	    }
 	    rb_str_cat(result, buf, nrd);
 	    len -= nrd;
 	}
+        free(buf);
     }
     else {
 	result = Qnil;

-- 
とみたまさひろ <tommy@...>
D68F 8F55 7F6C 5908 88EB  1EBA 25ED DEE7 BBE8 1752