aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-11-29 17:06:35 +0000
committertenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-11-29 17:06:35 +0000
commitfaf7a07f06c4e66b3c5b728452a925761e16190f (patch)
tree1de48d14e0ea3bcdda4eb1f8ca410a5138ff8a29
parent6783f4c1b1d3536ca92421f0526c510cc3e1ab51 (diff)
downloadruby-faf7a07f06c4e66b3c5b728452a925761e16190f.tar.gz
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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56938 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--variable.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/variable.c b/variable.c
index e9245050d3..91482e9d0f 100644
--- a/variable.c
+++ b/variable.c
@@ -1619,7 +1619,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) {