зеркало из https://github.com/github/ruby.git
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:
Родитель
ee821e9074
Коммит
9026e12f93
|
@ -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))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче