ruby-changes:44865
From: tenderlove <ko1@a...>
Date: Wed, 30 Nov 2016 02:06:40 +0900 (JST)
Subject: [ruby-changes:44865] tenderlove:r56938 (trunk): Stop reading past the end of `ivptr` array
tenderlove 2016-11-30 02:06:35 +0900 (Wed, 30 Nov 2016) New Revision: 56938 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=56938 Log: Stop reading past the end of `ivptr` array If you have code like this: ```ruby class A def initialize @a = nil @b = nil @c = nil @d = nil @e = nil end end x = A.new y = x.clone 100.times { |z| x.instance_variable_set(:"@foo#{z}", nil) } puts y.inspect ``` `x` and `y` will share `iv_index_tbl` hashes. However, the size of the hash will grow larger than the number if entries in `ivptr` in `y`. Before this commit, `rb_ivar_count` would use the size of the hash to determine how far to read in to the array, but this means that it could read past the end of the array and cause the program to segv [ruby-core:78403] Modified files: trunk/variable.c Index: variable.c =================================================================== --- variable.c (revision 56937) +++ variable.c (revision 56938) @@ -1619,7 +1619,7 @@ rb_ivar_count(VALUE obj) https://github.com/ruby/ruby/blob/trunk/variable.c#L1619 switch (BUILTIN_TYPE(obj)) { case T_OBJECT: if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) { - st_index_t i, count, num = tbl->num_entries; + st_index_t i, count, num = ROBJECT_NUMIV(obj); const VALUE *const ivptr = ROBJECT_IVPTR(obj); for (i = count = 0; i < num; ++i) { if (ivptr[i] != Qundef) { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/