Skip to content

Commit e5e9a77

Browse files
authored
Merge pull request #388 from flori/backport-ruby-core
Backport ruby core changes
2 parents 8d8e1aa + 5a28298 commit e5e9a77

8 files changed

Lines changed: 99 additions & 35 deletions

File tree

ext/json/ext/generator/generator.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
1515
#endif
1616
mFloat, mString, mString_Extend,
1717
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
18-
eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
18+
eNestingError,
1919
i_SAFE_STATE_PROTOTYPE;
2020

2121
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)
696696
if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
697697
return rb_funcall(self, i_send, 1, name);
698698
} else {
699-
return rb_ivar_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
699+
return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
700700
}
701701
}
702702

@@ -846,11 +846,20 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
846846
fbuffer_append_char(buffer, ']');
847847
}
848848

849+
#ifdef HAVE_RUBY_ENCODING_H
850+
static int enc_utf8_compatible_p(rb_encoding *enc)
851+
{
852+
if (enc == rb_usascii_encoding()) return 1;
853+
if (enc == rb_utf8_encoding()) return 1;
854+
return 0;
855+
}
856+
#endif
857+
849858
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
850859
{
851860
fbuffer_append_char(buffer, '"');
852861
#ifdef HAVE_RUBY_ENCODING_H
853-
if (!rb_enc_str_asciicompat_p(obj)) {
862+
if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
854863
obj = rb_str_encode(obj, CEncoding_UTF_8, 0, Qnil);
855864
}
856865
#endif
@@ -1073,10 +1082,8 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
10731082
} else if (rb_obj_is_kind_of(opts, rb_cHash)) {
10741083
return rb_funcall(self, i_new, 1, opts);
10751084
} else {
1076-
if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
1077-
CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
1078-
}
1079-
return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
1085+
VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
1086+
return rb_funcall(prototype, i_dup, 0);
10801087
}
10811088
}
10821089

@@ -1392,6 +1399,8 @@ void Init_generator(void)
13921399

13931400
eGeneratorError = rb_path2class("JSON::GeneratorError");
13941401
eNestingError = rb_path2class("JSON::NestingError");
1402+
rb_gc_register_mark_object(eGeneratorError);
1403+
rb_gc_register_mark_object(eNestingError);
13951404

13961405
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
13971406
rb_define_alloc_func(cState, cState_s_allocate);
@@ -1457,7 +1466,6 @@ void Init_generator(void)
14571466
mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
14581467
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
14591468

1460-
CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
14611469
i_to_s = rb_intern("to_s");
14621470
i_to_json = rb_intern("to_json");
14631471
i_new = rb_intern("new");
@@ -1488,5 +1496,4 @@ void Init_generator(void)
14881496
i_encode = rb_intern("encode");
14891497
#endif
14901498
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
1491-
CJSON_SAFE_STATE_PROTOTYPE = Qnil;
14921499
}

ext/json/ext/parser/parser.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
/* This file is automatically generated from parser.rl by using ragel */
22
#line 1 "parser.rl"
33
#include "../fbuffer/fbuffer.h"
44
#include "parser.h"
@@ -27,7 +27,7 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
2727

2828
/* unicode */
2929

30-
static const char digit_values[256] = {
30+
static const signed char digit_values[256] = {
3131
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3232
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3333
-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] = {
4646

4747
static UTF32 unescape_unicode(const unsigned char *p)
4848
{
49-
char b;
49+
signed char b;
5050
UTF32 result = 0;
5151
b = digit_values[p[0]];
5252
if (b < 0) return UNI_REPLACEMENT_CHAR;
@@ -1833,7 +1833,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
18331833
} else {
18341834
json->max_nesting = 100;
18351835
json->allow_nan = 0;
1836-
json->create_additions = 1;
1836+
json->create_additions = 0;
18371837
json->create_id = rb_funcall(mJSON, i_create_id, 0);
18381838
json->object_class = Qnil;
18391839
json->array_class = Qnil;
@@ -2089,14 +2089,21 @@ void Init_parser(void)
20892089
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
20902090
eParserError = rb_path2class("JSON::ParserError");
20912091
eNestingError = rb_path2class("JSON::NestingError");
2092+
rb_gc_register_mark_object(eParserError);
2093+
rb_gc_register_mark_object(eNestingError);
20922094
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
20932095
rb_define_method(cParser, "initialize", cParser_initialize, -1);
20942096
rb_define_method(cParser, "parse", cParser_parse, 0);
20952097
rb_define_method(cParser, "source", cParser_source, 0);
20962098

20972099
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
2100+
rb_gc_register_mark_object(CNaN);
2101+
20982102
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
2103+
rb_gc_register_mark_object(CInfinity);
2104+
20992105
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
2106+
rb_gc_register_mark_object(CMinusInfinity);
21002107

21012108
i_json_creatable_p = rb_intern("json_creatable?");
21022109
i_json_create = rb_intern("json_create");

ext/json/ext/parser/parser.rl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
2525

2626
/* unicode */
2727

28-
static const char digit_values[256] = {
28+
static const signed char digit_values[256] = {
2929
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3030
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3131
-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] = {
4444

4545
static UTF32 unescape_unicode(const unsigned char *p)
4646
{
47-
char b;
47+
signed char b;
4848
UTF32 result = 0;
4949
b = digit_values[p[0]];
5050
if (b < 0) return UNI_REPLACEMENT_CHAR;
@@ -728,7 +728,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
728728
} else {
729729
json->max_nesting = 100;
730730
json->allow_nan = 0;
731-
json->create_additions = 1;
731+
json->create_additions = 0;
732732
json->create_id = rb_funcall(mJSON, i_create_id, 0);
733733
json->object_class = Qnil;
734734
json->array_class = Qnil;
@@ -849,14 +849,21 @@ void Init_parser(void)
849849
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
850850
eParserError = rb_path2class("JSON::ParserError");
851851
eNestingError = rb_path2class("JSON::NestingError");
852+
rb_gc_register_mark_object(eParserError);
853+
rb_gc_register_mark_object(eNestingError);
852854
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
853855
rb_define_method(cParser, "initialize", cParser_initialize, -1);
854856
rb_define_method(cParser, "parse", cParser_parse, 0);
855857
rb_define_method(cParser, "source", cParser_source, 0);
856858

857859
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
860+
rb_gc_register_mark_object(CNaN);
861+
858862
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
863+
rb_gc_register_mark_object(CInfinity);
864+
859865
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
866+
rb_gc_register_mark_object(CMinusInfinity);
860867

861868
i_json_creatable_p = rb_intern("json_creatable?");
862869
i_json_create = rb_intern("json_create");

json.gemspec

-1014 Bytes
Binary file not shown.

lib/json/common.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class MissingUnicodeSupport < JSONError; end
153153
# * *object_class*: Defaults to Hash
154154
# * *array_class*: Defaults to Array
155155
def parse(source, opts = {})
156-
Parser.new(source, opts).parse
156+
Parser.new(source, **(opts||{})).parse
157157
end
158158

159159
# Parse the JSON document _source_ into a Ruby data structure and return it.
@@ -176,7 +176,7 @@ def parse!(source, opts = {})
176176
:max_nesting => false,
177177
:allow_nan => true
178178
}.merge(opts)
179-
Parser.new(source, opts).parse
179+
Parser.new(source, **(opts||{})).parse
180180
end
181181

182182
# Generate a JSON document from the Ruby data structure _obj_ and return

tests/json_common_interface_test.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ def test_index
2727
end
2828

2929
def test_parser
30-
assert_match /::Parser\z/, JSON.parser.name
30+
assert_match(/::Parser\z/, JSON.parser.name)
3131
end
3232

3333
def test_generator
34-
assert_match /::Generator\z/, JSON.generator.name
34+
assert_match(/::Generator\z/, JSON.generator.name)
3535
end
3636

3737
def test_state
38-
assert_match /::Generator::State\z/, JSON.state.name
38+
assert_match(/::Generator::State\z/, JSON.state.name)
3939
end
4040

4141
def test_create_id

tests/json_generator_test.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,43 @@ def setup
4040
EOT
4141
end
4242

43+
def silence
44+
v = $VERBOSE
45+
$VERBOSE = nil
46+
yield
47+
ensure
48+
$VERBOSE = v
49+
end
50+
51+
def test_remove_const_segv
52+
stress = GC.stress
53+
const = JSON::SAFE_STATE_PROTOTYPE.dup
54+
55+
bignum_too_long_to_embed_as_string = 1234567890123456789012345
56+
expect = bignum_too_long_to_embed_as_string.to_s
57+
GC.stress = true
58+
59+
10.times do |i|
60+
tmp = bignum_too_long_to_embed_as_string.to_json
61+
raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
62+
end
63+
64+
silence do
65+
JSON.const_set :SAFE_STATE_PROTOTYPE, nil
66+
end
67+
68+
10.times do |i|
69+
assert_raise TypeError do
70+
bignum_too_long_to_embed_as_string.to_json
71+
end
72+
end
73+
ensure
74+
GC.stress = stress
75+
silence do
76+
JSON.const_set :SAFE_STATE_PROTOTYPE, const
77+
end
78+
end if JSON.const_defined?("Ext")
79+
4380
def test_generate
4481
json = generate(@hash)
4582
assert_equal(parse(@json2), parse(json))
@@ -374,4 +411,10 @@ def to_s; self; end
374411
assert_equal '["foo"]', JSON.generate([s.new('foo')])
375412
end
376413
end
414+
415+
if defined?(Encoding)
416+
def test_nonutf8_encoding
417+
assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
418+
end
419+
end
377420
end

tests/json_parser_test.rb

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,27 +91,27 @@ def test_parse_numbers
9191
assert_raise(JSON::ParserError) { parse('+23') }
9292
assert_raise(JSON::ParserError) { parse('.23') }
9393
assert_raise(JSON::ParserError) { parse('023') }
94-
assert_equal 23, parse('23')
95-
assert_equal -23, parse('-23')
96-
assert_equal_float 3.141, parse('3.141')
97-
assert_equal_float -3.141, parse('-3.141')
98-
assert_equal_float 3.141, parse('3141e-3')
99-
assert_equal_float 3.141, parse('3141.1e-3')
100-
assert_equal_float 3.141, parse('3141E-3')
101-
assert_equal_float 3.141, parse('3141.0E-3')
102-
assert_equal_float -3.141, parse('-3141.0e-3')
103-
assert_equal_float -3.141, parse('-3141e-3')
94+
assert_equal(23, parse('23'))
95+
assert_equal(-23, parse('-23'))
96+
assert_equal_float(3.141, parse('3.141'))
97+
assert_equal_float(-3.141, parse('-3.141'))
98+
assert_equal_float(3.141, parse('3141e-3'))
99+
assert_equal_float(3.141, parse('3141.1e-3'))
100+
assert_equal_float(3.141, parse('3141E-3'))
101+
assert_equal_float(3.141, parse('3141.0E-3'))
102+
assert_equal_float(-3.141, parse('-3141.0e-3'))
103+
assert_equal_float(-3.141, parse('-3141e-3'))
104104
assert_raise(ParserError) { parse('NaN') }
105105
assert parse('NaN', :allow_nan => true).nan?
106106
assert_raise(ParserError) { parse('Infinity') }
107-
assert_equal 1.0/0, parse('Infinity', :allow_nan => true)
107+
assert_equal(1.0/0, parse('Infinity', :allow_nan => true))
108108
assert_raise(ParserError) { parse('-Infinity') }
109-
assert_equal -1.0/0, parse('-Infinity', :allow_nan => true)
109+
assert_equal(-1.0/0, parse('-Infinity', :allow_nan => true))
110110
end
111111

112112
def test_parse_bigdecimals
113-
assert_equal(BigDecimal, JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"].class)
114-
assert_equal(BigDecimal.new("0.901234567890123456789E1"),JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"] )
113+
assert_equal(BigDecimal, JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"].class)
114+
assert_equal(BigDecimal("0.901234567890123456789E1"),JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"] )
115115
end
116116

117117
if Array.method_defined?(:permutation)

0 commit comments

Comments
 (0)