From 6a583c260119cedb45bb6573aaa150d3d6777bcd Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Sun, 25 Oct 2026 00:32:50 +0900 Subject: [PATCH] Reject negative size in Zlib::ZStream#avail_out= A negative size was cast to a huge unsigned value, so avail_out became UINT_MAX while the buffer stayed small. z = Zlib::Inflate.new z.avail_out = -1 z.inflate(Zlib::Deflate.deflate("A" * 100_000)) #=> [BUG] probable buffer overflow: 100000 for 15 Co-Authored-By: Claude Opus 5.5 --- ext/zlib/zlib.c | 6 +++++- test/zlib/test_zlib.rb | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index bcdd32a..6d85f6e 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -1531,8 +1531,12 @@ static VALUE rb_zstream_set_avail_out(VALUE obj, VALUE size) { struct zstream *z = get_zstream(obj); + int n = NUM2INT(size); - zstream_expand_buffer_into(z, FIX2INT(size)); + if (n < 0) { + rb_raise(rb_eArgError, "negative size"); + } + zstream_expand_buffer_into(z, n); return size; } diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb index e1ecbf8..ac4bdde 100644 --- a/test/zlib/test_zlib.rb +++ b/test/zlib/test_zlib.rb @@ -132,6 +132,14 @@ def test_avail assert_equal("foobar", Zlib::Inflate.inflate(s)) end + def test_negative_avail_out + z = Zlib::Inflate.new + assert_raise(ArgumentError) { z.avail_out = -1 } + assert_equal("foo" * 100, z.inflate(Zlib::Deflate.deflate("foo" * 100))) + ensure + z&.close + end + def test_expand_buffer; z = Zlib::Deflate.new src = "baz" * 1000