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

ruby-changes:48017

From: nobu <ko1@a...>
Date: Sat, 7 Oct 2017 11:23:32 +0900 (JST)
Subject: [ruby-changes:48017] nobu:r60131 (trunk): zlib.c: ensure to free

nobu	2017-10-07 11:23:27 +0900 (Sat, 07 Oct 2017)

  New Revision: 60131

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

  Log:
    zlib.c: ensure to free
    
    * ext/zlib/zlib.c (zlib_gunzip): gz0 is a structure variable on
      the stack, no longer valid after exit by an exception.  ensure
      to free instead.  [Bug #13982]

  Modified files:
    trunk/ext/zlib/zlib.c
Index: ext/zlib/zlib.c
===================================================================
--- ext/zlib/zlib.c	(revision 60130)
+++ ext/zlib/zlib.c	(revision 60131)
@@ -4245,6 +4245,14 @@ rb_gzreader_external_encoding(VALUE self https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4245
     return rb_enc_from_encoding(get_gzfile(self)->enc);
 }
 
+static VALUE
+zlib_gzip_ensure(VALUE arg)
+{
+    struct gzfile *gz = (struct gzfile *)arg;
+    rb_rescue((VALUE(*)())gz->end, arg, NULL, Qnil);
+    return Qnil;
+}
+
 static void
 zlib_gzip_end(struct gzfile *gz)
 {
@@ -4257,6 +4265,7 @@ zlib_gzip_end(struct gzfile *gz) https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4265
 #define OPTHASH_GIVEN_P(opts) \
     (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
 static ID id_level, id_strategy;
+static VALUE zlib_gzip_run(VALUE arg);
 
 /*
  * call-seq:
@@ -4285,9 +4294,8 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4294
 {
     struct gzfile gz0;
     struct gzfile *gz = &gz0;
-    long len;
     int err;
-    VALUE src, opts, level=Qnil, strategy=Qnil, guard, ret;
+    VALUE src, opts, level=Qnil, strategy=Qnil, args[2];
 
     if (OPTHASH_GIVEN_P(opts)) {
 	ID keyword_ids[2];
@@ -4309,10 +4317,23 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4317
     err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
 		       -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
     if (err != Z_OK) {
+	zlib_gzip_end(gz);
 	raise_zlib_error(err, gz->z.stream.msg);
     }
-    guard = TypedData_Wrap_Struct(0, &gzfile_data_type, gz);
     ZSTREAM_READY(&gz->z);
+    args[0] = (VALUE)gz;
+    args[1] = src;
+    return rb_ensure(zlib_gzip_run, (VALUE)args, zlib_gzip_ensure, (VALUE)gz);
+}
+
+static VALUE
+zlib_gzip_run(VALUE arg)
+{
+    VALUE *args = (VALUE *)arg;
+    struct gzfile *gz = (struct gzfile *)args[0];
+    VALUE src = args[1];
+    long len;
+
     gzfile_make_header(gz);
     len = RSTRING_LEN(src);
     if (len > 0) {
@@ -4321,27 +4342,17 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4342
 	zstream_run(&gz->z, ptr, len, Z_NO_FLUSH);
     }
     gzfile_close(gz, 0);
-    ret = zstream_detach_buffer(&gz->z);
-    zstream_end(&gz->z);
-    DATA_PTR(guard) = 0;
-    return ret;
+    return zstream_detach_buffer(&gz->z);
 }
 
 static void
 zlib_gunzip_end(struct gzfile *gz)
 {
     gz->z.flags |= ZSTREAM_FLAG_CLOSING;
-    gzfile_check_footer(gz);
     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);
-}
+static VALUE zlib_gunzip_run(VALUE arg);
 
 /*
  * call-seq:
@@ -4367,8 +4378,6 @@ zlib_gunzip(VALUE klass, VALUE src) https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4378
     struct gzfile gz0;
     struct gzfile *gz = &gz0;
     int err;
-    VALUE dst;
-    VALUE guard;
 
     StringValue(src);
 
@@ -4377,22 +4386,28 @@ zlib_gunzip(VALUE klass, VALUE src) https://github.com/ruby/ruby/blob/trunk/ext/zlib/zlib.c#L4386
     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);
+    return rb_ensure(zlib_gunzip_run, (VALUE)gz, zlib_gzip_ensure, (VALUE)gz);
+}
+
+static VALUE
+zlib_gunzip_run(VALUE arg)
+{
+    struct gzfile *gz = (struct gzfile *)arg;
+    VALUE dst;
+
     gzfile_read_header(gz);
     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)) {
-	zlib_gunzip_guard_end(guard);
 	rb_raise(cNoFooter, "footer is not found");
     }
-    zlib_gunzip_guard_end(guard);
+    gzfile_check_footer(gz);
     return dst;
 }
 

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

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