From 5827d8e887d881eb3a6e6ea7410590261c90545f Mon Sep 17 00:00:00 2001 From: nagachika Date: Mon, 25 Apr 2016 18:06:57 +0000 Subject: [PATCH 1/2] add tag v2_3_1 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v2_3_1@54768 b2dd03c8-39d4-4d8f-98ff-823fe69b080e From a992d79f56ad6107e72d279343766f0154f90183 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 22 Nov 2016 14:31:17 -0800 Subject: [PATCH 2/2] 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 --- variable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variable.c b/variable.c index 79e4c8d5303c4f..af4ab16a3c0828 100644 --- a/variable.c +++ b/variable.c @@ -1605,7 +1605,7 @@ rb_ivar_count(VALUE obj) 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) {