mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
merge revision(s) 60042,60130,60131: [Backport #13982]
ext: adjust indent [ci skip] zlib.c: memory leak in gunzip * ext/zlib/zlib.c (zlib_gunzip): clear zstream to fix memory leak. [ruby-core:83162] [Bug #13982] 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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62172 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
05ba99388d
commit
ce2bc45ae8
8 changed files with 105 additions and 65 deletions
|
@ -4245,6 +4245,14 @@ rb_gzreader_external_encoding(VALUE self)
|
||||||
return rb_enc_from_encoding(get_gzfile(self)->enc);
|
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
|
static void
|
||||||
zlib_gzip_end(struct gzfile *gz)
|
zlib_gzip_end(struct gzfile *gz)
|
||||||
{
|
{
|
||||||
|
@ -4257,6 +4265,7 @@ zlib_gzip_end(struct gzfile *gz)
|
||||||
#define OPTHASH_GIVEN_P(opts) \
|
#define OPTHASH_GIVEN_P(opts) \
|
||||||
(argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
|
(argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
|
||||||
static ID id_level, id_strategy;
|
static ID id_level, id_strategy;
|
||||||
|
static VALUE zlib_gzip_run(VALUE arg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
|
@ -4285,9 +4294,8 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE klass)
|
||||||
{
|
{
|
||||||
struct gzfile gz0;
|
struct gzfile gz0;
|
||||||
struct gzfile *gz = &gz0;
|
struct gzfile *gz = &gz0;
|
||||||
long len;
|
|
||||||
int err;
|
int err;
|
||||||
VALUE src, opts, level=Qnil, strategy=Qnil;
|
VALUE src, opts, level=Qnil, strategy=Qnil, args[2];
|
||||||
|
|
||||||
if (OPTHASH_GIVEN_P(opts)) {
|
if (OPTHASH_GIVEN_P(opts)) {
|
||||||
ID keyword_ids[2];
|
ID keyword_ids[2];
|
||||||
|
@ -4309,9 +4317,23 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE klass)
|
||||||
err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
|
err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
|
||||||
-MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
|
-MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
|
||||||
if (err != Z_OK) {
|
if (err != Z_OK) {
|
||||||
|
zlib_gzip_end(gz);
|
||||||
raise_zlib_error(err, gz->z.stream.msg);
|
raise_zlib_error(err, gz->z.stream.msg);
|
||||||
}
|
}
|
||||||
ZSTREAM_READY(&gz->z);
|
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);
|
gzfile_make_header(gz);
|
||||||
len = RSTRING_LEN(src);
|
len = RSTRING_LEN(src);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
|
@ -4327,10 +4349,11 @@ static void
|
||||||
zlib_gunzip_end(struct gzfile *gz)
|
zlib_gunzip_end(struct gzfile *gz)
|
||||||
{
|
{
|
||||||
gz->z.flags |= ZSTREAM_FLAG_CLOSING;
|
gz->z.flags |= ZSTREAM_FLAG_CLOSING;
|
||||||
gzfile_check_footer(gz);
|
|
||||||
zstream_end(&gz->z);
|
zstream_end(&gz->z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE zlib_gunzip_run(VALUE arg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* Zlib.gunzip(src) -> String
|
* Zlib.gunzip(src) -> String
|
||||||
|
@ -4355,7 +4378,6 @@ zlib_gunzip(VALUE klass, VALUE src)
|
||||||
struct gzfile gz0;
|
struct gzfile gz0;
|
||||||
struct gzfile *gz = &gz0;
|
struct gzfile *gz = &gz0;
|
||||||
int err;
|
int err;
|
||||||
VALUE dst;
|
|
||||||
|
|
||||||
StringValue(src);
|
StringValue(src);
|
||||||
|
|
||||||
|
@ -4367,14 +4389,24 @@ zlib_gunzip(VALUE klass, VALUE src)
|
||||||
gz->io = Qundef;
|
gz->io = Qundef;
|
||||||
gz->z.input = src;
|
gz->z.input = src;
|
||||||
ZSTREAM_READY(&gz->z);
|
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);
|
gzfile_read_header(gz);
|
||||||
dst = zstream_detach_buffer(&gz->z);
|
dst = zstream_detach_buffer(&gz->z);
|
||||||
gzfile_calc_crc(gz, dst);
|
gzfile_calc_crc(gz, dst);
|
||||||
if (!ZSTREAM_IS_FINISHED(&gz->z)) {
|
if (!ZSTREAM_IS_FINISHED(&gz->z)) {
|
||||||
rb_raise(cGzError, "unexpected end of file");
|
rb_raise(cGzError, "unexpected end of file");
|
||||||
}
|
}
|
||||||
if (NIL_P(gz->z.input))
|
if (NIL_P(gz->z.input)) {
|
||||||
rb_raise(cNoFooter, "footer is not found");
|
rb_raise(cNoFooter, "footer is not found");
|
||||||
|
}
|
||||||
gzfile_check_footer(gz);
|
gzfile_check_footer(gz);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1196,5 +1196,13 @@ if defined? Zlib
|
||||||
src = %w[1f8b080000000000000].pack("H*")
|
src = %w[1f8b080000000000000].pack("H*")
|
||||||
assert_raise(Zlib::GzipFile::Error){ Zlib.gunzip(src) }
|
assert_raise(Zlib::GzipFile::Error){ Zlib.gunzip(src) }
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#define RUBY_VERSION "2.4.4"
|
#define RUBY_VERSION "2.4.4"
|
||||||
#define RUBY_RELEASE_DATE "2018-02-03"
|
#define RUBY_RELEASE_DATE "2018-02-03"
|
||||||
#define RUBY_PATCHLEVEL 229
|
#define RUBY_PATCHLEVEL 230
|
||||||
|
|
||||||
#define RUBY_RELEASE_YEAR 2018
|
#define RUBY_RELEASE_YEAR 2018
|
||||||
#define RUBY_RELEASE_MONTH 2
|
#define RUBY_RELEASE_MONTH 2
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue