summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSHIBATA Hiroshi <hsbt@ruby-lang.org>2019-11-29 12:36:34 +0900
committerGitHub <noreply@github.com>2019-11-29 12:36:34 +0900
commite5e9a7781831bc3acd48854cd860e92b53c568f0 (patch)
tree1bf19e0ce81082598ffb3feb0f693dff31693a6a
parent8d8e1aa70297d55034e3f6a4ce2f32300294b2a4 (diff)
parent5a28298e4f4cbaaadc3fda8a25b4567becb685c0 (diff)
downloadjson-e5e9a7781831bc3acd48854cd860e92b53c568f0.tar.gz
Merge pull request #388 from flori/backport-ruby-core
Backport ruby core changes
-rw-r--r--ext/json/ext/generator/generator.c25
-rw-r--r--ext/json/ext/parser/parser.c15
-rw-r--r--ext/json/ext/parser/parser.rl13
-rw-r--r--json.gemspecbin5439 -> 4425 bytes
-rw-r--r--lib/json/common.rb4
-rw-r--r--tests/json_common_interface_test.rb6
-rw-r--r--tests/json_generator_test.rb43
-rw-r--r--tests/json_parser_test.rb28
8 files changed, 99 insertions, 35 deletions
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index cc8c3a7..881435e 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -15,7 +15,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
#endif
mFloat, mString, mString_Extend,
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
- eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
+ eNestingError,
i_SAFE_STATE_PROTOTYPE;
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
@@ -696,7 +696,7 @@ static VALUE cState_aref(VALUE self, VALUE name)
if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
return rb_funcall(self, i_send, 1, name);
} else {
- return rb_ivar_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
+ return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
}
}
@@ -846,11 +846,20 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
fbuffer_append_char(buffer, ']');
}
+#ifdef HAVE_RUBY_ENCODING_H
+static int enc_utf8_compatible_p(rb_encoding *enc)
+{
+ if (enc == rb_usascii_encoding()) return 1;
+ if (enc == rb_utf8_encoding()) return 1;
+ return 0;
+}
+#endif
+
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
{
fbuffer_append_char(buffer, '"');
#ifdef HAVE_RUBY_ENCODING_H
- if (!rb_enc_str_asciicompat_p(obj)) {
+ if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
obj = rb_str_encode(obj, CEncoding_UTF_8, 0, Qnil);
}
#endif
@@ -1073,10 +1082,8 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
} 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);
}
}
@@ -1392,6 +1399,8 @@ void Init_generator(void)
eGeneratorError = rb_path2class("JSON::GeneratorError");
eNestingError = rb_path2class("JSON::NestingError");
+ rb_gc_register_mark_object(eGeneratorError);
+ rb_gc_register_mark_object(eNestingError);
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
rb_define_alloc_func(cState, cState_s_allocate);
@@ -1457,7 +1466,6 @@ void Init_generator(void)
mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
- CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
i_to_s = rb_intern("to_s");
i_to_json = rb_intern("to_json");
i_new = rb_intern("new");
@@ -1488,5 +1496,4 @@ void Init_generator(void)
i_encode = rb_intern("encode");
#endif
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
- CJSON_SAFE_STATE_PROTOTYPE = Qnil;
}
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
index 63b895e..0f98cf9 100644
--- a/ext/json/ext/parser/parser.c
+++ b/ext/json/ext/parser/parser.c
@@ -1,4 +1,4 @@
-
+/* This file is automatically generated from parser.rl by using ragel */
#line 1 "parser.rl"
#include "../fbuffer/fbuffer.h"
#include "parser.h"
@@ -27,7 +27,7 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
/* unicode */
-static const char digit_values[256] = {
+static const signed char digit_values[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
@@ -46,7 +46,7 @@ static const char digit_values[256] = {
static UTF32 unescape_unicode(const unsigned char *p)
{
- char b;
+ signed char b;
UTF32 result = 0;
b = digit_values[p[0]];
if (b < 0) return UNI_REPLACEMENT_CHAR;
@@ -1833,7 +1833,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
} else {
json->max_nesting = 100;
json->allow_nan = 0;
- json->create_additions = 1;
+ json->create_additions = 0;
json->create_id = rb_funcall(mJSON, i_create_id, 0);
json->object_class = Qnil;
json->array_class = Qnil;
@@ -2089,14 +2089,21 @@ void Init_parser(void)
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
eParserError = rb_path2class("JSON::ParserError");
eNestingError = rb_path2class("JSON::NestingError");
+ rb_gc_register_mark_object(eParserError);
+ rb_gc_register_mark_object(eNestingError);
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
rb_define_method(cParser, "initialize", cParser_initialize, -1);
rb_define_method(cParser, "parse", cParser_parse, 0);
rb_define_method(cParser, "source", cParser_source, 0);
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
+ rb_gc_register_mark_object(CNaN);
+
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
+ rb_gc_register_mark_object(CInfinity);
+
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
+ rb_gc_register_mark_object(CMinusInfinity);
i_json_creatable_p = rb_intern("json_creatable?");
i_json_create = rb_intern("json_create");
diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
index e7738d6..6b38bb2 100644
--- a/ext/json/ext/parser/parser.rl
+++ b/ext/json/ext/parser/parser.rl
@@ -25,7 +25,7 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
/* unicode */
-static const char digit_values[256] = {
+static const signed char digit_values[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
@@ -44,7 +44,7 @@ static const char digit_values[256] = {
static UTF32 unescape_unicode(const unsigned char *p)
{
- char b;
+ signed char b;
UTF32 result = 0;
b = digit_values[p[0]];
if (b < 0) return UNI_REPLACEMENT_CHAR;
@@ -728,7 +728,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
} else {
json->max_nesting = 100;
json->allow_nan = 0;
- json->create_additions = 1;
+ json->create_additions = 0;
json->create_id = rb_funcall(mJSON, i_create_id, 0);
json->object_class = Qnil;
json->array_class = Qnil;
@@ -849,14 +849,21 @@ void Init_parser(void)
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
eParserError = rb_path2class("JSON::ParserError");
eNestingError = rb_path2class("JSON::NestingError");
+ rb_gc_register_mark_object(eParserError);
+ rb_gc_register_mark_object(eNestingError);
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
rb_define_method(cParser, "initialize", cParser_initialize, -1);
rb_define_method(cParser, "parse", cParser_parse, 0);
rb_define_method(cParser, "source", cParser_source, 0);
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
+ rb_gc_register_mark_object(CNaN);
+
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
+ rb_gc_register_mark_object(CInfinity);
+
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
+ rb_gc_register_mark_object(CMinusInfinity);
i_json_creatable_p = rb_intern("json_creatable?");
i_json_create = rb_intern("json_create");
diff --git a/json.gemspec b/json.gemspec
index 6e7873f..51dd8f0 100644
--- a/json.gemspec
+++ b/json.gemspec
Binary files differ
diff --git a/lib/json/common.rb b/lib/json/common.rb
index 7cc8529..3be9fd8 100644
--- a/lib/json/common.rb
+++ b/lib/json/common.rb
@@ -153,7 +153,7 @@ module JSON
# * *object_class*: Defaults to Hash
# * *array_class*: Defaults to Array
def parse(source, opts = {})
- Parser.new(source, opts).parse
+ Parser.new(source, **(opts||{})).parse
end
# Parse the JSON document _source_ into a Ruby data structure and return it.
@@ -176,7 +176,7 @@ module JSON
:max_nesting => false,
:allow_nan => true
}.merge(opts)
- Parser.new(source, opts).parse
+ Parser.new(source, **(opts||{})).parse
end
# Generate a JSON document from the Ruby data structure _obj_ and return
diff --git a/tests/json_common_interface_test.rb b/tests/json_common_interface_test.rb
index de88c6e..53f335e 100644
--- a/tests/json_common_interface_test.rb
+++ b/tests/json_common_interface_test.rb
@@ -27,15 +27,15 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
end
def test_parser
- assert_match /::Parser\z/, JSON.parser.name
+ assert_match(/::Parser\z/, JSON.parser.name)
end
def test_generator
- assert_match /::Generator\z/, JSON.generator.name
+ assert_match(/::Generator\z/, JSON.generator.name)
end
def test_state
- assert_match /::Generator::State\z/, JSON.state.name
+ assert_match(/::Generator::State\z/, JSON.state.name)
end
def test_create_id
diff --git a/tests/json_generator_test.rb b/tests/json_generator_test.rb
index 86be398..10cbcd1 100644
--- a/tests/json_generator_test.rb
+++ b/tests/json_generator_test.rb
@@ -40,6 +40,43 @@ class JSONGeneratorTest < Test::Unit::TestCase
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 if JSON.const_defined?("Ext")
+
def test_generate
json = generate(@hash)
assert_equal(parse(@json2), parse(json))
@@ -374,4 +411,10 @@ EOT
assert_equal '["foo"]', JSON.generate([s.new('foo')])
end
end
+
+ if defined?(Encoding)
+ def test_nonutf8_encoding
+ assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
+ end
+ end
end
diff --git a/tests/json_parser_test.rb b/tests/json_parser_test.rb
index 5f454eb..9946dd9 100644
--- a/tests/json_parser_test.rb
+++ b/tests/json_parser_test.rb
@@ -91,27 +91,27 @@ class JSONParserTest < Test::Unit::TestCase
assert_raise(JSON::ParserError) { parse('+23') }
assert_raise(JSON::ParserError) { parse('.23') }
assert_raise(JSON::ParserError) { parse('023') }
- assert_equal 23, parse('23')
- assert_equal -23, parse('-23')
- assert_equal_float 3.141, parse('3.141')
- assert_equal_float -3.141, parse('-3.141')
- assert_equal_float 3.141, parse('3141e-3')
- assert_equal_float 3.141, parse('3141.1e-3')
- assert_equal_float 3.141, parse('3141E-3')
- assert_equal_float 3.141, parse('3141.0E-3')
- assert_equal_float -3.141, parse('-3141.0e-3')
- assert_equal_float -3.141, parse('-3141e-3')
+ assert_equal(23, parse('23'))
+ assert_equal(-23, parse('-23'))
+ assert_equal_float(3.141, parse('3.141'))
+ assert_equal_float(-3.141, parse('-3.141'))
+ assert_equal_float(3.141, parse('3141e-3'))
+ assert_equal_float(3.141, parse('3141.1e-3'))
+ assert_equal_float(3.141, parse('3141E-3'))
+ assert_equal_float(3.141, parse('3141.0E-3'))
+ assert_equal_float(-3.141, parse('-3141.0e-3'))
+ assert_equal_float(-3.141, parse('-3141e-3'))
assert_raise(ParserError) { parse('NaN') }
assert parse('NaN', :allow_nan => true).nan?
assert_raise(ParserError) { parse('Infinity') }
- assert_equal 1.0/0, parse('Infinity', :allow_nan => true)
+ assert_equal(1.0/0, parse('Infinity', :allow_nan => true))
assert_raise(ParserError) { parse('-Infinity') }
- assert_equal -1.0/0, parse('-Infinity', :allow_nan => true)
+ assert_equal(-1.0/0, parse('-Infinity', :allow_nan => true))
end
def test_parse_bigdecimals
- assert_equal(BigDecimal, JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"].class)
- assert_equal(BigDecimal.new("0.901234567890123456789E1"),JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"] )
+ assert_equal(BigDecimal, JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"].class)
+ assert_equal(BigDecimal("0.901234567890123456789E1"),JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"] )
end
if Array.method_defined?(:permutation)