Look up constant instead of caching in a global

The global can go bad if the compactor runs, so we need to look up the
constant instead of caching it in a global.
This commit is contained in:
Aaron Patterson 2019-10-17 13:30:09 -07:00
Родитель ee821e9074
Коммит 9026e12f93
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 953170BCB4FFAFC6
2 изменённых файлов: 40 добавлений и 6 удалений

Просмотреть файл

@ -15,7 +15,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
#endif #endif
mFloat, mString, mString_Extend, mFloat, mString, mString_Extend,
mTrueClass, mFalseClass, mNilClass, eGeneratorError, mTrueClass, mFalseClass, mNilClass, eGeneratorError,
eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE, eNestingError, CRegexp_MULTILINE,
i_SAFE_STATE_PROTOTYPE; i_SAFE_STATE_PROTOTYPE;
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before, static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
@ -1082,10 +1082,8 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
} else if (rb_obj_is_kind_of(opts, rb_cHash)) { } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
return rb_funcall(self, i_new, 1, opts); return rb_funcall(self, i_new, 1, opts);
} else { } else {
if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) { VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE); return rb_funcall(prototype, i_dup, 0);
}
return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
} }
} }
@ -1499,5 +1497,4 @@ void Init_generator(void)
i_encode = rb_intern("encode"); i_encode = rb_intern("encode");
#endif #endif
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE"); i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
CJSON_SAFE_STATE_PROTOTYPE = Qnil;
} }

Просмотреть файл

@ -40,6 +40,43 @@ class JSONGeneratorTest < Test::Unit::TestCase
EOT EOT
end end
def silence
v = $VERBOSE
$VERBOSE = nil
yield
ensure
$VERBOSE = v
end
def test_remove_const_segv
stress = GC.stress
const = JSON::SAFE_STATE_PROTOTYPE.dup
bignum_too_long_to_embed_as_string = 1234567890123456789012345
expect = bignum_too_long_to_embed_as_string.to_s
GC.stress = true
10.times do |i|
tmp = bignum_too_long_to_embed_as_string.to_json
raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
end
silence do
JSON.const_set :SAFE_STATE_PROTOTYPE, nil
end
10.times do |i|
assert_raise TypeError do
bignum_too_long_to_embed_as_string.to_json
end
end
ensure
GC.stress = stress
silence do
JSON.const_set :SAFE_STATE_PROTOTYPE, const
end
end
def test_generate def test_generate
json = generate(@hash) json = generate(@hash)
assert_equal(parse(@json2), parse(json)) assert_equal(parse(@json2), parse(json))