zlib.c: memory leak in gunzip
* ext/zlib/zlib.c (zlib_gunzip): clear zstream to fix memory leak. [ruby-core:83162] [Bug #13982] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60130 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4f966c0a68
commit
b268da23d2
@ -4287,7 +4287,7 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE klass)
|
||||
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 klass)
|
||||
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 klass)
|
||||
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)
|
||||
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)
|
||||
struct gzfile *gz = &gz0;
|
||||
int err;
|
||||
VALUE dst;
|
||||
VALUE guard;
|
||||
|
||||
StringValue(src);
|
||||
|
||||
@ -4364,6 +4377,7 @@ zlib_gunzip(VALUE klass, VALUE src)
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1196,5 +1196,13 @@ if defined? Zlib
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user