[前][次][番号順一覧][スレッド一覧]

ruby-changes:48016

From: nobu <ko1@a...>
Date: Fri, 6 Oct 2017 22:41:42 +0900 (JST)
Subject: [ruby-changes:48016] nobu:r60130 (trunk): zlib.c: memory leak in gunzip

nobu	2017-10-06 22:41:37 +0900 (Fri, 06 Oct 2017)

  New Revision: 60130

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60130

  Log:
    zlib.c: memory leak in gunzip
    
    * ext/zlib/zlib.c (zlib_gunzip): clear zstream to fix memory leak.
      [ruby-core:83162] [Bug #13982]

  Modified files:
    trunk/ext/zlib/zlib.c
    trunk/test/zlib/test_zlib.rb
Index: test/zlib/test_zlib.rb
===================================================================
--- test/zlib/test_zlib.rb	(revision 60129)
+++ test/zlib/test_zlib.rb	(revision 60130)
@@ -1196,5 +1196,13 @@ if defined? Zlib https://github.com/ruby/ruby/blob/trunk/test/zlib/test_zlib.rb#L1196
       src = %w[1f8b080000000000000].pack("H*")
       assert_raise(Zlib::GzipFile::Error){ Zlib.gunzip(src) }
     end
+
+    def test_gunzip_no_memory_leak
+      assert_no_memory_leak(%[-rzlib], "#{<<~"{#"}", "#{<<~'};'}")
+      d = Zlib.gzip("data")
+      {#
+        10_000.times {Zlib.gunzip(d)}
+      };
+    end
   end
 end
Index: ext/zlib/zlib.c
===================================================================
--- ext/zlib/zlib.c	(revision 60129)
+++ ext/zlib/zlib.c	(revision 60130)
@@ -4287,7 +4287,7 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4287
     struct gzfile *gz = &gz0;
     long len;
     int err;
-    VALUE src, opts, level=Qnil, strategy=Qnil;
+    VALUE src, opts, level=Qnil, strategy=Qnil, guard, ret;
 
     if (OPTHASH_GIVEN_P(opts)) {
 	ID keyword_ids[2];
@@ -4311,6 +4311,7 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4311
     if (err != Z_OK) {
 	raise_zlib_error(err, gz->z.stream.msg);
     }
+    guard = TypedData_Wrap_Struct(0, &gzfile_data_type, gz);
     ZSTREAM_READY(&gz->z);
     gzfile_make_header(gz);
     len = RSTRING_LEN(src);
@@ -4320,7 +4321,10 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4321
 	zstream_run(&gz->z, ptr, len, Z_NO_FLUSH);
     }
     gzfile_close(gz, 0);
-    return zstream_detach_buffer(&gz->z);
+    ret = zstream_detach_buffer(&gz->z);
+    zstream_end(&gz->z);
+    DATA_PTR(guard) = 0;
+    return ret;
 }
 
 static void
@@ -4331,6 +4335,14 @@ zlib_gunzip_end(struct gzfile *gz) https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4335
     zstream_end(&gz->z);
 }
 
+static void
+zlib_gunzip_guard_end(VALUE guard)
+{
+    struct gzfile *gz = DATA_PTR(guard);
+    DATA_PTR(guard) = 0;
+    gz->end(gz);
+}
+
 /*
  * call-seq:
  *   Zlib.gunzip(src) -> String
@@ -4356,6 +4368,7 @@ zlib_gunzip(VALUE klass, VALUE src) https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4368
     struct gzfile *gz = &gz0;
     int err;
     VALUE dst;
+    VALUE guard;
 
     StringValue(src);
 
@@ -4364,6 +4377,7 @@ zlib_gunzip(VALUE klass, VALUE src) https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4377
     if (err != Z_OK) {
 	raise_zlib_error(err, gz->z.stream.msg);
     }
+    guard = TypedData_Wrap_Struct(0, &gzfile_data_type, gz);
     gz->io = Qundef;
     gz->z.input = src;
     ZSTREAM_READY(&gz->z);
@@ -4371,11 +4385,14 @@ zlib_gunzip(VALUE klass, VALUE src) https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4385
     dst = zstream_detach_buffer(&gz->z);
     gzfile_calc_crc(gz, dst);
     if (!ZSTREAM_IS_FINISHED(&gz->z)) {
+	zlib_gunzip_guard_end(guard);
 	rb_raise(cGzError, "unexpected end of file");
     }
-    if (NIL_P(gz->z.input))
+    if (NIL_P(gz->z.input)) {
+	zlib_gunzip_guard_end(guard);
 	rb_raise(cNoFooter, "footer is not found");
-    gzfile_check_footer(gz);
+    }
+    zlib_gunzip_guard_end(guard);
     return dst;
 }
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]