zlib has a use-after-free when Zlib::Inflate#inflate or Zlib::Deflate#deflate is called recursively. The following script demonstrates the issue.
require "zlib"
require "securerandom"
GC.stress = true
zi = Zlib::Inflate.new
s = Zlib.deflate(SecureRandom.random_bytes(1024**2))
zi.inflate(s) do
zi.inflate(s)
end
If we run Ruby master (commit b680b632e5b88e4ea550de3f15cf6ef782efeb48) with Valgrind, we see use-after-free errors:
$ valgrind --leak-check=no --undef-value-errors=no ruby test.rb
==36376== Memcheck, a memory error detector
==36376== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==36376== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==36376== Command: ruby test.rb
==36376==
==36376== Warning: client switching stacks? SP change: 0x1ffe8020e0 --> 0x1fff0001b0
==36376== to suppress, use: --max-stackframe=8380624 or greater
==36376== Invalid read of size 8
==36376== at 0x484661F: memmove (vg_replace_strmem.c:1382)
==36376== by 0x2B967D: memcpy (string_fortified.h:34)
==36376== by 0x2B967D: ruby_nonempty_memcpy (memory.h:659)
==36376== by 0x2B967D: ruby_nonempty_memcpy (memory.h:656)
==36376== by 0x2B967D: str_buf_cat (string.c:3148)
==36376== by 0xA8FE30B: zstream_append_input (zlib.c:869)
==36376== by 0xA8FE30B: zstream_run0 (zlib.c:1135)
==36376== by 0xA8FE30B: zstream_run_synchronized (zlib.c:1156)
==36376== by 0x144B73: rb_ensure (eval.c:993)
==36376== by 0xA8FA4D5: zstream_run (zlib.c:1168)
==36376== by 0xA8FA4D5: do_inflate (zlib.c:2041)
==36376== by 0xA8FC1EF: rb_inflate_inflate (zlib.c:2159)
==36376== by 0x31E36A: vm_call_cfunc_with_frame (vm_insnhelper.c:3045)
==36376== by 0x32ABF8: vm_call_method_each_type (vm_insnhelper.c:3647)
==36376== by 0x32B4C3: vm_call_method (vm_insnhelper.c:3758)
==36376== by 0x338B86: vm_sendish (vm_insnhelper.c:4759)
==36376== by 0x338B86: vm_exec_core (insns.def:758)
==36376== by 0x32A07C: rb_vm_exec (vm.c:2214)
==36376== by 0x13EB5A: rb_ec_exec_node (eval.c:280)
==36376== Address 0xb110050 is 16 bytes inside an unallocated block of size 1,048,912 in arena "client"
The script does not crash on Ruby master, but crashes on 3.0.2, 2.7.4, 2.6.8.
Redmine ticket: https://bugs.ruby-lang.org/issues/18358
zlib has a use-after-free when
Zlib::Inflate#inflate
orZlib::Deflate#deflate
is called recursively. The following script demonstrates the issue.If we run Ruby master (commit b680b632e5b88e4ea550de3f15cf6ef782efeb48) with Valgrind, we see use-after-free errors:
The script does not crash on Ruby master, but crashes on 3.0.2, 2.7.4, 2.6.8.