[前][次][番号順一覧][スレッド一覧]

ruby-changes:58301

From: Aaron <ko1@a...>
Date: Fri, 18 Oct 2019 05:30:40 +0900 (JST)
Subject: [ruby-changes:58301] 9026e12f93 (master): Look up constant instead of caching in a global

https://git.ruby-lang.org/ruby.git/commit/?id=9026e12f93

From 9026e12f93bb0f3f63d7449cdb5eabb2e660088f Mon Sep 17 00:00:00 2001
From: Aaron Patterson <tenderlove@r...>
Date: Thu, 17 Oct 2019 13:30:09 -0700
Subject: 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.

diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index 443b4d3..e996161 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -15,7 +15,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject, https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L15
 #endif
              mFloat, mString, mString_Extend,
              mTrueClass, mFalseClass, mNilClass, eGeneratorError,
-             eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
+             eNestingError, CRegexp_MULTILINE,
              i_SAFE_STATE_PROTOTYPE;
 
 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) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L1082
     } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
         return rb_funcall(self, i_new, 1, opts);
     } else {
-        if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
-            CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
-        }
-        return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
+        VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
+        return rb_funcall(prototype, i_dup, 0);
     }
 }
 
@@ -1499,5 +1497,4 @@ void Init_generator(void) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L1497
     i_encode = rb_intern("encode");
 #endif
     i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
-    CJSON_SAFE_STATE_PROTOTYPE = Qnil;
 }
diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb
index d7f9ebe..3d9ab7a 100644
--- a/test/json/json_generator_test.rb
+++ b/test/json/json_generator_test.rb
@@ -40,6 +40,43 @@ class JSONGeneratorTest < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/json/json_generator_test.rb#L40
 EOT
   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
     json = generate(@hash)
     assert_equal(parse(@json2), parse(json))
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]